summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2022-02-12 11:37:40 -0500
committerpommicket <pommicket@gmail.com>2022-02-12 11:37:40 -0500
commitb69bd8be29a53d8801387d09043de5bd75ca9e26 (patch)
treeeea6752ff72b67720d2b6468fc1b6bd989df000e
parent3db0956b193f837e2b3bf1901653e43ca18f1501 (diff)
codegen for global variables
-rw-r--r--04/README.md2
-rw-r--r--04a/in043
-rw-r--r--05/codegen.b92
-rw-r--r--05/main.c4
-rw-r--r--05/parse.b7
5 files changed, 104 insertions, 4 deletions
diff --git a/04/README.md b/04/README.md
index 68cd81d..6840080 100644
--- a/04/README.md
+++ b/04/README.md
@@ -271,4 +271,4 @@ you need to use a lot of labels, and that means their names can get quite long.
the 03 language, you'll get an error if you use the same label name twice!
Overall, though, this language ended up being surprisingly powerful. With any luck, stage `05` will
-finally be a C compiler... But first, it's time to make [something that's not a compiler](../04a/README.html).
+finally be a C compiler... But first, it's time to make [something that's not a compiler](../04a/README.md).
diff --git a/04a/in04 b/04a/in04
index 8c0d2cc..5bd955c 100644
--- a/04a/in04
+++ b/04a/in04
@@ -6,11 +6,10 @@ byte 40
byte 0
byte 0
byte 0
+goto main
global output_fd
-goto main
-
global defines
global defines_end
diff --git a/05/codegen.b b/05/codegen.b
index 0d70f37..ff4687a 100644
--- a/05/codegen.b
+++ b/05/codegen.b
@@ -150,6 +150,62 @@ function emit_mov_eax_eax
code_output += 2
return
+function emit_mov_al_byte_rbx
+ ; 8a 03
+ *2code_output = 0x038a
+ code_output += 2
+ return
+
+function emit_mov_byte_rbx_al
+ ; 88 03
+ *2code_output = 0x0388
+ code_output += 2
+ return
+
+function emit_mov_ax_word_rbx
+ ; 66 8b 03
+ *2code_output = 0x8b66
+ code_output += 2
+ *1code_output = 0x03
+ code_output += 1
+ return
+
+function emit_mov_word_rbx_ax
+ ; 66 89 03
+ *2code_output = 0x8966
+ code_output += 2
+ *1code_output = 0x03
+ code_output += 1
+ return
+
+function emit_mov_eax_dword_rbx
+ ; 8b 03
+ *2code_output = 0x038b
+ code_output += 2
+ return
+
+function emit_mov_dword_rbx_eax
+ ; 89 03
+ *2code_output = 0x0389
+ code_output += 2
+ return
+
+function emit_mov_rax_qword_rbx
+ ; 48 8b 03
+ *2code_output = 0x8b48
+ code_output += 2
+ *1code_output = 0x03
+ code_output += 1
+ return
+
+function emit_mov_qword_rbx_rax
+ ; 48 89 03
+ *2code_output = 0x8948
+ code_output += 2
+ *1code_output = 0x03
+ code_output += 1
+ return
+
function emit_mov_qword_rsp_plus_imm32_rax
argument imm32
; 48 89 84 24 IMM32
@@ -889,6 +945,7 @@ function generate_stack_sub
function generate_push_expression
argument statement
argument expr
+ local b
local c
local d
local p
@@ -906,6 +963,7 @@ function generate_push_expression
if c == EXPRESSION_LOGICAL_NOT goto generate_unary_logical_not
if c == EXPRESSION_ADD goto generate_add
if c == EXPRESSION_SUB goto generate_sub
+ if c == EXPRESSION_GLOBAL_VARIABLE goto generate_global_variable
die(.str_genpushexprNI)
:str_genpushexprNI
@@ -991,6 +1049,40 @@ function generate_push_expression
emit_movq_xmm0_rax() ; movq xmm0, rax
emit_comisd_xmm0_xmm1() ; comisd xmm0, xmm1
goto generate_logical_not_cont
+ :generate_global_variable
+ expr += 8
+ d = *8expr ; address
+ expr += 8
+ b = type_is_array(type)
+ if b != 0 goto global_var_array
+ c = type_sizeof(type)
+ if c > 8 goto global_var_large
+ emit_mov_rbx_imm64(d) ; mov rbx, (address)
+ emit_mov_rax_qword_rbx() ; mov rax, [rbx]
+ emit_push_rax() ; push rax
+ p = types + type
+ if *1p < TYPE_LONG goto global_var_needs_cast
+ return expr
+ :global_var_needs_cast
+ ; we need to sign extend 8/16/32-bit signed global variables to 64 bits
+ generate_cast_top_of_stack(statement, TYPE_UNSIGNED_LONG, type)
+ return expr
+ :global_var_large
+ ; @TODO: test this
+ c = round_up_to_8(c)
+ emit_sub_rsp_imm32(c) ; sub rsp, (size)
+ emit_mov_reg(REG_RDI, REG_RSP) ; mov rdi, rsp
+ emit_mov_rax_imm64(d) ; mov rax, (address)
+ emit_mov_reg(REG_RSI, REG_RAX) ; mov rsi, rax
+ emit_mov_rax_imm64(c) ; mov rax, (size)
+ emit_mov_reg(REG_RCX, REG_RAX) ; mov rcx, rax
+ emit_rep_movsb() ; rep movsb
+ return expr
+ :global_var_array
+ ; just push the address of the array
+ emit_mov_rax_imm64(d) ; mov rax, (address)
+ emit_push_rax() ; push rax
+ return expr
:generate_float
expr += 8
emit_mov_rax_imm64(*8expr)
diff --git a/05/main.c b/05/main.c
index d156c52..b2a0001 100644
--- a/05/main.c
+++ b/05/main.c
@@ -1,3 +1,5 @@
+static int x = -2;
+
long main(int argc, char **argv) {
- return (double*)808 - (double*)792;
+ return x + 17.3;
}
diff --git a/05/parse.b b/05/parse.b
index 476d503..a6dd81d 100644
--- a/05/parse.b
+++ b/05/parse.b
@@ -24,6 +24,13 @@ function token_is_type
if b != 0 goto return_1
goto return_0
+function type_is_array
+ argument type
+ local p
+ p = types + type
+ if *1p == TYPE_ARRAY goto return_1
+ return 0
+
function functype_return_type
argument ftype
local type