Das hat sicher schon einer gemacht...
Also, mir hat Java und WebAssembly nicht so gefallen und da dachte ich
mir, ich mache nur eine VM und irgendwann ein LLVM Plugin.
Kann mir bitte einer sagen, ob das jetzt gleich in den Abfall kann? Sind
halt entwurfstechnisch zwei Byte pro Instruktion 💩
https://github.com/ykat-UG-haftungsbeschrankt/agilertos/blob/main/zrtos_script.h
Dein Code enthält Bezeichner wie "zrtos_clist__each", also mit zwei
Unterstrichen in der Mitte. In C ist das erlaubt, in C++ aber nicht
(reserviert für die Implementation). Sollte es also entfernt die
Möglichkeit geben, dass man den Code in C++ einbindet, müsstest du das
ändern.
Christoph M. schrieb:
> 404 page not found.
Ihm hat bestimmt die Patentanmeldung, vor der Veröffentlichung,
vergessen.
Sieht so aus, als ob einfach die Datei umbenannt wurde.
Daniel A. schrieb:
> Sieht so aus, als ob einfach die Datei umbenannt wurde.
Ja, hab die Datei umbenannt, da es doch eher eine VM als ein Script
wurde.
https://github.com/ykat-UG-haftungsbeschrankt/agilertos/blob/main/zrtos_vm.h
Niklas G. schrieb:
> Dein Code enthält Bezeichner wie "zrtos_clist__each", also mit zwei
> Unterstrichen in der Mitte. In C ist das erlaubt, in C++ aber nicht
> (reserviert für die Implementation). Sollte es also entfernt die
> Möglichkeit geben, dass man den Code in C++ einbindet, müsstest du das
> ändern.
Danke, das wusste ich nicht! Muss mal nachlesen, ob das auch in einem
extern "C" kollidieren kann...
Man kann das schon alles in zrtosClist_each ändern, aber da sehe ich
nach einer durchgezechten Nacht nur noch Buchstabensalat.
_ am Anfang und _t am Ende ist eigentlich auch reserviert. Ist halt eine
schlechte Angewohnheit von mir. 🥺
Matthias schrieb:
> Danke, das wusste ich nicht! Muss mal nachlesen, ob das auch in einem
> extern "C" kollidieren kann...
Ja, in extern "C" kommt ja kein C rein, sondern C++. Also gelten da auch
die C++ Regeln.
Beitrag #7673005 wurde von einem Moderator gelöscht.
Niklas G. schrieb:
> Matthias schrieb:
>> Danke, das wusste ich nicht! Muss mal nachlesen, ob das auch in einem
>> extern "C" kollidieren kann...
>
> Ja, in extern "C" kommt ja kein C rein, sondern C++. Also gelten da auch
> die C++ Regeln.
Hast Recht.
Scheinbar verwenden aber die C++ Compiler intern ^_[A-Z] für die
identifier damit das nicht mit den alten C Quelltexten kollidiert.
Man müsste aus dem Schneider sein, wenn man auf ^__* und ^_[A-Z]
verzichtet.
Da muss ich tatsächlich nacharbeiten.
Wenn das einer kommerziell einsetzen will und sich an den __ stört und
auf Nummer sicher gehen will, kann ich das schon in paar Tagen
umschreiben 😇
Matthias schrieb:
> Wenn das einer kommerziell einsetzen will
LOL, als ob das überhaupt jemand einsetzen will.
Open Source (nach OSI) sowie Freie Software Nutzer werden es meiden,
weil nicht Open Source / Freie Software. Und kommerzielle dürfen es
nicht einsetzen, müssten also erst mit dir verhandeln. Gleichzeitig
können die das auch selber, und es gibt auch schon längst fertige & weit
verbreitete RTOS, die sogar Open Source sind, auch mit Support Angeboten
usw.
Die einzigen die das Nutzen werden Microsoft sein um ihr CoPilot zu
trainieren.
Matthias schrieb:
> Also, mir hat Java und WebAssembly nicht so gefallen und da dachte ich
> mir, ich mache nur eine VM und irgendwann ein LLVM Plugin.
Also, du machst dir eine VM, die deinen eigenen Bytecode ausführt. Kein
statischer Recompiler wie bei WASM möglich, und nicht einmal als JIT
umgesetzt. Und du willst später mit LLVM code dafür generieren, den du
dank LLVM auch gleich für deine native Plattform hättest generieren
lassen können?
Was genau soll das bringen?
Naja, zumindest eine gute Übung um Erfahrung zu sammeln ist es.
Daniel A. schrieb:
> LOL, als ob das überhaupt jemand einsetzen will.
Tja, er hat in ziemlich kurzer Zeit einen relativ vollständigen
grundlegenden Scheduler geschrieben. Das ist von Kompetenz und
Produktivität her schon ziemlich gut. Allerdings halt für AVR - der
Markt für RTOSe für AVR dürfte ziemlich klein sein. Der für
Bytecode-Interpreter für AVR noch kleiner. Aber es gibt sogar Leute die
für Basic-Compiler Geld ausgeben, also wer weiß.
Der gezeigte Bytecode ist allerdings ziemlich minimalistisch, ob man
damit wirklich eine geringere Codegröße als mit AVR-Opcodes oder auch
ARM (Thumb) hinbekommt? Dazu bräuchte man direkte Integration von
High-Level-Operationen, z.B. String-Operationen, direkten Zugriff auf
Klassenmember/Funktionen ähnlich wie JVM, weil dieses Geschnippsel auf
Maschinencode-Ebene schon einigen Platz wegnimmt.
Mit etwas mehr Gespür dafür, was der Markt braucht, kann das schon eher
was werden. Wie wärs mit Unterstützung RISC-V? Oder Xtensa (ESP32)?
Fokus auf IoT und Low-Power (tickless)? Direkte Integration von
Internetprotokollen? Das ist kommerziell eher interessant...
Warum ist eigentlich alles in Header-Files, selbst die main()-Funktion
in den examples?
Könnten schon, __ ist in C++ verboten, weil das intern vom Compiler
verwendet werden kann.
Angenommen man schreibt: 1 | test.a__b = test__a__b
| 2 | test__a.b = test__a__a
|
Dann hat man in C++ einen Namenskonflikt.
Der Namenskonflikt mit den alten C Quelltexten wird sehr sehr sicher
unabhängig davon durch die Nutzung des Namensraum _[A-Z0-9]+test__a__b
ausgeschlossen.
Ich habe das korrigiert, müsste jetzt passen.
Matthias schrieb:
> weil das intern vom Compiler
> verwendet werden kann.
Eher von der Standardbibliothek.
Matthias schrieb:
> Dann hat man in C++ einen Namenskonflikt.
Wahrscheinlich nicht. Moderne Compiler können prinzipiell beliebig lange
und beliebig aufgebaute Bezeichner verwenden (kein Limit auf 30 Zeichen
o.ä.). Die Tücke ist, solche Dinge funktionieren in 95% der Fälle
problemlos. Aber dann kommt in der nächsten Version des Compilers oder
der Standard-Bibliothek ein reservierter Bezeichner in dieser Form dazu,
und dann kompiliert der eigene Code nicht mehr (richtig). Die doppelten
Unterstriche innerhalb eines Bezeichners sind vermutlich verboten damit
implementationsspezifische Makros Bezeichner ohne Kollision
zusammenbauen können (offsetof oder so?).
Matthias schrieb:
> Ich habe das korrigiert, müsste jetzt passen.
Du hast immer noch doppelte Unterstriche... Der Name
"ZRTOS_ASSERT__STATIC" ist reserviert
Niklas G. schrieb:
> Matthias schrieb:
>> weil das intern vom Compiler
>> verwendet werden kann.
>
> Eher von der Standardbibliothek.
>
> Matthias schrieb:
>> Dann hat man in C++ einen Namenskonflikt.
>
> Wahrscheinlich nicht. Moderne Compiler können prinzipiell beliebig lange
> und beliebig aufgebaute Bezeichner verwenden (kein Limit auf 30 Zeichen
> o.ä.). Die Tücke ist, solche Dinge funktionieren in 95% der Fälle
> problemlos. Aber dann kommt in der nächsten Version des Compilers oder
> der Standard-Bibliothek ein reservierter Bezeichner in dieser Form dazu,
> und dann kompiliert der eigene Code nicht mehr (richtig). Die doppelten
> Unterstriche innerhalb eines Bezeichners sind vermutlich verboten damit
> implementationsspezifische Makros Bezeichner ohne Kollision
> zusammenbauen können (offsetof oder so?).
>
> Matthias schrieb:
>> Ich habe das korrigiert, müsste jetzt passen.
>
> Du hast immer noch doppelte Unterstriche... Der Name
> "ZRTOS_ASSERT__STATIC" ist reserviert
So natürlich... 1 | test.a__b = test__a__b
| 2 | test__a.b = test__a__b
|
Ja, kann sein. Aber C++ gibt es schon ewig und man hat da nicht alles
neu geschrieben, sondern nur Klassen um C gebaut. Trotzdem ist da nie
was eingestürzt.
Auch gibt es keinen C++ Standard für C Programmierer. Die können sich
freiwillig, oder wenn vom Auftraggeber gefordert, an C++
Namenskonventionen halten, müssen das aber eigentlich nicht.
Sry, ich muss meine Jalousien montieren. Mache da später wieder weiter!
Matthias schrieb:
> So natürlich...
Ist trotzdem wahrscheinlich unproblematisch... Bis der Compiler
"test__a__b" als reservierten Bezeichner einführt.
Matthias schrieb:
> Aber C++ gibt es schon ewig und man hat da nicht alles
> neu geschrieben, sondern nur Klassen um C gebaut.
Naja, viel C-Code ist extra so geschrieben dass er auch mit C++
funktioniert. Ich habe gesehen du hast ja auch extra das "this"-Keyword
vermieden.
Matthias schrieb:
> Trotzdem ist da nie
> was eingestürzt.
"Citation Needed". Der Linux-Kernel kann z.B. überhaupt nicht als C++
kompiliert werden.
Matthias schrieb:
> müssen das aber eigentlich nicht.
Es ist aber clever für Aufwärtskompatibilität. Besonders wenn man es
verkaufen möchte... Du kannst auch den RTOS-Code in C++ schreiben, das
funktioniert wunderbar, und erspart Arbeit.
Niklas G. schrieb:
> Dein Code enthält Bezeichner wie "zrtos_clist__each", also mit zwei
> Unterstrichen in der Mitte. In C ist das erlaubt, in C++ aber nicht
> (reserviert für die Implementation.
Hast du da einen Link, dass alle Bezeichner mit __ irgendwo im Namen im
Namespace der C++ Implementation sind?
Johann L. schrieb:
> Hast du da einen Link, dass alle Bezeichner mit __ irgendwo im Namen im
> Namespace der C++ Implementation sind?
https://en.cppreference.com/w/cpp/language/identifiers
> An identifier can be used to name objects, [...], and other entities, with the
following exceptions: [...]
> * Identifiers [...] of one of the following forms are reserved:
> * identifiers with a double underscore anywhere;
> * identifiers that begin with an underscore followed by an uppercase letter;
> in the global namespace, identifiers that begin with an underscore.
> If the programmer uses such identifiers, the program is ill-formed, no
diagnostic required.
Ok, danke. Bezieht sich das auch auf Macros? Dann gehörten auch Macros
beginnend mit nur einem _ zur Implementation.
Noch eine Anregung zur Config und den Includes.
Ich packe bei mir die Includes gerne in ein Unterverzeichnis: 1 | include/vendorprefix/someheader.h
|
Dann kann man das include Directory beim Kompilieren angeben: 1 | cc -Iinclude/ somefile.c
|
Dann kann man in somefile.c die Includes so handhaben: 1 | #include <vendorprefix/someheader.h>
|
Das ganze ist auch beim Installieren der headers nützlich. Unter Linux
z.B. kopiert man einfach `include/vendorprefix/.` nach
`/usr/include/vendorprefix/` oder `/usr/local/include/vendorprefix/`,
und das Include oben geht auch einfach per `cc somefile.c`, also ganz
ohne das -I.
Bei den Configs mache ich es oft so, dass ich in jeder Headerdatei
zuallererst die eine config.h einbinde.
In der habe ich in der Regel sowas in der Art: 1 | #ifndef VENDOR_PROJECT_CONFIG_H
| 2 | #define VENDOR_PROJECT_CONFIG_H
| 3 |
| 4 | // Where is the config? Has it been specified? Otherwise, can we search for it?
| 5 |
| 6 | #if !defined(CONFIG_FILE) && defined(__has_include)
| 7 | // Note: The following line mustn't be merged with the previous one
| 8 | #if __has_include(<config.h>)
| 9 | #define CONFIG_FILE <config.h>
| 10 | #endif
| 11 | #endif
| 12 |
| 13 | // Include the config
| 14 |
| 15 | #ifdef CONFIG_FILE
| 16 | #include CONFIG_FILE
| 17 | #endif
| 18 |
| 19 | // Defaults
| 20 |
| 21 | #ifndef SOME_OPTION
| 22 | #define SOME_OPTION default value
| 23 | #endif
| 24 |
| 25 | #endif
|
__has_include gibt es in C++, und in C seit C23 (wobei C23 noch noch
weit supportet ist, aber GCC und clang kannten es schon vorher als
extension).
Wenn der Compiler es unterstützt, kann man dann einfach eine config.h in
seinen include/ Ordner legen. Falls nicht, kann man es explizit mit `-D`
setzen, z.B. `cc -D'CONFIG_FILE="/absolute/path/to/config.h"' myfile.c`
oder `cc -I include/ -D'CONFIG_FILE=<config.h>' myfile.c`.
Hmm
https://github.com/ykat-UG-haftungsbeschrankt/agilertos/commits/main/ In
die Commit Logs sollte man schon was reinschreiben. Die sind wichtig,
wenn man später mal was suchen will.
Johann L. schrieb:
> Ok, danke. Bezieht sich das auch auf Macros?
Ich denke schon:
https://timsong-cpp.github.io/cppwp/n4950/lex.name#:character,underscore,in_identifier
> In addition, some identifiers appearing as a token or preprocessing-token are
reserved for use by C++ implementations
Weil es auch im preprocessing tokens geht, gilt das wohl auch für
Makros. Macht auch Sinn, denn Makros mit reservierten Namen können auch
fies mit Bezeichnern in der Standardbibliothek kollidieren.
Niklas G. schrieb:
> Es ist aber clever für Aufwärtskompatibilität. Besonders wenn man es
> verkaufen möchte... Du kannst auch den RTOS-Code in C++ schreiben, das
> funktioniert wunderbar, und erspart Arbeit.
Ich mache es erst mal fertig und dann muss das eh in die Arduino IDE und
mit dem C++ harmonieren.
Müsste eigentlich eine Kleinigkeit sein, die __ zu entfernen, da fast
alles mit zrtos_ anfängt.
Das Problem war, dass ich ohne Exception nicht aus dem Konstruktor raus
komme und dann hab ich das bleiben lassen.
Klar, wenn alles Singleton sind bzw. bei der Initialisierung kein Fehler
auftreten kann ist es wurscht....
Kennt sich einer mit den LLVM-Backend aus? Ich habe mich daran versucht,
aber das ganze Teil zu compilieren um da ein Backendplugin einzubauen
dauert fast einen halben Tag??
Also, wollte ich einfach das LLVM IR übersetzen. Geht das so auch oder
ist das dann so kompliziert, dass man doch lieber das als Backend
implementiert?
Leider habe ich keine Zeit mehr, weil die Bilanz und Steuererklärung
unbedingt fertig werden muss.
Hat da einer Lust drauf? Ist auch C++...
1 | #include <string>
| 2 | #include <iostream>
| 3 |
| 4 |
| 5 | //#include <llvm/ADT/OwningPtr.h>
| 6 | #include <llvm/Bitcode/BitcodeReader.h>
| 7 | #include <llvm/IR/LLVMContext.h>
| 8 | #include <llvm/IR/Module.h>
| 9 | #include <llvm/Support/FileSystem.h>
| 10 | #include <llvm/Support/MemoryBuffer.h>
| 11 | #include <llvm/Support/ManagedStatic.h>
| 12 | #include <llvm/Support/raw_ostream.h>
| 13 | //#include <llvm/Support/system_error.h>
| 14 | #include <llvm/Support/TargetSelect.h>
| 15 |
| 16 | using namespace llvm;
| 17 |
| 18 | int main()
| 19 | {
| 20 | // llvm::InitializeNativeTarget();
| 21 |
| 22 | // read byte-code from file
| 23 | auto Buffer = llvm::MemoryBuffer::getFile("./test.bc");
| 24 | if (Buffer.getError()){
| 25 | llvm::errs() << "test.bc not found\n";
| 26 | return -1;
| 27 | }
| 28 | auto MemoryBuffer = Buffer.get().get();
| 29 | // generate corresponding LLVM module
| 30 | llvm::LLVMContext Context;
| 31 | std::string ErrorMessage;
| 32 | auto Module = llvm::parseBitcodeFile(*MemoryBuffer, Context);
| 33 | if (! Module)
| 34 | {
| 35 | llvm::errs() << ErrorMessage << "\n";
| 36 | return -1;
| 37 | }
| 38 |
| 39 | // create JIT execution engine and setup JIT, no function is complied yet
| 40 | //llvm::OwningPtr<llvm::ExecutionEngine> EE(llvm::EngineBuilder(M).create());
| 41 |
| 42 | // retrieve the Function IR object that represents sum
| 43 | llvm::Function* SumFn = Module.get()->getFunction("main");
| 44 | std::cout << SumFn;
| 45 |
| 46 |
| 47 | for(auto &Global : Module->get()->getGlobalList()){
| 48 | std::cout << Global.getName().data();
| 49 | }
| 50 |
| 51 | for(auto &Function : Module->get()->getFunctionList()){
| 52 | std::cout << Function.getName().data();
| 53 | for(auto &Args : Function.args()){
| 54 | std::cout << Args.getName().data();
| 55 | //std::cout << Args.getType().;
| 56 | }
| 57 | }
| 58 | /*
| 59 | // trigger JIT compilation
| 60 | int(*Sum)(int, int) = (int(*)(int, int))EE->getPointerToFunction(SumFn);
| 61 |
| 62 | // call the original sum function via the JIT-compiled function
| 63 | int res = Sum(4, 5);
| 64 | llvm::outs() << "Sum result: " << res << "\n";
| 65 |
| 66 | // release the execution engine allocated memory that holds the function code
| 67 | EE->freeMachineCodeForFunction(SumFn);
| 68 | llvm::llvm_shutdown();
| 69 | */
| 70 | return 0;
| 71 | }
|
Btw. nicht wundern, wenn beim AgileRTOS bzw zRTOS nichts mehr vorwärts
geht. Mache bestimmt irgendwann weiter, gerade habe ich einfach nur
keine Zeit dafür.
Ist halt scheiße, wenn man alleine über zwei Fahrräder schieben muss...
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|