summaryrefslogtreecommitdiff
path: root/05
diff options
context:
space:
mode:
Diffstat (limited to '05')
-rw-r--r--05/codegen.b31
-rw-r--r--05/constants.b3
-rw-r--r--05/main.b2
-rw-r--r--05/main.c5
-rw-r--r--05/parse.b41
-rw-r--r--05/util.b38
6 files changed, 98 insertions, 22 deletions
diff --git a/05/codegen.b b/05/codegen.b
index 1507e6d..2cd000c 100644
--- a/05/codegen.b
+++ b/05/codegen.b
@@ -1,7 +1,18 @@
; CALLING CONVENTION:
-; arguments are pushed onto the stack by the caller, from right to left
-; caller must also reserve space on stack for return value
-; so the function puts the return value at [rbp+8] (+8 for stored return address)
+; Here is the process for calling a function:
+; - the caller pushes the arguments on to the stack, from right to left
+; - the caller subtracts sizeof(return type) from rsp
+; - the caller calls the function
+; - the caller stores away the return value
+; - the caller adds (sizeof(return type) + sizeof arg0 + ... + sizeof argn) to rsp
+; STACK LAYOUT:
+; arg n
+; ...
+; arg 0
+; return value [rbp+16]
+; return address [rbp+8]
+; old rbp [rbp]
+; local variables
@@ -191,5 +202,19 @@ function generate_code
codegen_second_pass = 1
generate_functions()
; generate code at the entry point of the executable
+ local main_addr
+ main_addr = ident_list_lookup(functions_addresses, .str_main)
+ if main_addr == 0 goto no_main_function
+
+ ; on entry, we will have:
+ ; argc = *rsp
+ ; argv = rsp + 8
+
+
; @TODO
return
+ :no_main_function
+ die(.str_no_main_function)
+ :str_no_main_function
+ string Error: No main function.
+ byte 0
diff --git a/05/constants.b b/05/constants.b
index b719375..c6555ee 100644
--- a/05/constants.b
+++ b/05/constants.b
@@ -783,3 +783,6 @@
:str_default
string default
byte 0
+:str_main
+ string main
+ byte 0
diff --git a/05/main.b b/05/main.b
index b94dc45..0e356d7 100644
--- a/05/main.b
+++ b/05/main.b
@@ -64,7 +64,7 @@ global statement_datas_ends
; block_static_variables[1] = static variables inside this block inside this function
; etc.
global block_static_variables
-; ident lists of (type << 32) | rbp offset; one per block depth
+; ident lists of (type << 32) | rbp offset; one per block depth -- note that rbp offset may be negative!
global local_variables
global block_depth
global expressions
diff --git a/05/main.c b/05/main.c
index 56af630..059291f 100644
--- a/05/main.c
+++ b/05/main.c
@@ -13,5 +13,8 @@ struct A { struct B *blah; }
struct B { struct A *blah; }
*/
-int main(void) {
+int main(int argc, char **Argv) {
+ int i,j;
+ Argv+argc+i;
+ j;
}
diff --git a/05/parse.b b/05/parse.b
index c5cd91e..7f288ae 100644
--- a/05/parse.b
+++ b/05/parse.b
@@ -239,21 +239,31 @@ function parse_toplevel_declaration
string Functions should not have initializers.
byte 0
:parse_function_definition
+ local ret_type
+ local param_offset
+
if block_depth != 0 goto nested_function
if function_param_has_no_name != 0 goto function_no_param_name
p = types + type
if *1p != TYPE_FUNCTION goto lbrace_after_declaration
+ ret_type = functype_return_type(type)
+
global function_stmt_data ; initialized in main
global function_stmt_data_bytes_used
-
- local_var_rbp_offset = 0
-
+
out = function_stmt_data + function_stmt_data_bytes_used
out0 = out
ident_list_add(function_statements, name, out)
; deal with function parameters
+ ; function parameters go above return value on the stack
+ n = type_sizeof(ret_type)
+ n += 7
+ n >= 3
+ n <= 3
+ param_offset = n + 16 ; + 16 for old rbp and return address
+
p = type + 1
name = function_param_names
list = local_variables
@@ -261,18 +271,21 @@ function parse_toplevel_declaration
list = *8list
:fn_params_loop
if *1name == 0 goto fn_params_loop_end
- local_var_rbp_offset += type_sizeof(p)
- local_var_rbp_offset += 7
- local_var_rbp_offset >= 3
- local_var_rbp_offset <= 3
c = p < 32
- c |= local_var_rbp_offset
+ c |= param_offset
ident_list_add(list, name, c)
+ param_offset += type_sizeof(p)
+ param_offset += 7
+ param_offset >= 3
+ param_offset <= 3
p += type_length(p)
name = memchr(name, 0)
name += 1
goto fn_params_loop
:fn_params_loop_end
+
+ local_var_rbp_offset = 0
+
; NOTE: it's the caller's responsibility to properly set rsp to accomodate all the arguments.
; it needs to be this way because of varargs functions (the function doesn't know how many arguments there are).
parse_statement(&token, &out)
@@ -698,8 +711,9 @@ function parse_statement
out += 24
p = local_variables
p += block_depth < 3
- l_offset = local_var_rbp_offset
- c = l_offset
+ ; local variables are stored below rbp
+ l_offset = 0 - local_var_rbp_offset
+ c = l_offset & 0xffffffff
c |= l_type < 32
ident_list_set(*8p, l_name, c)
@@ -3080,7 +3094,8 @@ function parse_expression
out += 4
*4out = c > 32 ; extract type
out += 4
- *8out = c & 0xffffffff ; extract rbp offset
+ c &= 0xffffffff
+ *8out = sign_extend_32_to_64(c) ; extract rbp offset
out += 8
return out
:expression_integer
@@ -4074,12 +4089,12 @@ function print_expression
:print_local_variable
puts(.str_local_prefix)
expression += 8
- putn(*8expression)
+ putn_with_sign(*8expression)
putc('])
expression += 8
return expression
:str_local_prefix
- string [rbp-
+ string [rbp
byte 0
:print_expr_function
expression += 8
diff --git a/05/util.b b/05/util.b
index 3d0ffb6..5f7c5e6 100644
--- a/05/util.b
+++ b/05/util.b
@@ -1,3 +1,11 @@
+function sign_extend_32_to_64
+ argument n
+ local c
+ c = n > 31
+ n |= c * 0xffffffff00000000
+ return n
+
+
; multiply two 64-bit signed numbers to a 128-bit number
function full_multiply_signed
argument a
@@ -456,15 +464,27 @@ function fputn_signed
argument fd
argument n
if n < 0 goto fputn_negative
-
- fputn(fd, n)
- return
-
+ fputn(fd, n)
+ return
:fputn_negative
fputc(fd, '-)
n = 0 - n
fputn(fd, n)
return
+
+; like fputn_signed, but include the sign even if it's zero or positive
+function fputn_with_sign
+ argument fd
+ argument n
+ if n < 0 goto fputn_with_sign_negative
+ fputc(fd, '+)
+ fputn(fd, n)
+ return
+ :fputn_with_sign_negative
+ fputc(fd, '-)
+ n = 0 - n
+ fputn(fd, n)
+ return
:hex_digits
string 0123456789abcdef
@@ -527,6 +547,11 @@ function putn_signed
fputn_signed(1, n)
return
+function putn_with_sign
+ argument n
+ fputn_with_sign(1, n)
+ return
+
function putnln
argument n
fputn(1, n)
@@ -539,6 +564,11 @@ function putnln_signed
fputc(1, 10)
return
+function putnln_with_sign
+ argument n
+ fputn_with_sign(1, n)
+ fputc(1, 10)
+ return
function fputc
argument fd