Adds native code invoke unit.

This commit is contained in:
Felix Queissner 2015-08-14 11:58:16 +02:00
parent a22d91903f
commit 8e5f1e90c3
9 changed files with 305 additions and 6 deletions

3
.gitignore vendored
View file

@ -41,3 +41,6 @@ trainscript/tsvm
*.tab.h *.tab.h
*.l.h *.l.h
lex.yy.cpp lex.yy.cpp
depmake.exe*
docs/*

21
Depfile Normal file
View file

@ -0,0 +1,21 @@
#Config
Artifact=kernel
TempDir=obj
SourceDir=asm src
Files=trainscript/trainscript.y trainscript/trainscript.l trainscript/tsvm.cpp
# Tools
AS=gcc
CC=gcc
CXX=g++
LD=g++
LEX=flex
YACC=bison
# Flags
FLAGS=-m32 -Dnullptr=0
ASFLAGS=
CCFLAGS=-g -std=c11 -Dnullptr=0 -Wall -g -fno-stack-protector -ffreestanding -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 -m32 -nostdlib -fno-builtin -Tkernel.ld

View file

@ -8,11 +8,11 @@ LEX=flex
YACC=bison YACC=bison
# define nullptr, but not NULL. # define nullptr, but not NULL.
CFLAGS = -m32 -Dnullptr=0 CFLAGS = -m32
ASFLAGS = ASFLAGS =
CCFLAGS = -g -std=c11 -Wall -g -fno-stack-protector -ffreestanding -Iinclude CCFLAGS = -g -std=c11 -Wall -Dnullptr=0 -g -fno-stack-protector -ffreestanding -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 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 LDFLAGS = -g -m32 -nostdlib -fno-builtin -Tkernel.ld
all: clean kernel all: clean kernel

109
Makefile.new Normal file
View file

@ -0,0 +1,109 @@
# Makefile generated by makedep.
# Tools
AS = gcc
CC = gcc
CXX = g++
LD = g++
LEX = flex
YACC = bison
# File Lists
SRCS_AS = asm/intr_common_handler.S asm/multiboot.S asm/start.S
SRCS_CC = src/console.c src/init.c src/interrupts.c src/malloc.c src/pmm.c src/stdlib.c src/timer.c src/vmm.c
SRCS_CXX = trainscript/tsvm.cpp src/cplusplus.cpp src/vm.cpp obj/trainscript.yy.cpp obj/trainscript.tab.cpp
OBJS = obj/trainscript.o obj/trainscript.o obj/tsvm.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o
# Flags
FLAGS = -m32 -Dnullptr=0
ASFLAGS =
CCFLAGS = -g -std=c11 -Dnullptr=0 -Wall -g -fno-stack-protector -ffreestanding -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 -m32 -nostdlib -fno-builtin -Tkernel.ld
# Targets
all: kernel
kernel: obj/trainscript.o obj/trainscript.o obj/tsvm.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o
$(LD) $(FLAGS) $(LDFLAGS) -o $@ obj/trainscript.o obj/trainscript.o obj/tsvm.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o
# src/console.c
obj/console.o: src/console.c include/console.h include/stdlib.h \
include/varargs.h
$(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/console.c
# src/init.c
obj/init.o: src/init.c include/kernel.h include/stdlib.h include/varargs.h \
include/console.h include/interrupts.h include/cpustate.h include/pmm.h \
include/multiboot.h include/vmm.h include/timer.h
$(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/init.c
# src/interrupts.c
obj/interrupts.o: src/interrupts.c include/interrupts.h include/cpustate.h \
include/console.h include/stdlib.h include/varargs.h include/io.h \
src/intr_stubs.h
$(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/interrupts.c
# src/malloc.c
obj/malloc.o: src/malloc.c include/stdlib.h include/varargs.h
$(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/malloc.c
# src/pmm.c
obj/pmm.o: src/pmm.c include/pmm.h include/multiboot.h include/kernel.h \
include/stdlib.h include/varargs.h include/console.h
$(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/pmm.c
# src/stdlib.c
obj/stdlib.o: src/stdlib.c include/stdlib.h include/varargs.h \
include/kernel.h
$(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/stdlib.c
# src/timer.c
obj/timer.o: src/timer.c include/timer.h include/interrupts.h \
include/cpustate.h
$(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/timer.c
# src/vmm.c
obj/vmm.o: src/vmm.c include/vmm.h include/pmm.h include/multiboot.h \
include/stdlib.h include/varargs.h include/console.h include/kernel.h
$(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/vmm.c
# trainscript/tsvm.cpp
obj/tsvm.o: trainscript/tsvm.cpp include/stdlib.h include/varargs.h \
include/console.h trainscript/common.h trainscript/tsvm.hpp \
include/ker/string.hpp include/ker/vector.hpp include/ker/new.hpp \
include/ker/dictionary.hpp include/ker/pair.hpp trainscript/typeid.hpp \
trainscript/trainscript.tab.hpp trainscript/trainscript.l.h \
include/string.h
$(CXX) $(FLAGS) $(CXXFLAGS) -o $@ -c trainscript/tsvm.cpp
# src/cplusplus.cpp
obj/cplusplus.o: src/cplusplus.cpp include/stdlib.h include/varargs.h \
include/console.h include/ker/new.hpp
$(CXX) $(FLAGS) $(CXXFLAGS) -o $@ -c src/cplusplus.cpp
# src/vm.cpp
obj/vm.o: src/vm.cpp include/stdlib.h include/varargs.h \
src/../trainscript/tsvm.hpp include/console.h include/ker/string.hpp \
include/ker/vector.hpp include/ker/new.hpp include/ker/dictionary.hpp \
include/ker/pair.hpp src/../trainscript/typeid.hpp
$(CXX) $(FLAGS) $(CXXFLAGS) -o $@ -c src/vm.cpp
# obj/trainscript.yy.cpp
$(CXX) $(FLAGS) $(CXXFLAGS) -o $@ -c obj/trainscript.yy.cpp
# obj/trainscript.tab.cpp
$(CXX) $(FLAGS) $(CXXFLAGS) -o $@ -c obj/trainscript.tab.cpp
# asm/intr_common_handler.S
obj/intr_common_handler.o: asm/intr_common_handler.S
$(AS) $(FLAGS) $(ASFLAGS) -o $@ -c asm/intr_common_handler.S
# asm/multiboot.S
obj/multiboot.o: asm/multiboot.S
$(AS) $(FLAGS) $(ASFLAGS) -o $@ -c asm/multiboot.S
# asm/start.S
obj/start.o: asm/start.S
$(AS) $(FLAGS) $(ASFLAGS) -o $@ -c asm/start.S

View file

@ -183,6 +183,7 @@ void kprintf(const char *format, ...)
{ {
c = *(format++); c = *(format++);
int i; int i;
float f;
char *str; char *str;
switch(c) switch(c)
{ {
@ -200,6 +201,10 @@ void kprintf(const char *format, ...)
i = va_arg(vl, int); i = va_arg(vl, int);
kputs(itoa(i, buffer, 16)); kputs(itoa(i, buffer, 16));
break; break;
case 'f':
f = va_arg(vl, float);
kputs(ftoa(f, buffer, 3));
break;
case 'c': case 'c':
c = va_arg(vl, int); c = va_arg(vl, int);
kputc(c); kputc(c);

View file

@ -97,6 +97,54 @@ double atod(const char *str)
return 42.0; return 42.0;
} }
// Converts a given integer x to string str[]. d is the number
// of digits required in output. If d is more than the number
// of digits in x, then 0s are added at the beginning.
static int intToStr(int x, char str[], int d)
{
int i = 0;
while (x)
{
str[i++] = (x%10) + '0';
x = x/10;
}
// If number of digits required is more, then
// add 0s at the beginning
while (i < d)
str[i++] = '0';
reverse(str, i);
str[i] = '\0';
return i;
}
// Converts a floating point number to string.
void ftoa(float n, char *res, int afterpoint)
{
// Extract integer part
int ipart = (int)n;
// Extract floating part
float fpart = n - (float)ipart;
// convert integer part to string
int i = intToStr(ipart, res, 0);
// check for display option after point
if (afterpoint != 0)
{
res[i] = '.'; // add dot
// Get the value of fraction part upto given no.
// of points after dot. The third parameter is needed
// to handle cases like 233.007
//fpart = fpart * pow(10, afterpoint);
intToStr((int)fpart, res + i + 1, afterpoint);
}
}
void *memmove( void *destination, const void *source, size_t num) void *memmove( void *destination, const void *source, size_t num)
{ {

View file

@ -15,12 +15,18 @@ VAR global : INT;
PUB main() | i : INT PUB main() | i : INT
BEGIN BEGIN
print(10, 20, 30); print(10, 20, 30);
afraid(15.0, 34) i;
print(40, i, 60);
0 -> i; 0 -> i;
REPEAT WHILE i < 5 DO
BEGIN BEGIN
print(i); print(i);
i + 1 -> i; i + 1 -> i;
END END
REPEAT
BEGIN
END
END)code"; END)code";
void cpp_test(); void cpp_test();
@ -32,6 +38,21 @@ public:
Variable invoke(Vector<Variable> arguments) override; Variable invoke(Vector<Variable> arguments) override;
}; };
class NativeMethod :
public Method
{
private:
void *function;
public:
NativeMethod(void *fn) :
function(fn)
{
}
Variable invoke(Vector<Variable> arguments) override;
};
Variable PrintMethod::invoke(Vector<Variable> arguments) Variable PrintMethod::invoke(Vector<Variable> arguments)
{ {
for(auto &var : arguments) for(auto &var : arguments)
@ -43,6 +64,95 @@ Variable PrintMethod::invoke(Vector<Variable> arguments)
return Variable::Void; return Variable::Void;
} }
static void copyCode(uint8_t **ptr, const uint8_t *src, size_t length)
{
for(size_t i = 0; i < length; i++) {
// Copy byte
**ptr = src[i];
// Iterate
(*ptr)++;
}
}
/**
* @brief Invokes a cdecl function
* @param arguments Arguments passed to the c function
* @return uint32_t return value of the c function
*/
Variable NativeMethod::invoke(Vector<Variable> arguments)
{
if(this->function == nullptr) {
return Variable::Invalid;
}
// ASM code:
// push ebp
// mov ebp, esp
// (push imm32) * num
// call [function]
// add esp, 4 * num
// ret
uint8_t headerCode[] = {
0x55, // push ebp
0x89, 0xE5, // mov ebp, esp
};
uint8_t tailCode[] = {
0xB8, 0x42, 0x00, 0x00, 0x00, // mov eax,0x42
0xFF, 0xD0, // call eax
0x83, 0xC4, 0x08, // add esp, 0x00
0xC9, // leave
// 0x5D, // pop ebp
0xC3, // ret
};
// Store some memory for a function
uint8_t pushCode[] = {
0x68, 0x00, 0x00, 0x00, 0x00 // push 0x00
};
size_t stackSize = 4 * arguments.length();
// Copy target address to mov eax, 0x42
*reinterpret_cast<uintptr_t*>(&tailCode[1]) = reinterpret_cast<uintptr_t>(this->function);
// Copy stack size to add esp, 0x00
*reinterpret_cast<uint8_t*>(&tailCode[9]) = static_cast<uint8_t>(stackSize);
uint8_t code[128];
// Built the function
{
uint8_t *codePtr = &code[0];
// Copy function header
copyCode(&codePtr, headerCode, sizeof(headerCode));
// Copy arguments
for(int i = arguments.length() - 1; i >= 0; i--) {
// Copy argument value to push 0x00
*reinterpret_cast<int32_t*>(&pushCode[1]) = reinterpret_cast<int32_t>(arguments[i].integer);
// Copy push code
copyCode(&codePtr, pushCode, sizeof(pushCode));
}
// Copy function end
copyCode(&codePtr, tailCode, sizeof(tailCode));
}
// Call some crazy
uint32_t (*func)() = (uint32_t(*)())code;
uint32_t result = func();
return mkvar((Int)result);
}
extern "C" uint32_t __attribute__((cdecl)) cCodeFunction(float a, int b)
{
kprintf("a=%d, b=%d\n", a, b);
return 666;
}
extern "C" void vm_start() extern "C" void vm_start()
{ {
// cpp_test(); // cpp_test();
@ -58,6 +168,8 @@ extern "C" void vm_start()
module->methods.add("print", new PrintMethod()); module->methods.add("print", new PrintMethod());
module->methods.add("afraid", new NativeMethod(reinterpret_cast<void*>(&cCodeFunction)));
for(const auto &var : module->variables) for(const auto &var : module->variables)
{ {
kprintf("Variable: '%s' => '", var.first.str()); kprintf("Variable: '%s' => '", var.first.str());

View file

@ -51,7 +51,8 @@ DISTFILES += \
trainscript/Makefile \ trainscript/Makefile \
trainscript/trainscript.y \ trainscript/trainscript.y \
trainscript/file02.ts \ trainscript/file02.ts \
kernel.ld kernel.ld \
Depfile
QMAKE_INCDIR = QMAKE_INCDIR =

View file

@ -19,7 +19,7 @@ extern "C" {
namespace trainscript namespace trainscript
{ {
using Int = int32_t; using Int = int32_t;
using Real = double; using Real = float;
using Void = void; using Void = void;
using Bool = bool; using Bool = bool;