Add in calling of external functions (malloc and free for now), move memory addresses to be real memeory addresses, add support for sizeof compiler intrinsic
This commit is contained in:
@@ -73,6 +73,9 @@ fun offset_into_struct(struct_type: *type, ident: *ast_node): ulong {
|
||||
}
|
||||
|
||||
var register_size = #sizeof<*void>
|
||||
var malloc_addr = -1
|
||||
var free_addr = -2
|
||||
|
||||
adt operand_size {
|
||||
b8,
|
||||
b16,
|
||||
@@ -345,14 +348,27 @@ obj bytecode_generator (Object) {
|
||||
})
|
||||
})
|
||||
fixup_function_addresses.for_each(fun(p: pair<int, *ast_node>) {
|
||||
instructions[p.first].imm.val = functions[node_function_idx[p.second]].instruction_start
|
||||
if (p.second->function.is_extern) {
|
||||
if (p.second->function.name == "malloc")
|
||||
instructions[p.first].imm.val = malloc_addr
|
||||
else if (p.second->function.name == "free")
|
||||
instructions[p.first].imm.val = free_addr
|
||||
else
|
||||
error("bad extern function used: " + p.second->function.name)
|
||||
} else {
|
||||
instructions[p.first].imm.val = functions[node_function_idx[p.second]].instruction_start
|
||||
}
|
||||
})
|
||||
for (var i = 0; i < functions.size - 1; i++;)
|
||||
functions[i].instruction_end = functions[i+1].instruction_start
|
||||
functions.last().instruction_end = instructions.size
|
||||
/*return make_pair(functions, instructions)*/
|
||||
}
|
||||
fun generate_function_definition(node: *ast_node): int {
|
||||
fun generate_function_definition(node: *ast_node) {
|
||||
if (node->function.is_extern) {
|
||||
println("Skipping extern function " + node->function.name)
|
||||
return
|
||||
}
|
||||
reset_reg()
|
||||
node_function_idx[node] = functions.size
|
||||
functions.add(bytecode_function(get_name(node), instructions.size))
|
||||
@@ -381,7 +397,6 @@ obj bytecode_generator (Object) {
|
||||
|
||||
instructions[push_frame_idx].addi.bi = -functions.last().frame_size
|
||||
|
||||
return -1
|
||||
}
|
||||
fun generate_declaration_statement(node: *ast_node): int {
|
||||
var identifier = node->declaration_statement.identifier
|
||||
@@ -553,7 +568,7 @@ obj bytecode_generator (Object) {
|
||||
}
|
||||
fun generate_function_call(node: *ast_node, lvalue: bool): int {
|
||||
var func = node->function_call.func
|
||||
if (is_function(func) && func->function.body_statement == null<ast_node>()) {
|
||||
if (is_function(func) && !func->function.is_extern && func->function.body_statement == null<ast_node>()) {
|
||||
var name = func->function.name
|
||||
var parameter_nodes = node->function_call.parameters
|
||||
// generate with lvalue=true to make return a pointer
|
||||
@@ -732,8 +747,12 @@ obj bytecode_generator (Object) {
|
||||
}
|
||||
|
||||
fun generate_compiler_intrinsic(node: *ast_node): int {
|
||||
instructions.add(byte_inst::nop())
|
||||
return -1
|
||||
if (node->compiler_intrinsic.intrinsic == "sizeof") {
|
||||
if (node->compiler_intrinsic.parameters.size || node->compiler_intrinsic.type_parameters.size != 1)
|
||||
error("wrong parameters to sizeof compiler intrinsic")
|
||||
return emit_imm(type_size(node->compiler_intrinsic.type_parameters[0]))
|
||||
}
|
||||
error("bad compiler intrinsic " + node->compiler_intrinsic.intrinsic)
|
||||
}
|
||||
|
||||
fun generate(node: *ast_node): int return generate(node, false)
|
||||
@@ -977,12 +996,13 @@ obj bytecode_generator (Object) {
|
||||
var main_entry = functions.find_first_satisfying(fun(block: bytecode_function): bool return block.name == "main";)
|
||||
var registers.construct(reg_max): vector<long>
|
||||
registers.size = reg_max
|
||||
registers[0] = -register_size // with the stack being zeroed out, this makes it a return address of 0
|
||||
registers[1] = 0xdeadbeefcafebabe
|
||||
var stack_size = 8 * 1024 * 1024
|
||||
var got_malloc = null<void>()
|
||||
var stack = new<uchar>(stack_size) + stack_size
|
||||
for (var i = 0; i < stack_size; i++;)
|
||||
stack[-i + -1] = 0
|
||||
registers[0] = (stack-register_size) cast long // with the stack being zeroed out, this makes it a return address of 0
|
||||
for (var i = main_entry.instruction_start; i < instructions.size; i++;) {
|
||||
println(string("evaling: ") + i + ": " + to_string(instructions[i]))
|
||||
match(instructions[i]) {
|
||||
@@ -1006,41 +1026,56 @@ obj bytecode_generator (Object) {
|
||||
byte_inst::lz(a) registers[a.to_reg] = registers[a.a] < 0
|
||||
byte_inst::ez(a) registers[a.to_reg] = registers[a.a] == 0
|
||||
byte_inst::ldr(l) match (l.size) {
|
||||
operand_size::b8() registers[l.reg] = *(stack + registers[l.base_reg] + l.offset) cast *char
|
||||
operand_size::b16() registers[l.reg] = *(stack + registers[l.base_reg] + l.offset) cast *short
|
||||
operand_size::b32() registers[l.reg] = *(stack + registers[l.base_reg] + l.offset) cast *int
|
||||
operand_size::b64() registers[l.reg] = *(stack + registers[l.base_reg] + l.offset) cast *long
|
||||
operand_size::b8() registers[l.reg] = *(registers[l.base_reg] + l.offset) cast *char
|
||||
operand_size::b16() registers[l.reg] = *(registers[l.base_reg] + l.offset) cast *short
|
||||
operand_size::b32() registers[l.reg] = *(registers[l.base_reg] + l.offset) cast *int
|
||||
operand_size::b64() registers[l.reg] = *(registers[l.base_reg] + l.offset) cast *long
|
||||
}
|
||||
byte_inst::str(s) match (s.size) {
|
||||
operand_size::b8() *(stack + registers[s.base_reg] + s.offset) cast *uchar = registers[s.reg]
|
||||
operand_size::b16() *(stack + registers[s.base_reg] + s.offset) cast *ushort = registers[s.reg]
|
||||
operand_size::b32() *(stack + registers[s.base_reg] + s.offset) cast *uint = registers[s.reg]
|
||||
operand_size::b64() *(stack + registers[s.base_reg] + s.offset) cast *ulong = registers[s.reg]
|
||||
operand_size::b8() *(registers[s.base_reg] + s.offset) cast *uchar = registers[s.reg]
|
||||
operand_size::b16() *(registers[s.base_reg] + s.offset) cast *ushort = registers[s.reg]
|
||||
operand_size::b32() *(registers[s.base_reg] + s.offset) cast *uint = registers[s.reg]
|
||||
operand_size::b64() *(registers[s.base_reg] + s.offset) cast *ulong = registers[s.reg]
|
||||
}
|
||||
byte_inst::jmp(offset) i += offset - 1 // to counteract pc inc
|
||||
byte_inst::jz(j) if (registers[j.reg] == 0)
|
||||
i += j.offset - 1 // to counteract pc inc
|
||||
byte_inst::call(c) {
|
||||
/*registers[0] -= register_size*/
|
||||
registers[0] = registers[0] - register_size
|
||||
*(stack + registers[0]) cast *long = i + 1
|
||||
i = registers[c] - 1
|
||||
print("call!")
|
||||
println("first part of memory is (after push)")
|
||||
for (var i = 0; i < 8*8; i+=8;) {
|
||||
print(string("-") + i + string(": "))
|
||||
for (var j = 0; j < 8; j++;) {
|
||||
if (j == 4)
|
||||
var func_start = registers[c]
|
||||
// extern call
|
||||
if (func_start < 0) {
|
||||
if (func_start == malloc_addr)
|
||||
/*registers[2] = (malloc(*(stack + registers[0]) cast *ulong)) cast long*/
|
||||
{
|
||||
got_malloc = malloc(*(registers[0]) cast *ulong)
|
||||
registers[2] = (got_malloc) cast long
|
||||
}
|
||||
else if (func_start == free_addr)
|
||||
free(*(registers[0]) cast **void)
|
||||
else
|
||||
error(string("bad extern call number") + func_start)
|
||||
} else {
|
||||
/*registers[0] -= register_size*/
|
||||
registers[0] = registers[0] - register_size
|
||||
*(registers[0]) cast *long = i + 1
|
||||
i = func_start - 1
|
||||
print("call!")
|
||||
println("first part of memory is (after push)")
|
||||
for (var i = 0; i < 8*8; i+=8;) {
|
||||
print(string("-") + i + string(": "))
|
||||
for (var j = 0; j < 8; j++;) {
|
||||
if (j == 4)
|
||||
print(" ")
|
||||
print(*(stack - (i+j)*#sizeof<uchar> - 1) cast *uchar)
|
||||
print(" ")
|
||||
print(*(stack - (i+j)*#sizeof<uchar> - 1) cast *uchar)
|
||||
print(" ")
|
||||
}
|
||||
println()
|
||||
}
|
||||
println()
|
||||
println("Done")
|
||||
}
|
||||
println("Done")
|
||||
}
|
||||
byte_inst::ret() {
|
||||
var pc = *(stack + registers[0]) cast *long
|
||||
var pc = *(registers[0]) cast *long
|
||||
/*registers[0] += register_size*/
|
||||
registers[0] = registers[0] + register_size
|
||||
print("returning! return value is\n\t")
|
||||
@@ -1059,6 +1094,7 @@ obj bytecode_generator (Object) {
|
||||
}
|
||||
println("Done")
|
||||
if (pc == 0) {
|
||||
println(string("got malloc is ") + *(got_malloc) cast *int)
|
||||
return value
|
||||
} else {
|
||||
i = pc - 1
|
||||
|
||||
Reference in New Issue
Block a user