somehow c++ support and stuff.

This commit is contained in:
Felix Queißner 2015-08-13 17:23:11 +02:00
parent ddbfb0e1aa
commit ec533526df
13 changed files with 212 additions and 43 deletions

View file

@ -3,7 +3,7 @@ OBJS = $(addsuffix .o,$(basename $(SRCS)))
CC = gcc CC = gcc
CXX = g++ CXX = g++
LD = ld LD = g++
LEX=flex LEX=flex
YACC=bison YACC=bison
@ -11,10 +11,12 @@ YACC=bison
CFLAGS = -m32 -Dnullptr=0 CFLAGS = -m32 -Dnullptr=0
ASFLAGS = ASFLAGS =
CCFLAGS = -g -std=c11 -Wall -g -fno-stack-protector -ffreestanding -Iinclude 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 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 -melf_i386 -Tkernel.ld 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 $^)) $(LD) $(LDFLAGS) -o $@ $(addprefix obj/, $(notdir $^))
%.o: %.c %.o: %.c
@ -26,13 +28,16 @@ kernel: $(OBJS) obj/tsvm.o obj/lex.yy.o obj/trainscript.tab.o
%.o: %.cpp %.o: %.cpp
$(CXX) $(CFLAGS) $(CXXFLAGS) -c -o $(addprefix obj/, $(notdir $@)) $^ $(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 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 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 g++ $(CFLAGS) $(CXXFLAGS) -c trainscript/trainscript.tab.cpp -o obj/trainscript.tab.o
trainscript/lex.yy.cpp: trainscript/trainscript.l 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 trainscript/trainscript.tab.cpp: trainscript/trainscript.y
$(YACC) -o trainscript/trainscript.tab.cpp -d 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: clean:
rm $(addprefix obj/, $(notdir $(OBJS))) rm obj/*.o
run: run:
qemu-system-i386 -kernel kernel qemu-system-i386 -kernel kernel

View file

@ -4,8 +4,8 @@
.extern init .extern init
// .global für Sichtbarkeit im Linker (invers zu static aus C) // .global für Sichtbarkeit im Linker (invers zu static aus C)
.global _start .global _trainOS_start
_start: _trainOS_start:
// Init stack // Init stack
mov $kernel_stack, %esp mov $kernel_stack, %esp

View file

@ -40,7 +40,7 @@ namespace ker
} }
bool contains(const Key &key) const bool contains(const Key &key) const
{ {
for(const auto &pair : this->contents) for(const auto &pair : this->contents)
{ {
if(pair.first == key) { if(pair.first == key) {
@ -51,7 +51,7 @@ namespace ker
} }
void add(const Key &key, const Value &value) void add(const Key &key, const Value &value)
{ {
if(this->contains(key)) { if(this->contains(key)) {
for(auto &&pair : this->contents) for(auto &&pair : this->contents)
{ {

View file

@ -2,12 +2,12 @@
#include <inttypes.h> #include <inttypes.h>
inline void* operator new(size_t size, void* __p) inline void* operator new(size_t, void* __p)
{ {
return __p; return __p;
} }
inline void* operator new[](size_t size, void* __p) inline void* operator new[](size_t, void* __p)
{ {
return __p; return __p;
} }

View file

@ -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) : String(const char *text) :
mText(nullptr), mText(nullptr),
mLength(0) mLength(0)
{ {
this->mLength = strlen(text); this->mLength = strlen(text);
this->mText = (uint8_t*)malloc(this->mLength + 1); this->mText = (uint8_t*)malloc(this->mLength + 1);
memcpy(this->mText, text, this->mLength); memcpy(this->mText, text, this->mLength);
this->mText[this->mLength] = 0;
} }
String(const uint8_t *bytes, size_t length) : String(const uint8_t *bytes, size_t length) :
mText((uint8_t*)malloc(length)), mText((uint8_t*)malloc(length + 1)),
mLength(length) mLength(length)
{ {
memcpy(this->mText, bytes, length); memcpy(this->mText, bytes, length);
this->mText[this->mLength] = 0; // last byte is always 0
} }
~String() ~String()
{ {
free(this->mText); if(this->mText != nullptr) {
free(this->mText);
}
} }
size_t length() const size_t length() const

View file

@ -1,5 +1,7 @@
/* Bei _start soll die Ausfuehrung losgehen */ /* 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 * Hier wird festgelegt, in welcher Reihenfolge welche Sektionen in die Binary
@ -24,6 +26,11 @@ SECTIONS
*(.text) *(.text)
} }
.data ALIGN(4096) : { .data ALIGN(4096) : {
start_ctors = .;
KEEP(*( .init_array ));
KEEP(*(SORT_BY_INIT_PRIORITY( .init_array.* )));
end_ctors = .;
*(.data) *(.data)
} }
.rodata ALIGN(4096) : { .rodata ALIGN(4096) : {

View file

@ -1,11 +1,12 @@
#include <stdlib.h> #include <stdlib.h>
#include <console.h>
#include <inttypes.h> #include <inttypes.h>
#include <ker/new.hpp> #include <ker/new.hpp>
void *operator new( size_t size ) void *operator new( size_t size )
{ {
return calloc( size ); return calloc( size );
} }
void *operator new[]( size_t size ) void *operator new[]( size_t size )
@ -22,3 +23,47 @@ void operator delete[]( void *obj )
{ {
free( 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();
}

View file

@ -94,10 +94,7 @@ static void dumpMB(const MultibootStructure *mbHeader)
// TODO: MB_APS_TABLE // TODO: MB_APS_TABLE
} }
void cpp_init() void cpp_init();
{
}
void putsuccess() void putsuccess()
{ {
@ -106,6 +103,8 @@ void putsuccess()
kputs("[success]"); kputs("[success]");
} }
extern void vm_start();
void init(const MultibootStructure *mbHeader) void init(const MultibootStructure *mbHeader)
{ {
(void)debug_test; (void)debug_test;
@ -151,9 +150,22 @@ void init(const MultibootStructure *mbHeader)
cpp_init(); cpp_init();
putsuccess(); putsuccess();
vm_start();
while(1) while(1)
{ {
kputs("x"); kputs("x");
sleep(1); sleep(1);
} }
} }
int main(int argc, char **argv)
{
while(1) {
kputs("x");
}
return 0;
}
void __init_array_start() { }
void __init_array_end() { }

View file

@ -85,6 +85,19 @@ int atoi(const char *str)
return res; 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) void *memmove( void *destination, const void *source, size_t num)
{ {
// TODO: Implement memmove // TODO: Implement memmove

52
src/vm.cpp Normal file
View file

@ -0,0 +1,52 @@
#include <stdlib.h>
#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");
}
}

View file

@ -14,7 +14,8 @@ SOURCES += \
trainscript/tsvm.cpp \ trainscript/tsvm.cpp \
trainscript/main.cpp \ trainscript/main.cpp \
src/timer.c \ src/timer.c \
src/cplusplus.cpp src/cplusplus.cpp \
src/vm.cpp
HEADERS += \ HEADERS += \
include/console.h \ include/console.h \
@ -49,7 +50,8 @@ DISTFILES += \
trainscript/file01.ts \ trainscript/file01.ts \
trainscript/Makefile \ trainscript/Makefile \
trainscript/trainscript.y \ trainscript/trainscript.y \
trainscript/file02.ts trainscript/file02.ts \
kernel.ld
QMAKE_INCDIR = QMAKE_INCDIR =

View file

@ -144,7 +144,8 @@ void yyerror(void *scanner, const char *s);
input: input:
%empty %empty
| input variableDeclaration SEMICOLON { | 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 { | input method {
using namespace trainscript; using namespace trainscript;
@ -153,22 +154,22 @@ input:
Method *method = new Method(mod, $2.body); Method *method = new Method(mod, $2.body);
method->isPublic = $2.header.isPublic; method->isPublic = $2.header.isPublic;
if($2.header.returnValue) { if($2.header.returnValue) {
method->returnValue = std::pair<std::string, Variable>( method->returnValue = ker::Pair<ker::String, Variable>(
$2.header.returnValue->name, $2.header.returnValue->name,
$2.header.returnValue->variable); $2.header.returnValue->variable);
} }
LocalVariable *local = $2.header.locals; LocalVariable *local = $2.header.locals;
while(local) { while(local) {
method->locals.insert( { local->name, local->variable } ); method->locals.add( local->name, local->variable );
local = local->next; local = local->next;
} }
LocalVariable *arg = $2.header.arguments; LocalVariable *arg = $2.header.arguments;
while(arg) { while(arg) {
method->arguments.push_back( { arg->name, arg->variable } ); method->arguments.append( { arg->name, arg->variable } );
arg = arg->next; 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; MethodBody *mb = $2;
while(mb) { while(mb) {
if(mb->instruction != nullptr) { if(mb->instruction != nullptr) {
block->instructions.push_back(mb->instruction); block->instructions.append(mb->instruction);
} }
mb = mb->next; mb = mb->next;
} }
@ -335,7 +336,7 @@ expression:
auto *call = new MethodInvokeExpression($1); auto *call = new MethodInvokeExpression($1);
auto *list = $3; auto *list = $3;
while(list) { while(list) {
call->parameters.push_back(list->instruction); call->parameters.append(list->instruction);
list = list->next; list = list->next;
} }
$$ = call; $$ = call;

View file

@ -21,12 +21,12 @@ namespace trainscript
const Type Type::Text = { TypeID::Text, 0 }; const Type Type::Text = { TypeID::Text, 0 };
const Type Type::Boolean = { TypeID::Bool, 0 }; const Type Type::Boolean = { TypeID::Bool, 0 };
const Variable Variable::Invalid = { Type::Invalid }; const Variable Variable::Invalid = { Type::Invalid, 0 };
const Variable Variable::Void = { Type::Void }; const Variable Variable::Void = { Type::Void, 0 };
const Variable Variable::Int = { Type::Int }; const Variable Variable::Int = { Type::Int, 0 };
const Variable Variable::Real = { Type::Real }; const Variable Variable::Real = { Type::Real, 0 };
const Variable Variable::Text = { Type::Text }; const Variable Variable::Text = { Type::Text, 0 };
const Variable Variable::Boolean = { Type::Boolean }; const Variable Variable::Boolean = { Type::Boolean, 0 };
Module *VM::load(const void *buffer, size_t length) Module *VM::load(const void *buffer, size_t length)
{ {
@ -42,7 +42,9 @@ namespace trainscript
data.module = module; data.module = module;
yylex_init_extra(&data, &data.scanner); 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); yylex_destroy(data.scanner);
free(internalStorage); free(internalStorage);