diff --git a/Makefile b/Makefile index ff14510..c26c6b5 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ OBJS = $(addsuffix .o,$(basename $(SRCS))) CC = gcc CXX = g++ -LD = ld +LD = g++ LEX=flex YACC=bison @@ -11,10 +11,12 @@ YACC=bison CFLAGS = -m32 -Dnullptr=0 ASFLAGS = CCFLAGS = -g -std=c11 -Wall -g -fno-stack-protector -ffreestanding -Iinclude -CXXFLAGS = -g -std=c++11 -Wall -g -fno-stack-protector -fno-exceptions -ffreestanding -Wno-unused-function -Iinclude -LDFLAGS = -g -melf_i386 -Tkernel.ld +CXXFLAGS = -g -std=c++11 -Wall -g -fno-stack-protector -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore -Wall -Wextra -ffreestanding -Wno-unused-function -Iinclude +LDFLAGS = -g -m32 -Tkernel.ld -kernel: $(OBJS) obj/tsvm.o obj/lex.yy.o obj/trainscript.tab.o +all: clean kernel + +kernel: $(OBJS) obj/tsvm.o obj/lex.yy.o obj/trainscript.tab.o obj/vm.o $(LD) $(LDFLAGS) -o $@ $(addprefix obj/, $(notdir $^)) %.o: %.c @@ -26,13 +28,16 @@ kernel: $(OBJS) obj/tsvm.o obj/lex.yy.o obj/trainscript.tab.o %.o: %.cpp $(CXX) $(CFLAGS) $(CXXFLAGS) -c -o $(addprefix obj/, $(notdir $@)) $^ -obj/tsvm.o: trainscript/tsvm.cpp trainscript/tsvm.hpp trainscript/common.h +obj/vm.o: src/vm.cpp trainscript/tsvm.hpp + g++ $(CFLAGS) $(CXXFLAGS) -c src/vm.cpp -o obj/vm.o + +obj/tsvm.o: trainscript/tsvm.cpp trainscript/tsvm.hpp g++ $(CFLAGS) $(CXXFLAGS) -c trainscript/tsvm.cpp -o obj/tsvm.o -obj/lex.yy.o: trainscript/lex.yy.cpp trainscript/tsvm.hpp trainscript/common.h trainscript/trainscript.tab.cpp +obj/lex.yy.o: trainscript/lex.yy.cpp trainscript/tsvm.hpp g++ $(CFLAGS) $(CXXFLAGS) -c trainscript/lex.yy.cpp -o obj/lex.yy.o -trainscript.tab.o: trainscript/lex.yy.cpp trainscript/trainscript.tab.cpp trainscript/tsvm.hpp trainscript/common.h +obj/trainscript.tab.o: trainscript/trainscript.tab.cpp trainscript/tsvm.hpp g++ $(CFLAGS) $(CXXFLAGS) -c trainscript/trainscript.tab.cpp -o obj/trainscript.tab.o trainscript/lex.yy.cpp: trainscript/trainscript.l @@ -41,8 +46,11 @@ trainscript/lex.yy.cpp: trainscript/trainscript.l trainscript/trainscript.tab.cpp: trainscript/trainscript.y $(YACC) -o trainscript/trainscript.tab.cpp -d trainscript/trainscript.y +obj/file01.o: + objcopy -I binary -O elf32-i386 --redefine-sym _binary_trainscript_file01_ts_start=file01_start --redefine-sym _binary_trainscript_file01_ts_end=file01_end --redefine-sym _binary_trainscript_file01_ts_size=file01_size trainscript/file01.ts obj/file01.o + clean: - rm $(addprefix obj/, $(notdir $(OBJS))) + rm obj/*.o run: qemu-system-i386 -kernel kernel diff --git a/asm/start.S b/asm/start.S index 9c56137..a4db257 100644 --- a/asm/start.S +++ b/asm/start.S @@ -4,8 +4,8 @@ .extern init // .global für Sichtbarkeit im Linker (invers zu static aus C) -.global _start -_start: +.global _trainOS_start +_trainOS_start: // Init stack mov $kernel_stack, %esp diff --git a/include/ker/dictionary.hpp b/include/ker/dictionary.hpp index fecbf77..5fe2428 100644 --- a/include/ker/dictionary.hpp +++ b/include/ker/dictionary.hpp @@ -40,7 +40,7 @@ namespace ker } bool contains(const Key &key) const - { + { for(const auto &pair : this->contents) { if(pair.first == key) { @@ -51,7 +51,7 @@ namespace ker } void add(const Key &key, const Value &value) - { + { if(this->contains(key)) { for(auto &&pair : this->contents) { diff --git a/include/ker/new.hpp b/include/ker/new.hpp index 36f3756..a901a60 100644 --- a/include/ker/new.hpp +++ b/include/ker/new.hpp @@ -2,12 +2,12 @@ #include -inline void* operator new(size_t size, void* __p) +inline void* operator new(size_t, void* __p) { return __p; } -inline void* operator new[](size_t size, void* __p) +inline void* operator new[](size_t, void* __p) { return __p; } diff --git a/include/ker/string.hpp b/include/ker/string.hpp index 72061d5..3b031c9 100644 --- a/include/ker/string.hpp +++ b/include/ker/string.hpp @@ -18,25 +18,52 @@ namespace ker } + String(const String &other) : + String(other.mText, other.mLength) + { + + } + + String(String &&other) : + mText(other.mText), + mLength(other.mLength) + { + other.mText = nullptr; + other.mLength = 0; + } + + String & operator = (const String &other) + { + free(this->mText); + this->mLength = other.mLength; + + this->mText = (uint8_t*)malloc(this->mLength + 1); + memcpy(this->mText, other.mText, this->mLength + 1); + } + String(const char *text) : mText(nullptr), mLength(0) - { - this->mLength = strlen(text); - this->mText = (uint8_t*)malloc(this->mLength + 1); - memcpy(this->mText, text, this->mLength); + { + this->mLength = strlen(text); + this->mText = (uint8_t*)malloc(this->mLength + 1); + memcpy(this->mText, text, this->mLength); + this->mText[this->mLength] = 0; } String(const uint8_t *bytes, size_t length) : - mText((uint8_t*)malloc(length)), + mText((uint8_t*)malloc(length + 1)), mLength(length) { - memcpy(this->mText, bytes, length); + memcpy(this->mText, bytes, length); + this->mText[this->mLength] = 0; // last byte is always 0 } ~String() { - free(this->mText); + if(this->mText != nullptr) { + free(this->mText); + } } size_t length() const diff --git a/kernel.ld b/kernel.ld index 077108e..16201af 100644 --- a/kernel.ld +++ b/kernel.ld @@ -1,5 +1,7 @@ /* Bei _start soll die Ausfuehrung losgehen */ -ENTRY(_start) +ENTRY(_trainOS_start) +OUTPUT_FORMAT(elf32-i386) +OUTPUT_ARCH(i386:i386) /* * Hier wird festgelegt, in welcher Reihenfolge welche Sektionen in die Binary @@ -24,6 +26,11 @@ SECTIONS *(.text) } .data ALIGN(4096) : { + start_ctors = .; + KEEP(*( .init_array )); + KEEP(*(SORT_BY_INIT_PRIORITY( .init_array.* ))); + end_ctors = .; + *(.data) } .rodata ALIGN(4096) : { diff --git a/src/cplusplus.cpp b/src/cplusplus.cpp index d0ad01e..3fe9e3d 100644 --- a/src/cplusplus.cpp +++ b/src/cplusplus.cpp @@ -1,11 +1,12 @@ #include +#include #include #include void *operator new( size_t size ) { - return calloc( size ); + return calloc( size ); } void *operator new[]( size_t size ) @@ -22,3 +23,47 @@ void operator delete[]( void *obj ) { free( obj ); } + +extern "C" void __cxa_pure_virtual() +{ + kprintf("Pure virtual function call.\n"); +} + +extern "C" int *__errno_location() +{ + static int errno; + return &errno; +} + +extern "C" int fprintf ( void * , const char * , ... ) +{ + kprintf("[some fprintf :P]"); + return 0; +} + +extern "C" +{ + void *stdin, *stdout, *stderr; +} + +// Lizenz: public domain + +typedef void (*constructor)(); + +// Im Linkerskript definiert +extern "C" constructor start_ctors; +extern "C" constructor end_ctors; + +extern "C" void initialiseConstructors(); + +// Ruft die Konstruktoren für globale/statische Objekte auf +void initialiseConstructors() +{ + for (constructor* i = &start_ctors;i != &end_ctors;++i) + (*i)(); +} + +extern "C" void cpp_init() +{ + initialiseConstructors(); +} diff --git a/src/init.c b/src/init.c index 156e268..33f5897 100644 --- a/src/init.c +++ b/src/init.c @@ -94,10 +94,7 @@ static void dumpMB(const MultibootStructure *mbHeader) // TODO: MB_APS_TABLE } -void cpp_init() -{ - -} +void cpp_init(); void putsuccess() { @@ -106,6 +103,8 @@ void putsuccess() kputs("[success]"); } +extern void vm_start(); + void init(const MultibootStructure *mbHeader) { (void)debug_test; @@ -151,9 +150,22 @@ void init(const MultibootStructure *mbHeader) cpp_init(); putsuccess(); + vm_start(); + while(1) { kputs("x"); sleep(1); } } + +int main(int argc, char **argv) +{ + while(1) { + kputs("x"); + } + return 0; +} + +void __init_array_start() { } +void __init_array_end() { } diff --git a/src/stdlib.c b/src/stdlib.c index 010c8f4..75425bc 100644 --- a/src/stdlib.c +++ b/src/stdlib.c @@ -85,6 +85,19 @@ int atoi(const char *str) return res; } +float atof(const char *str) +{ + // HACK: Implement + return 42.0f; +} + +double atod(const char *str) +{ + // HACK: Implement + return 42.0; +} + + void *memmove( void *destination, const void *source, size_t num) { // TODO: Implement memmove diff --git a/src/vm.cpp b/src/vm.cpp new file mode 100644 index 0000000..a1d4f07 --- /dev/null +++ b/src/vm.cpp @@ -0,0 +1,52 @@ +#include +#include "../trainscript/tsvm.hpp" + +using namespace ker; +using namespace trainscript; + +extern "C" { +// extern const char file01_start; +// extern const char file01_end; +// extern size_t file01_size; +} + +char file01[] = "VAR global : INT;\0"; + +String fn() +{ + return String("keks"); +} + +extern "C" void vm_start() +{ + kprintf("Testing ker::String:\n"); + + { + String a("hello"); + String b(a); + String c; + String d(fn()); + String e; + c = a; + e = fn(); + + kprintf("'%s' '%s' '%s' '%s' '%s'\n", a.str(), b.str(), c.str(), d.str(), e.str()); + } + + + kprintf("Parse kernel module:"); + Module *module = VM::load(file01, sizeof(file01)); + if(module == nullptr) { + kprintf("Could not load module :(\n"); + return; + } + + kprintf("Module successfully loaded :)\n"); + + for(const auto &var : module->variables) + { + kprintf("Variable: '%s' => '"); + var.second->printval(); + kprintf("\n"); + } +} diff --git a/trainOS.pro b/trainOS.pro index d6fbd42..0e22042 100644 --- a/trainOS.pro +++ b/trainOS.pro @@ -14,7 +14,8 @@ SOURCES += \ trainscript/tsvm.cpp \ trainscript/main.cpp \ src/timer.c \ - src/cplusplus.cpp + src/cplusplus.cpp \ + src/vm.cpp HEADERS += \ include/console.h \ @@ -49,7 +50,8 @@ DISTFILES += \ trainscript/file01.ts \ trainscript/Makefile \ trainscript/trainscript.y \ - trainscript/file02.ts + trainscript/file02.ts \ + kernel.ld QMAKE_INCDIR = diff --git a/trainscript/trainscript.y b/trainscript/trainscript.y index a981a82..0d006b2 100644 --- a/trainscript/trainscript.y +++ b/trainscript/trainscript.y @@ -144,7 +144,8 @@ void yyerror(void *scanner, const char *s); input: %empty | input variableDeclaration SEMICOLON { - context->module->variables.insert( { $2.name, new Variable($2.variable) } ); + auto *var = new Variable($2.variable); + context->module->variables.add( ker::String($2.name), var ); } | input method { using namespace trainscript; @@ -153,22 +154,22 @@ input: Method *method = new Method(mod, $2.body); method->isPublic = $2.header.isPublic; if($2.header.returnValue) { - method->returnValue = std::pair( + method->returnValue = ker::Pair( $2.header.returnValue->name, $2.header.returnValue->variable); } LocalVariable *local = $2.header.locals; while(local) { - method->locals.insert( { local->name, local->variable } ); + method->locals.add( local->name, local->variable ); local = local->next; } LocalVariable *arg = $2.header.arguments; while(arg) { - method->arguments.push_back( { arg->name, arg->variable } ); + method->arguments.append( { arg->name, arg->variable } ); arg = arg->next; } - context->module->methods.insert( { $2.header.name, method } ); + context->module->methods.add( $2.header.name, method ); } ; @@ -185,7 +186,7 @@ block: MethodBody *mb = $2; while(mb) { if(mb->instruction != nullptr) { - block->instructions.push_back(mb->instruction); + block->instructions.append(mb->instruction); } mb = mb->next; } @@ -335,7 +336,7 @@ expression: auto *call = new MethodInvokeExpression($1); auto *list = $3; while(list) { - call->parameters.push_back(list->instruction); + call->parameters.append(list->instruction); list = list->next; } $$ = call; diff --git a/trainscript/tsvm.cpp b/trainscript/tsvm.cpp index de8db1c..9c723f8 100644 --- a/trainscript/tsvm.cpp +++ b/trainscript/tsvm.cpp @@ -21,12 +21,12 @@ namespace trainscript const Type Type::Text = { TypeID::Text, 0 }; const Type Type::Boolean = { TypeID::Bool, 0 }; - const Variable Variable::Invalid = { Type::Invalid }; - const Variable Variable::Void = { Type::Void }; - const Variable Variable::Int = { Type::Int }; - const Variable Variable::Real = { Type::Real }; - const Variable Variable::Text = { Type::Text }; - const Variable Variable::Boolean = { Type::Boolean }; + const Variable Variable::Invalid = { Type::Invalid, 0 }; + const Variable Variable::Void = { Type::Void, 0 }; + const Variable Variable::Int = { Type::Int, 0 }; + const Variable Variable::Real = { Type::Real, 0 }; + const Variable Variable::Text = { Type::Text, 0 }; + const Variable Variable::Boolean = { Type::Boolean, 0 }; Module *VM::load(const void *buffer, size_t length) { @@ -42,7 +42,9 @@ namespace trainscript data.module = module; yylex_init_extra(&data, &data.scanner); - bool valid = yyparse(&data) == 0; + int error = yyparse(&data); + kprintf("[E:%d]", error); + bool valid = error == 0; yylex_destroy(data.scanner); free(internalStorage);