diff options
-rw-r--r-- | 05/codegen.b | 188 | ||||
-rw-r--r-- | 05/main.b | 5 | ||||
-rw-r--r-- | 05/main.c | 2 | ||||
-rw-r--r-- | markdown.c | 1 |
4 files changed, 152 insertions, 44 deletions
diff --git a/05/codegen.b b/05/codegen.b index d1bd9ad..0d70f37 100644 --- a/05/codegen.b +++ b/05/codegen.b @@ -106,6 +106,12 @@ function emit_zero_rax code_output += 2 return +function emit_zero_rdx + ; 31 d2 + *2code_output = 0xd231 + code_output += 2 + return + function emit_movsx_rax_al ; 48 0f be c0 *4code_output = 0xc0be0f48 @@ -582,7 +588,7 @@ function generate_cast_top_of_stack c = type_sizeof(*1from) d = type_sizeof(*1to) if d > c goto return_0 ; casting to bigger type, so we're good - if d == 8 goto return_0 ; casting from unsigned/signed long to unsigned/signed long, we're good + if d == 8 goto return_0 ; casting from unsigned/signed long to unsigned/signed long/pointer, we're good ; mov rax, [rsp] emit_mov_rax_qword_rsp() @@ -729,7 +735,6 @@ function generate_push_expression_casted from_type = expr + 4 from_type = *4from_type - expr = generate_push_expression(statement, expr) generate_cast_top_of_stack(statement, from_type, to_type) return expr @@ -751,6 +756,134 @@ function scale_rax_for_addition_with emit_mul_rbx() return +; pop the top two things off of the stack, and push their sum +; the things should both have type `out_type` on the stack, but their original types are given by type1,2 +function generate_stack_add + argument statement ; for errors (currently unused) + argument type1 ; type of 1st operand + argument type2 ; type of 2nd operand + argument out_type + + + out_type += types + if *1out_type == TYPE_FLOAT goto generate_add_floats + if *1out_type == TYPE_DOUBLE goto generate_add_doubles + + emit_mov_rax_qword_rsp_plus_imm32(0) ; mov rax, [rsp] (second operand) + scale_rax_for_addition_with(type1) ; in case this is a pointer addition + emit_mov_reg(REG_RSI, REG_RAX) ; mov rsi, rax + emit_mov_rax_qword_rsp_plus_imm32(8) ; mov rax, [rsp+8] (first operand) + scale_rax_for_addition_with(type2) ; in case this is a pointer addition + emit_mov_reg(REG_RBX, REG_RSI) ; mov rbx, rsi + emit_add_rax_rbx() ; add rax, rbx + emit_add_rsp_imm32(8) ; add rsp, 8 + emit_mov_qword_rsp_rax() ; mov [rsp], rax + return + + :generate_add_floats + emit_mov_rax_qword_rsp_plus_imm32(0) ; mov rax, [rsp] (second operand) + emit_movq_xmm0_rax() ; movq xmm0, rax + emit_cvtss2sd_xmm0_xmm0() ; cvtss2sd xmm0, xmm0 + emit_movq_xmm1_xmm0() ; movq xmm1, xmm0 + emit_mov_rax_qword_rsp_plus_imm32(8) ; mov rax, [rsp+8] (first operand) + emit_movq_xmm0_rax() ; movq xmm0, rax + emit_addsd_xmm0_xmm1() ; addsd xmm0, xmm1 + emit_cvtsd2ss_xmm0_xmm0() ; cvtsd2ss xmm0, xmm0 + emit_movq_rax_xmm0() ; movq rax, xmm0 + emit_add_rsp_imm32(8) ; add rsp, 8 + emit_mov_qword_rsp_rax() ; mov [rsp], rax + return + + :generate_add_doubles + emit_mov_rax_qword_rsp_plus_imm32(0) ; mov rax, [rsp] (second operand) + emit_movq_xmm1_rax() ; movq xmm1, rax + emit_mov_rax_qword_rsp_plus_imm32(8) ; mov rax, [rsp+8] (first operand) + emit_movq_xmm0_rax() ; movq xmm0, rax + emit_addsd_xmm0_xmm1() ; addsd xmm0, xmm1 + emit_movq_rax_xmm0() ; movq rax, xmm0 + emit_add_rsp_imm32(8) ; add rsp, 8 + emit_mov_qword_rsp_rax() ; mov [rsp], rax + return + +; pop the top two things off of the stack, and push their difference +; the things should both have type `out_type` on the stack, but their original types are given by type1,2 +function generate_stack_sub + argument statement ; for errors + argument type1 ; type of 1st operand + argument type2 ; type of 2nd operand + argument out_type + local p + + p = types + out_type + if *1p == TYPE_FLOAT goto generate_sub_floats + if *1p == TYPE_DOUBLE goto generate_sub_doubles + p = types + type2 + if *1p == TYPE_POINTER goto generate_sub_pointers + + emit_mov_rax_qword_rsp_plus_imm32(0) ; mov rax, [rsp] (second operand) + scale_rax_for_addition_with(type1) ; in case this is a pointer - integer subtraction + emit_mov_reg(REG_RSI, REG_RAX) ; mov rsi, rax + emit_mov_rax_qword_rsp_plus_imm32(8) ; mov rax, [rsp+8] (first operand) + emit_mov_reg(REG_RBX, REG_RSI) ; mov rbx, rsi + emit_sub_rax_rbx() ; sub rax, rbx + emit_add_rsp_imm32(8) ; add rsp, 8 + emit_mov_qword_rsp_rax() ; mov [rsp], rax + return + + :generate_sub_pointers + ; pointer difference - need to divide by object size + local sz1 + local sz2 + p = types + type1 + if *1p != TYPE_POINTER goto bad_pointer_diff + p = type1 + 1 + sz1 = type_sizeof(p) + p = type2 + 1 + sz2 = type_sizeof(p) + if sz1 != sz2 goto bad_pointer_diff + + emit_mov_rax_qword_rsp_plus_imm32(0) ; mov rax, [rsp] (second operand) + emit_mov_reg(REG_RSI, REG_RAX) ; mov rsi, rax + emit_mov_rax_qword_rsp_plus_imm32(8) ; mov rax, [rsp+8] (first operand) + emit_mov_reg(REG_RBX, REG_RSI) ; mov rbx, rsi + emit_sub_rax_rbx() ; sub rax, rbx + emit_add_rsp_imm32(8) ; add rsp, 8 + emit_mov_rbx_imm64(sz1) ; mov rbx, (object size) + emit_zero_rdx() ; xor edx, edx + emit_div_rbx() ; div rbx + emit_mov_qword_rsp_rax() ; mov [rsp], rax + return + + :bad_pointer_diff + statement_error(statement, .str_bad_pointer_diff) + :str_bad_pointer_diff + string Subtraction of incompatible pointer types. + byte 0 + :generate_sub_floats + emit_mov_rax_qword_rsp_plus_imm32(0) ; mov rax, [rsp] (second operand) + emit_movq_xmm0_rax() ; movq xmm0, rax + emit_cvtss2sd_xmm0_xmm0() ; cvtss2sd xmm0, xmm0 + emit_movq_xmm1_xmm0() ; movq xmm1, xmm0 + emit_mov_rax_qword_rsp_plus_imm32(8) ; mov rax, [rsp+8] (first operand) + emit_movq_xmm0_rax() ; movq xmm0, rax + emit_subsd_xmm0_xmm1() ; subsd xmm0, xmm1 + emit_cvtsd2ss_xmm0_xmm0() ; cvtsd2ss xmm0, xmm0 + emit_movq_rax_xmm0() ; movq rax, xmm0 + emit_add_rsp_imm32(8) ; add rsp, 8 + emit_mov_qword_rsp_rax() ; mov [rsp], rax + return + + :generate_sub_doubles + emit_mov_rax_qword_rsp_plus_imm32(0) ; mov rax, [rsp] (second operand) + emit_movq_xmm1_rax() ; movq xmm1, rax + emit_mov_rax_qword_rsp_plus_imm32(8) ; mov rax, [rsp+8] (first operand) + emit_movq_xmm0_rax() ; movq xmm0, rax + emit_subsd_xmm0_xmm1() ; subsd xmm0, xmm1 + emit_movq_rax_xmm0() ; movq rax, xmm0 + emit_add_rsp_imm32(8) ; add rsp, 8 + emit_mov_qword_rsp_rax() ; mov [rsp], rax + return + ; `statement` is used for errors ; returns pointer to end of expression function generate_push_expression @@ -772,6 +905,7 @@ function generate_push_expression if c == EXPRESSION_BITWISE_NOT goto generate_unary_bitwise_not if c == EXPRESSION_LOGICAL_NOT goto generate_unary_logical_not if c == EXPRESSION_ADD goto generate_add + if c == EXPRESSION_SUB goto generate_sub die(.str_genpushexprNI) :str_genpushexprNI @@ -819,48 +953,16 @@ function generate_push_expression expr = generate_push_expression_casted(statement, expr, type) d = expr + 4 ; type of 2nd operand expr = generate_push_expression_casted(statement, expr, type) - p = types + type - if *1p == TYPE_FLOAT goto generate_add_floats - if *1p == TYPE_DOUBLE goto generate_add_doubles - c = *4c - d = *4d - - emit_mov_rax_qword_rsp_plus_imm32(8) ; mov rax, [rsp+8] (first operand) - scale_rax_for_addition_with(d) ; in case this is a pointer addition - emit_mov_reg(REG_RSI, REG_RAX) ; store away 2nd operand in rsi - emit_mov_rax_qword_rsp_plus_imm32(0) ; mov rax, [rsp] (second operand) - scale_rax_for_addition_with(c) ; in case this is a pointer addition - emit_mov_reg(REG_RBX, REG_RSI) ; put 1st operand in rbx - emit_add_rax_rbx() - emit_add_rsp_imm32(8) ; add rsp, 8 - emit_mov_qword_rsp_rax() ; mov [rsp], rax + generate_stack_add(statement, *4c, *4d, type) + return expr + :generate_sub + expr += 8 + c = expr + 4 ; type of 1st operand + expr = generate_push_expression_casted(statement, expr, type) + d = expr + 4 ; type of 2nd operand + expr = generate_push_expression_casted(statement, expr, type) + generate_stack_sub(statement, *4c, *4d, type) return expr - - :generate_add_floats - emit_mov_rax_qword_rsp_plus_imm32(0) ; mov rax, [rsp] (second operand) - emit_movq_xmm0_rax() ; movq xmm0, rax - emit_cvtss2sd_xmm0_xmm0() ; cvtss2sd xmm0, xmm0 - emit_movq_xmm1_xmm0() ; movq xmm1, xmm0 - emit_mov_rax_qword_rsp_plus_imm32(8) ; mov rax, [rsp+8] (first operand) - emit_movq_xmm0_rax() ; movq xmm0, rax - emit_addsd_xmm0_xmm1() ; addsd xmm0, xmm1 - emit_cvtsd2ss_xmm0_xmm0() ; cvtsd2ss xmm0, xmm0 - emit_movq_rax_xmm0() ; movq rax, xmm0 - emit_add_rsp_imm32(8) ; add rsp, 8 - emit_mov_qword_rsp_rax() ; mov [rsp], rax - return expr - - :generate_add_doubles - emit_mov_rax_qword_rsp_plus_imm32(0) ; mov rax, [rsp] (second operand) - emit_movq_xmm1_rax() ; movq xmm1, rax - emit_mov_rax_qword_rsp_plus_imm32(8) ; mov rax, [rsp+8] (first operand) - emit_movq_xmm0_rax() ; movq xmm0, rax - emit_addsd_xmm0_xmm1() ; addsd xmm0, xmm1 - emit_movq_rax_xmm0() ; movq rax, xmm0 - emit_add_rsp_imm32(8) ; add rsp, 8 - emit_mov_qword_rsp_rax() ; mov [rsp], rax - return expr - :generate_unary_logical_not expr += 8 p = expr + 4 @@ -160,6 +160,11 @@ function token_error line = *4p compile_error(file, line, message) +function statement_error + argument statement + argument message + token_error(statement, message) ; tokens & statements have the same location format + ; accepts EITHER file index OR pointer to filename function compile_warning argument file @@ -1,3 +1,3 @@ long main(int argc, char **argv) { - return -(3.5+2.5); + return (double*)808 - (double*)792; } @@ -214,4 +214,5 @@ int main(int argc, char **argv) { } fprintf(out, "</p>\n</body>\n</html>\n"); + return 0; } |