Adds native code invoke unit.
This commit is contained in:
parent
a22d91903f
commit
8e5f1e90c3
9 changed files with 305 additions and 6 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -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
21
Depfile
Normal 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
|
||||||
|
|
6
Makefile
6
Makefile
|
@ -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
109
Makefile.new
Normal 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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
48
src/stdlib.c
48
src/stdlib.c
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
114
src/vm.cpp
114
src/vm.cpp
|
@ -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());
|
||||||
|
|
|
@ -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 =
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue