Adds dynamic.h and dynamic.S creating a dynamic call utility.
This commit is contained in:
parent
0f54fabc99
commit
6cea5944c3
9 changed files with 241 additions and 531 deletions
4
Depfile
4
Depfile
|
@ -17,8 +17,8 @@ LEX=flex
|
|||
YACC=bison
|
||||
|
||||
# Flags
|
||||
FLAGS=-m32 -Dnullptr=0 -D__cdecl="__attribute__((cdecl))"
|
||||
ASFLAGS=
|
||||
FLAGS=-m32 -Dnullptr=0 -D__cdecl="__attribute__((cdecl))" -mno-sse -mno-sse2 -mno-mmx
|
||||
ASFLAGS=-masm=intel
|
||||
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
|
||||
|
|
25
Makefile
25
Makefile
|
@ -10,14 +10,14 @@ LEX = flex
|
|||
YACC = bison
|
||||
|
||||
# File Lists
|
||||
SRCS_AS = asm/intr_common_handler.S asm/multiboot.S asm/start.S
|
||||
SRCS_AS = asm/dynamic.S 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/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 obj/main.o
|
||||
OBJS = obj/tsvm.o obj/dynamic.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 obj/main.o
|
||||
|
||||
# Flags
|
||||
FLAGS = -m32 -Dnullptr=0 -D__cdecl="__attribute__((cdecl))"
|
||||
ASFLAGS =
|
||||
FLAGS = -m32 -Dnullptr=0 -D__cdecl="__attribute__((cdecl))" -mno-sse -mno-sse2 -mno-mmx
|
||||
ASFLAGS = -masm=intel
|
||||
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
|
||||
|
@ -27,10 +27,10 @@ all: kernel
|
|||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(RM) obj/trainscript.yy.cpp obj/trainscript.tab.cpp 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 obj/main.o
|
||||
$(RM) obj/trainscript.yy.cpp obj/trainscript.tab.cpp obj/tsvm.o obj/dynamic.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 obj/main.o
|
||||
|
||||
kernel: 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 obj/main.o
|
||||
$(LD) $(FLAGS) $(LDFLAGS) -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 obj/main.o
|
||||
kernel: obj/tsvm.o obj/dynamic.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 obj/main.o
|
||||
$(LD) $(FLAGS) $(LDFLAGS) -o $@ obj/tsvm.o obj/dynamic.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 obj/main.o
|
||||
|
||||
# src/console.c
|
||||
obj/console.o: src/console.c include/console.h include/stdlib.h \
|
||||
|
@ -89,9 +89,10 @@ obj/cplusplus.o: src/cplusplus.cpp include/stdlib.h include/varargs.h \
|
|||
|
||||
# src/vm.cpp
|
||||
obj/vm.o: src/vm.cpp include/stdlib.h include/varargs.h include/timer.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/kernel.h include/ker/pair.hpp src/../trainscript/typeid.hpp
|
||||
include/dynamic.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/kernel.h include/ker/pair.hpp \
|
||||
src/../trainscript/typeid.hpp
|
||||
$(CXX) $(FLAGS) $(CXXFLAGS) -o $@ -c src/vm.cpp
|
||||
|
||||
# obj/trainscript.yy.cpp
|
||||
|
@ -112,6 +113,10 @@ obj/trainscript.tab.o: obj/trainscript.tab.cpp include/stdlib.h \
|
|||
include/string.h
|
||||
$(CXX) -iquotetrainscript $(FLAGS) $(CXXFLAGS) -o $@ -c obj/trainscript.tab.cpp
|
||||
|
||||
# asm/dynamic.S
|
||||
obj/dynamic.o: asm/dynamic.S
|
||||
$(AS) $(FLAGS) $(ASFLAGS) -o $@ -c asm/dynamic.S
|
||||
|
||||
# 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
|
||||
|
|
42
asm/dynamic.S
Normal file
42
asm/dynamic.S
Normal file
|
@ -0,0 +1,42 @@
|
|||
.section .text
|
||||
.intel_syntax noprefix
|
||||
|
||||
.extern _callee
|
||||
|
||||
/**
|
||||
* void __cdecl dynamic_call(void *func, void *stack, size_t stacksize)
|
||||
*/
|
||||
.global dynamic_call
|
||||
dynamic_call:
|
||||
/* save everything except EAX, ECX, EDX */
|
||||
push ebx
|
||||
push esi
|
||||
push edi
|
||||
|
||||
/* setup call */
|
||||
mov ebx, [esp+0x18] /* stacksize */
|
||||
mov eax, [esp+0x10] /* function */
|
||||
mov esi /* src */, [esp+0x14] /* stackptr */
|
||||
|
||||
sub esp, ebx /* adjust stack pointer for call */
|
||||
mov edi /* dst */, esp
|
||||
mov ecx /* num */, ebx
|
||||
|
||||
/* jump to label if we don't need to copy anything */
|
||||
cmp ebx, 0x00
|
||||
jz label
|
||||
|
||||
/* copy virtual stack data */
|
||||
cld
|
||||
rep movsb
|
||||
|
||||
label:
|
||||
/* call function and restore stack */
|
||||
call eax
|
||||
add esp, ebx /* ebx = stacksize */
|
||||
|
||||
/* clean up */
|
||||
pop edi
|
||||
pop esi
|
||||
pop ebx
|
||||
ret
|
12
include/dynamic.h
Normal file
12
include/dynamic.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
#include <inttypes.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void __cdecl dynamic_call(void *func, void *stack, uint32_t stackSize);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
|
@ -2,7 +2,10 @@ VAR global : INT;
|
|||
|
||||
PUB main() | i : INT
|
||||
BEGIN
|
||||
fun() -> i;
|
||||
0 -> i;
|
||||
# Print numbers from 1 to 5
|
||||
WHILE ((i + 1) -> i) <= 5 DO
|
||||
printInt(i);
|
||||
END
|
||||
|
||||
PUB fun() -> i : INT
|
||||
|
|
|
@ -150,6 +150,10 @@ void init(const MultibootStructure *mbHeader)
|
|||
cpp_init();
|
||||
putsuccess();
|
||||
|
||||
double f = 1.0;
|
||||
|
||||
int i = (int)f;
|
||||
|
||||
vm_start();
|
||||
|
||||
kputs("\x12\x04trainOS stopped.\x12\x07!\n");
|
||||
|
|
343
src/vm.cpp
343
src/vm.cpp
|
@ -1,5 +1,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <timer.h>
|
||||
#include <dynamic.h>
|
||||
#include "../trainscript/tsvm.hpp"
|
||||
|
||||
using namespace ker;
|
||||
|
@ -37,7 +38,9 @@ public:
|
|||
}
|
||||
|
||||
Vector<Type> arguments() const {
|
||||
return Vector<Type>();
|
||||
Vector<Type> list;
|
||||
list.append(Type::Int);
|
||||
return list;
|
||||
}
|
||||
|
||||
Type returnType() const {
|
||||
|
@ -45,16 +48,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
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
|
||||
|
@ -66,66 +59,45 @@ Variable NativeMethod::invoke(Vector<Variable> arguments)
|
|||
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 arguments
|
||||
size_t stackSize = 0;
|
||||
for(int i = 0; i < arguments.length(); i++) {
|
||||
switch(arguments[i].type.id) {
|
||||
case TypeID::Bool: stackSize += sizeof(Int); break;
|
||||
case TypeID::Int: stackSize += sizeof(Int); break;
|
||||
case TypeID::Real: stackSize += sizeof(Real); break;
|
||||
default: die("invalid argument type."); break;
|
||||
}
|
||||
|
||||
// Copy function end
|
||||
copyCode(&codePtr, tailCode, sizeof(tailCode));
|
||||
}
|
||||
|
||||
// Call some crazy
|
||||
uint32_t (*func)() = (uint32_t(*)())code;
|
||||
uint8_t *stack = (uint8_t*)malloc(stackSize);
|
||||
for(int i = arguments.length() - 1; i >= 0; i--) {
|
||||
switch(arguments[i].type.id) {
|
||||
case TypeID::Bool:
|
||||
*reinterpret_cast<Int*>(stack) = arguments[i].boolean ? 1 : 0;
|
||||
stack += sizeof(Int);
|
||||
break;
|
||||
case TypeID::Int:
|
||||
*reinterpret_cast<Int*>(stack) = arguments[i].integer;
|
||||
stack += sizeof(Int);
|
||||
break;
|
||||
case TypeID::Real:
|
||||
*reinterpret_cast<Real*>(stack) = arguments[i].real;
|
||||
stack += sizeof(Real);
|
||||
break;
|
||||
default: die("invalid argument type."); break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t result = func();
|
||||
dynamic_call(this->function, stack-stackSize, stackSize);
|
||||
|
||||
return mkvar((Int)result);
|
||||
free(stack);
|
||||
|
||||
return mkvar((Int)0);
|
||||
}
|
||||
|
||||
extern "C" void __cdecl printInt(int i) {
|
||||
kprintf("{%d}\n", i);
|
||||
}
|
||||
|
||||
struct NativeModuleDef
|
||||
|
@ -138,6 +110,7 @@ NativeModuleDef methods[] = {
|
|||
{ "sleep", (void*)sleep },
|
||||
{ "timer_get", (void*)timer_get },
|
||||
{ "timer_set", (void*)timer_set },
|
||||
{ "printInt", (void*)printInt },
|
||||
{ nullptr, 0 }
|
||||
};
|
||||
|
||||
|
@ -151,23 +124,17 @@ extern "C" void vm_start()
|
|||
(uint32_t)&mainscript_size
|
||||
};
|
||||
|
||||
// cpp_test();
|
||||
// cpp_test();
|
||||
|
||||
kprintf("Parse kernel module: ");
|
||||
kprintf("Parse kernel module: ");
|
||||
Module *module = VM::load(mainfile.ptr, mainfile.size);
|
||||
if(module == nullptr) {
|
||||
kprintf("Could not load module :(\n");
|
||||
return;
|
||||
}
|
||||
|
||||
kprintf("Module successfully loaded :)\n");
|
||||
|
||||
String errorCode;
|
||||
if(module->validate(errorCode) == false) {
|
||||
kprintf("Module validation failed: \x12\x06%s\x12\x07\n", errorCode.str());
|
||||
if(module == nullptr) {
|
||||
kprintf("Could not load module :(\n");
|
||||
return;
|
||||
}
|
||||
|
||||
kprintf("Module successfully loaded :)\n");
|
||||
|
||||
// Load native modules
|
||||
NativeModuleDef *mod = methods;
|
||||
while(mod->name != nullptr) {
|
||||
|
@ -175,155 +142,161 @@ extern "C" void vm_start()
|
|||
mod++;
|
||||
}
|
||||
|
||||
Method *main = module->method("main");
|
||||
if(main == nullptr) {
|
||||
kprintf("Script has no main method.\n");
|
||||
return;
|
||||
}
|
||||
String errorCode;
|
||||
if(module->validate(errorCode) == false) {
|
||||
kprintf("Module validation failed: \x12\x06%s\x12\x07\n", errorCode.str());
|
||||
return;
|
||||
}
|
||||
|
||||
main->invoke({ });
|
||||
Method *main = module->method("main");
|
||||
if(main == nullptr) {
|
||||
kprintf("Script has no main method.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
delete module;
|
||||
main->invoke({ });
|
||||
|
||||
delete module;
|
||||
}
|
||||
|
||||
|
||||
String fn()
|
||||
String strfn()
|
||||
{
|
||||
return String("keks");
|
||||
return String("keks");
|
||||
}
|
||||
|
||||
void put(Vector<int> &v)
|
||||
{
|
||||
kprintf("v[%d]: ", v.length());
|
||||
for(int i : v) { kprintf("%d,", i); }
|
||||
kprintf("\n");
|
||||
kprintf("v[%d]: ", v.length());
|
||||
for(int i : v) { kprintf("%d,", i); }
|
||||
kprintf("\n");
|
||||
}
|
||||
|
||||
void put(Vector<String> &v)
|
||||
{
|
||||
kprintf("v[%d]: ", v.length());
|
||||
for(String &s : v) { kprintf("[%s],", s.str()); }
|
||||
kprintf("\n");
|
||||
kprintf("v[%d]: ", v.length());
|
||||
for(String &s : v) { kprintf("[%s],", s.str()); }
|
||||
kprintf("\n");
|
||||
}
|
||||
|
||||
void put(Dictionary<int, int> &d)
|
||||
{
|
||||
kprintf("dict: ");
|
||||
for(auto &it : d)
|
||||
{
|
||||
kprintf("[%d -> %d] ", it.first, it.second);
|
||||
}
|
||||
kprintf("\n");
|
||||
kprintf("dict: ");
|
||||
for(auto &it : d)
|
||||
{
|
||||
kprintf("[%d -> %d] ", it.first, it.second);
|
||||
}
|
||||
kprintf("\n");
|
||||
}
|
||||
|
||||
void put(Dictionary<String, String> &d)
|
||||
{
|
||||
kprintf("dict: ");
|
||||
for(auto &it : d)
|
||||
{
|
||||
kprintf("[%s -> %s] ", it.first.str(), it.second.str());
|
||||
}
|
||||
kprintf("\n");
|
||||
kprintf("dict: ");
|
||||
for(auto &it : d)
|
||||
{
|
||||
kprintf("[%s -> %s] ", it.first.str(), it.second.str());
|
||||
}
|
||||
kprintf("\n");
|
||||
}
|
||||
|
||||
void cpp_test()
|
||||
{
|
||||
kprintf("Testing ker::String:\n");
|
||||
{
|
||||
String a("hello");
|
||||
String b(a);
|
||||
String c;
|
||||
String d(fn());
|
||||
String e;
|
||||
c = a;
|
||||
e = fn();
|
||||
kprintf("Testing ker::String:\n");
|
||||
{
|
||||
String a("hello");
|
||||
String b(a);
|
||||
String c;
|
||||
String d(strfn());
|
||||
String e;
|
||||
c = a;
|
||||
e = strfn();
|
||||
|
||||
kprintf("'%s' '%s' '%s' '%s' '%s'\n", a.str(), b.str(), c.str(), d.str(), e.str());
|
||||
}
|
||||
kprintf("'%s' '%s' '%s' '%s' '%s'\n", a.str(), b.str(), c.str(), d.str(), e.str());
|
||||
}
|
||||
|
||||
kprintf("Testing ker::Pair:\n");
|
||||
{
|
||||
Pair<int, int> a(10, 20);
|
||||
Pair<String, String> b("Hey", "Affe");
|
||||
kprintf("Testing ker::Pair:\n");
|
||||
{
|
||||
Pair<int, int> a(10, 20);
|
||||
Pair<String, String> b("Hey", "Affe");
|
||||
|
||||
Pair<int, int> c(a);
|
||||
Pair<String, String> d(b);
|
||||
Pair<int, int> c(a);
|
||||
Pair<String, String> d(b);
|
||||
|
||||
Pair<int, int> e; e = a;
|
||||
Pair<String, String> f; f = b;
|
||||
Pair<int, int> e; e = a;
|
||||
Pair<String, String> f; f = b;
|
||||
|
||||
kprintf("'%d,%d' '%d,%d' '%d,%d'\n", a.first, a.second, c.first, c.second, e.first, e.second);
|
||||
kprintf("'%s,%s' '%s,%s' '%s,%s'\n", b.first.str(), b.second.str(), d.first.str(), d.second.str(), f.first.str(), f.second.str());
|
||||
}
|
||||
kprintf("'%d,%d' '%d,%d' '%d,%d'\n", a.first, a.second, c.first, c.second, e.first, e.second);
|
||||
kprintf("'%s,%s' '%s,%s' '%s,%s'\n", b.first.str(), b.second.str(), d.first.str(), d.second.str(), f.first.str(), f.second.str());
|
||||
}
|
||||
|
||||
kprintf("Testing ker::Vector:\n");
|
||||
{
|
||||
Vector<int> a;
|
||||
a.append(1);
|
||||
a.append(2);
|
||||
a.append(3);
|
||||
kprintf("Testing ker::Vector:\n");
|
||||
{
|
||||
Vector<int> a;
|
||||
a.append(1);
|
||||
a.append(2);
|
||||
a.append(3);
|
||||
|
||||
Vector<int> c;
|
||||
Vector<int> b(a);
|
||||
c = a;
|
||||
Vector<int> c;
|
||||
Vector<int> b(a);
|
||||
c = a;
|
||||
|
||||
put(a);
|
||||
put(b);
|
||||
put(c);
|
||||
}
|
||||
{
|
||||
Vector<String> a;
|
||||
a.append("x");
|
||||
a.append("y");
|
||||
a.append("z");
|
||||
put(a);
|
||||
put(b);
|
||||
put(c);
|
||||
}
|
||||
{
|
||||
Vector<String> a;
|
||||
a.append("x");
|
||||
a.append("y");
|
||||
a.append("z");
|
||||
|
||||
Vector<String> c;
|
||||
Vector<String> b(a);
|
||||
c = a;
|
||||
Vector<String> c;
|
||||
Vector<String> b(a);
|
||||
c = a;
|
||||
|
||||
put(a);
|
||||
put(b);
|
||||
put(c);
|
||||
}
|
||||
put(a);
|
||||
put(b);
|
||||
put(c);
|
||||
}
|
||||
|
||||
kprintf("Testing ker::Dictionary:\n");
|
||||
{
|
||||
kprintf("int -> int\n");
|
||||
Dictionary<int, int> a;
|
||||
a.add(1, 30);
|
||||
a.add(2, 20);
|
||||
a.add(3, 10);
|
||||
kprintf("Testing ker::Dictionary:\n");
|
||||
{
|
||||
kprintf("int -> int\n");
|
||||
Dictionary<int, int> a;
|
||||
a.add(1, 30);
|
||||
a.add(2, 20);
|
||||
a.add(3, 10);
|
||||
|
||||
kprintf("%d %d\n", a.contains(1), a.contains(4));
|
||||
kprintf("%d %d\n", a.at(1), a.at(3));
|
||||
kprintf("%d %d\n", a[1], a[3]);
|
||||
kprintf("%d %d\n", a.contains(1), a.contains(4));
|
||||
kprintf("%d %d\n", a.at(1), a.at(3));
|
||||
kprintf("%d %d\n", a[1], a[3]);
|
||||
|
||||
Dictionary<int, int> b(a);
|
||||
Dictionary<int, int> c;
|
||||
c = a;
|
||||
Dictionary<int, int> b(a);
|
||||
Dictionary<int, int> c;
|
||||
c = a;
|
||||
|
||||
put(a);
|
||||
put(b);
|
||||
put(c);
|
||||
}
|
||||
put(a);
|
||||
put(b);
|
||||
put(c);
|
||||
}
|
||||
|
||||
{
|
||||
kprintf("String -> String\n");
|
||||
Dictionary<String, String> a;
|
||||
a.add("x", "30");
|
||||
a.add("y", "20");
|
||||
a.add("z", "10");
|
||||
{
|
||||
kprintf("String -> String\n");
|
||||
Dictionary<String, String> a;
|
||||
a.add("x", "30");
|
||||
a.add("y", "20");
|
||||
a.add("z", "10");
|
||||
|
||||
kprintf("%d %d\n", a.contains("x"), a.contains("w"));
|
||||
kprintf("%s %s\n", a.at("x").str(), a.at("z").str());
|
||||
kprintf("%s %s\n", a["x"].str(), a["z"].str());
|
||||
kprintf("%d %d\n", a.contains("x"), a.contains("w"));
|
||||
kprintf("%s %s\n", a.at("x").str(), a.at("z").str());
|
||||
kprintf("%s %s\n", a["x"].str(), a["z"].str());
|
||||
|
||||
Dictionary<String, String> b(a);
|
||||
Dictionary<String, String> c;
|
||||
c = a;
|
||||
Dictionary<String, String> b(a);
|
||||
Dictionary<String, String> c;
|
||||
c = a;
|
||||
|
||||
put(a);
|
||||
put(b);
|
||||
put(c);
|
||||
}
|
||||
put(a);
|
||||
put(b);
|
||||
put(c);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,331 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <timer.h>
|
||||
#include "../trainscript/tsvm.hpp"
|
||||
|
||||
using namespace ker;
|
||||
using namespace trainscript;
|
||||
|
||||
extern "C" {
|
||||
extern const char mainscript_start;
|
||||
extern const char mainscript_end;
|
||||
extern const char mainscript_size;
|
||||
}
|
||||
|
||||
void cpp_test();
|
||||
|
||||
class NativeMethod :
|
||||
public Method
|
||||
{
|
||||
private:
|
||||
void *function;
|
||||
public:
|
||||
NativeMethod(void *fn) :
|
||||
function(fn)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Variable invoke(Vector<Variable> arguments) override;
|
||||
|
||||
bool validate(ker::String &errorCode) const
|
||||
{
|
||||
if(this->function == nullptr) {
|
||||
errorCode = "Native method with nullptr interface.";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Vector<Type> arguments() const {
|
||||
return Vector<Type>();
|
||||
}
|
||||
|
||||
Type returnType() const {
|
||||
return Type::Int;
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
struct NativeModuleDef
|
||||
{
|
||||
const char *name;
|
||||
void *function;
|
||||
};
|
||||
|
||||
NativeModuleDef methods[] = {
|
||||
{ "sleep", (void*)sleep },
|
||||
{ "timer_get", (void*)timer_get },
|
||||
{ "timer_set", (void*)timer_set },
|
||||
{ nullptr, 0 }
|
||||
};
|
||||
|
||||
extern "C" void vm_start()
|
||||
{
|
||||
struct {
|
||||
const char *ptr;
|
||||
uint32_t size;
|
||||
} mainfile {
|
||||
&mainscript_start,
|
||||
(uint32_t)&mainscript_size
|
||||
};
|
||||
|
||||
// cpp_test();
|
||||
|
||||
kprintf("Parse kernel module: ");
|
||||
Module *module = VM::load(mainfile.ptr, mainfile.size);
|
||||
if(module == nullptr) {
|
||||
kprintf("Could not load module :(\n");
|
||||
return;
|
||||
}
|
||||
|
||||
kprintf("Module successfully loaded :)\n");
|
||||
|
||||
String errorCode;
|
||||
if(module->validate(errorCode) == false) {
|
||||
kprintf("Module validation failed: \x12\x06%s\x12\x07\n", errorCode.str());
|
||||
return;
|
||||
}
|
||||
|
||||
// Load native modules
|
||||
NativeModuleDef *mod = methods;
|
||||
while(mod->name != nullptr) {
|
||||
module->methods.add(mod->name, new NativeMethod(mod->function));
|
||||
mod++;
|
||||
}
|
||||
|
||||
Method *main = module->method("main");
|
||||
if(main == nullptr) {
|
||||
kprintf("Script has no main method.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
main->invoke({ });
|
||||
|
||||
delete module;
|
||||
}
|
||||
|
||||
|
||||
String fn()
|
||||
{
|
||||
return String("keks");
|
||||
}
|
||||
|
||||
void put(Vector<int> &v)
|
||||
{
|
||||
kprintf("v[%d]: ", v.length());
|
||||
for(int i : v) { kprintf("%d,", i); }
|
||||
kprintf("\n");
|
||||
}
|
||||
|
||||
void put(Vector<String> &v)
|
||||
{
|
||||
kprintf("v[%d]: ", v.length());
|
||||
for(String &s : v) { kprintf("[%s],", s.str()); }
|
||||
kprintf("\n");
|
||||
}
|
||||
|
||||
void put(Dictionary<int, int> &d)
|
||||
{
|
||||
kprintf("dict: ");
|
||||
for(auto &it : d)
|
||||
{
|
||||
kprintf("[%d -> %d] ", it.first, it.second);
|
||||
}
|
||||
kprintf("\n");
|
||||
}
|
||||
|
||||
void put(Dictionary<String, String> &d)
|
||||
{
|
||||
kprintf("dict: ");
|
||||
for(auto &it : d)
|
||||
{
|
||||
kprintf("[%s -> %s] ", it.first.str(), it.second.str());
|
||||
}
|
||||
kprintf("\n");
|
||||
}
|
||||
|
||||
void cpp_test()
|
||||
{
|
||||
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("Testing ker::Pair:\n");
|
||||
{
|
||||
Pair<int, int> a(10, 20);
|
||||
Pair<String, String> b("Hey", "Affe");
|
||||
|
||||
Pair<int, int> c(a);
|
||||
Pair<String, String> d(b);
|
||||
|
||||
Pair<int, int> e; e = a;
|
||||
Pair<String, String> f; f = b;
|
||||
|
||||
kprintf("'%d,%d' '%d,%d' '%d,%d'\n", a.first, a.second, c.first, c.second, e.first, e.second);
|
||||
kprintf("'%s,%s' '%s,%s' '%s,%s'\n", b.first.str(), b.second.str(), d.first.str(), d.second.str(), f.first.str(), f.second.str());
|
||||
}
|
||||
|
||||
kprintf("Testing ker::Vector:\n");
|
||||
{
|
||||
Vector<int> a;
|
||||
a.append(1);
|
||||
a.append(2);
|
||||
a.append(3);
|
||||
|
||||
Vector<int> c;
|
||||
Vector<int> b(a);
|
||||
c = a;
|
||||
|
||||
put(a);
|
||||
put(b);
|
||||
put(c);
|
||||
}
|
||||
{
|
||||
Vector<String> a;
|
||||
a.append("x");
|
||||
a.append("y");
|
||||
a.append("z");
|
||||
|
||||
Vector<String> c;
|
||||
Vector<String> b(a);
|
||||
c = a;
|
||||
|
||||
put(a);
|
||||
put(b);
|
||||
put(c);
|
||||
}
|
||||
|
||||
kprintf("Testing ker::Dictionary:\n");
|
||||
{
|
||||
kprintf("int -> int\n");
|
||||
Dictionary<int, int> a;
|
||||
a.add(1, 30);
|
||||
a.add(2, 20);
|
||||
a.add(3, 10);
|
||||
|
||||
kprintf("%d %d\n", a.contains(1), a.contains(4));
|
||||
kprintf("%d %d\n", a.at(1), a.at(3));
|
||||
kprintf("%d %d\n", a[1], a[3]);
|
||||
|
||||
Dictionary<int, int> b(a);
|
||||
Dictionary<int, int> c;
|
||||
c = a;
|
||||
|
||||
put(a);
|
||||
put(b);
|
||||
put(c);
|
||||
}
|
||||
|
||||
{
|
||||
kprintf("String -> String\n");
|
||||
Dictionary<String, String> a;
|
||||
a.add("x", "30");
|
||||
a.add("y", "20");
|
||||
a.add("z", "10");
|
||||
|
||||
kprintf("%d %d\n", a.contains("x"), a.contains("w"));
|
||||
kprintf("%s %s\n", a.at("x").str(), a.at("z").str());
|
||||
kprintf("%s %s\n", a["x"].str(), a["z"].str());
|
||||
|
||||
Dictionary<String, String> b(a);
|
||||
Dictionary<String, String> c;
|
||||
c = a;
|
||||
|
||||
put(a);
|
||||
put(b);
|
||||
put(c);
|
||||
}
|
||||
}
|
|
@ -38,7 +38,8 @@ HEADERS += \
|
|||
include/ker/vector.hpp \
|
||||
include/ker/dictionary.hpp \
|
||||
include/string.h \
|
||||
include/ker/new.hpp
|
||||
include/ker/new.hpp \
|
||||
include/dynamic.h
|
||||
|
||||
DISTFILES += \
|
||||
asm/intr_common_handler.S \
|
||||
|
@ -54,7 +55,8 @@ DISTFILES += \
|
|||
kernel.ld \
|
||||
Depfile \
|
||||
Makefile.new \
|
||||
scripts/main.ts
|
||||
scripts/main.ts \
|
||||
asm/dynamic.S
|
||||
|
||||
QMAKE_INCDIR =
|
||||
|
||||
|
|
Loading…
Reference in a new issue