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.
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. 🥺
:
Bearbeitet durch User
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 vom Autor 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.
:
Bearbeitet durch User
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?
:
Bearbeitet durch User
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.
:
Bearbeitet durch User
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.
:
Bearbeitet durch User
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...
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.