summaryrefslogtreecommitdiff
path: root/05
diff options
context:
space:
mode:
Diffstat (limited to '05')
-rw-r--r--05/codegen.b188
-rw-r--r--05/main.b5
-rw-r--r--05/main.c2
3 files changed, 151 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
diff --git a/05/main.b b/05/main.b
index 7e570f5..7d4df9e 100644
--- a/05/main.b
+++ b/05/main.b
@@ -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
diff --git a/05/main.c b/05/main.c
index 26dda01..d156c52 100644
--- a/05/main.c
+++ b/05/main.c
@@ -1,3 +1,3 @@
long main(int argc, char **argv) {
- return -(3.5+2.5);
+ return (double*)808 - (double*)792;
}