From 3c4b1864c71cb5cd3c9f9f797b786b2f3bac42df Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Sat, 10 Mar 2018 00:27:16 -0500 Subject: [PATCH] Add in addi to reduce use of imm, add and or and not to put in negate/subtract (might need it's own opcode, really) as well as and or and not themselves --- stdlib/bytecode_generator.krak | 103 ++++++++++++++++++++++++++++----- 1 file changed, 88 insertions(+), 15 deletions(-) diff --git a/stdlib/bytecode_generator.krak b/stdlib/bytecode_generator.krak index 117fdda..47b9c70 100644 --- a/stdlib/bytecode_generator.krak +++ b/stdlib/bytecode_generator.krak @@ -90,6 +90,10 @@ adt byte_inst { nop, imm: imm, add: add, + addi: addi, + and: and, + or: or, + not: not, ldr: ldr, str: str, jmp: jmp, @@ -106,6 +110,25 @@ obj add { var a: int var b: int } +obj addi { + var to_reg: int + var a: int + var bi:long +} +obj and { + var to_reg: int + var a: int + var b: int +} +obj or { + var to_reg: int + var a: int + var b: int +} +obj not { + var to_reg: int + var a: int +} obj ldr { var to_reg: int var from_reg: int @@ -144,11 +167,15 @@ fun to_string(b: byte_inst): string { byte_inst::nop() return string("nop") byte_inst::imm(i) return string("r") + i.reg + " = imm " + i.val byte_inst::add(a) return string("r") + a.to_reg + " = r" + a.a + " + r" + a.b + byte_inst::addi(a) return string("r") + a.to_reg + " = r" + a.a + " + " + a.bi + byte_inst::and(a) return string("r") + a.to_reg + " = r" + a.a + " & " + a.b + byte_inst::or(a) return string("r") + a.to_reg + " = r" + a.a + " | " + a.b + byte_inst::not(a) return string("r") + a.to_reg + " = ~r" + a.a byte_inst::ldr(l) return string("r") + l.to_reg + " = ldr" + to_string(l.size) + " r" + l.from_reg + " (" + l.offset + ")" byte_inst::str(s) return "str" + to_string(s.size) + " (r" + s.to_reg + "(" + s.offset + ") <= r" + s.from_reg + ")" byte_inst::jmp(j) return string("jmp(pc += ") + j.offset + ")" byte_inst::jz(j) return string("jmp(r") + j.reg + " == 0, pc += " + j.offset + ")" - byte_inst::call(c) return string("call pc = r") + c.reg + byte_inst::call(c) return string("call pc = r") + c.reg byte_inst::ret() return string("ret") } return string("Missed byte_inst case in to_string") @@ -322,16 +349,16 @@ obj bytecode_generator (Object) { functions.last().var_to_frame_offset[p] = parameter_offset parameter_offset += type_size(p->identifier.type) }) - emit_add(0, 0, emit_imm(-register_size)) // these two lines push rbp onto the stack, which grows towards negative + emit_addi(0, 0, -register_size) // these two lines push rbp onto the stack, which grows towards negative emit_str(0, 0, 1, operand_size::b64()) // rsp[0] <= rbp - emit_add(1, 0, emit_imm(0)) // note that we start the frame size at register_size for this reason + emit_addi(1, 0, 0) // note that we start the frame size at register_size for this reason var push_frame_idx = instructions.size - emit_add(0, 0, emit_imm(0)) // this has to be fixed afterwards to be the -frame_size + emit_addi(0, 0, 0) // this has to be fixed afterwards to be the -frame_size generate(node->function.body_statement) - instructions[push_frame_idx].imm.val = -functions.last().frame_size + instructions[push_frame_idx].addi.bi = -functions.last().frame_size return -1 } @@ -385,16 +412,15 @@ obj bytecode_generator (Object) { } fun generate_identifier(node: *ast_node, lvalue: bool): int { if (lvalue) { - return emit_add(1, emit_imm(functions.last().var_to_frame_offset[node])) + return emit_addi(1, functions.last().var_to_frame_offset[node]) } else { return emit_ldr(1, functions.last().var_to_frame_offset[node], size_to_operand_size(type_size(get_ast_type(node)))) } } fun generate_return_statement(node: *ast_node): int { if (node->return_statement.return_value) { - /*emit_str(1, register_size, generate(node->return_statement.return_value))*/ - emit_add(2, emit_imm(0), generate(node->return_statement.return_value)) - emit_add(0, 1, emit_imm(register_size)) + emit_addi(2, generate(node->return_statement.return_value), 0) + emit_addi(0, 1, register_size) emit_ldr(1, 1, 0, operand_size::b64()) emit_ret() } else { @@ -442,7 +468,10 @@ obj bytecode_generator (Object) { else return emit_add(params[0], params[1]) } else if (name == "-") { - error("subtract/negate not supported") + if (params.size == 1) + return emit_addi(emit_not(params[0]), 1) + else + return emit_add(params[0], emit_addi(emit_not(params[1]), 1)) } else if (name == "!") { error("not not supported") } else if (name == "--" || name == "++" || name == "--p" || name == "++p") { @@ -452,6 +481,9 @@ obj bytecode_generator (Object) { } else if (name == "==" || name == "<=" || name == ">=" || name == "!=" || name == "<" || name == ">") { error("comparator operators are not supported") } else if (name == "|" || (name == "&" && params.size == 2) || name == "^" || name == "~") { + if (name == "|") return emit_or(params[0], params[1]) + if (name == "&") return emit_and(params[0], params[1]) + if (name == "~") return emit_not(params[0]) error("bitwise operators are not supported") } else if (name == ">>" || name == "<<") { error("shift operators are not supported") @@ -466,12 +498,12 @@ obj bytecode_generator (Object) { node->function_call.parameters.reverse().for_each(fun(child: *ast_node) { // push param onto stack var param_size = type_size(get_ast_type(child)) - emit_add(0, 0, emit_imm(-param_size)) + emit_addi(0, 0, -param_size) stack_offset += param_size emit_str(0, 0, generate(child), size_to_operand_size(param_size)) }) var return_reg = emit_call(generate_function(node->function_call.func)) - emit_add(0, 0, emit_imm(stack_offset)) + emit_addi(0, 0, stack_offset) return return_reg } } @@ -519,9 +551,7 @@ obj bytecode_generator (Object) { instructions.add(byte_inst::imm(i)) return i.reg } - fun emit_add(a: int, b: int): int { - return emit_add(get_reg(), a, b) - } + fun emit_add(a: int, b: int): int { return emit_add(get_reg(), a, b); } fun emit_add(dest: int, a: int, b: int): int { var i: add i.to_reg = dest @@ -530,6 +560,45 @@ obj bytecode_generator (Object) { instructions.add(byte_inst::add(i)) return i.to_reg } + fun emit_addi(a: int, bi: long): int { return emit_addi(get_reg(), a, bi); } + fun emit_addi(a: int, bi: int): int { return emit_addi(get_reg(), a, (bi) cast long); } + fun emit_addi(dest: int, a: int, bi: int): int { return emit_addi(dest, a, (bi) cast long); } + fun emit_addi(a: int, bi: ulong): int { return emit_addi(get_reg(), a, (bi) cast long); } + fun emit_addi(dest: int, a: int, bi: ulong): int { return emit_addi(dest, a, (bi) cast long); } + fun emit_addi(dest: int, a: int, bi: long): int { + var i: addi + i.to_reg = dest + i.a = a + i.bi = bi + instructions.add(byte_inst::addi(i)) + return i.to_reg + } + fun emit_and(a: int, b: int): int { return emit_and(get_reg(), a, b); } + fun emit_and(dest: int, a: int, b: int): int { + var i: and + i.to_reg = dest + i.a = a + i.b = b + instructions.add(byte_inst::and(i)) + return i.to_reg + } + fun emit_or(a: int, b: int): int { return emit_or(get_reg(), a, b); } + fun emit_or(dest: int, a: int, b: int): int { + var i: or + i.to_reg = dest + i.a = a + i.b = b + instructions.add(byte_inst::or(i)) + return i.to_reg + } + fun emit_not(a: int): int { return emit_not(get_reg(), a); } + fun emit_not(dest: int, a: int): int { + var i: not + i.to_reg = dest + i.a = a + instructions.add(byte_inst::not(i)) + return i.to_reg + } fun emit_ldr(reg: int, offset: int, size: operand_size): int { return emit_ldr(get_reg(), reg, offset, size); } fun emit_ldr(dest: int, reg: int, offset: int, size: operand_size): int { var l: ldr @@ -593,6 +662,10 @@ obj bytecode_generator (Object) { byte_inst::nop() {} byte_inst::imm(i) registers[i.reg] = i.val byte_inst::add(a) registers[a.to_reg] = registers[a.a] + registers[a.b] + byte_inst::addi(a) registers[a.to_reg] = registers[a.a] + a.bi + byte_inst::and(a) registers[a.to_reg] = registers[a.a] & registers[a.b] + byte_inst::or(a) registers[a.to_reg] = registers[a.a] | registers[a.b] + byte_inst::not(a) registers[a.to_reg] = ~registers[a.a] byte_inst::ldr(l) match (l.size) { operand_size::b8() registers[l.to_reg] = *(stack + registers[l.from_reg] + l.offset) cast *char operand_size::b16() registers[l.to_reg] = *(stack + registers[l.from_reg] + l.offset) cast *short