fix some calling convention stuff

This commit is contained in:
pommicket 2022-02-10 13:24:02 -05:00
parent 3d44eba388
commit b88de92fc7
6 changed files with 98 additions and 22 deletions

View file

@ -1,7 +1,18 @@
; CALLING CONVENTION: ; CALLING CONVENTION:
; arguments are pushed onto the stack by the caller, from right to left ; Here is the process for calling a function:
; caller must also reserve space on stack for return value ; - the caller pushes the arguments on to the stack, from right to left
; so the function puts the return value at [rbp+8] (+8 for stored return address) ; - 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 codegen_second_pass = 1
generate_functions() generate_functions()
; generate code at the entry point of the executable ; 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 ; @TODO
return return
:no_main_function
die(.str_no_main_function)
:str_no_main_function
string Error: No main function.
byte 0

View file

@ -783,3 +783,6 @@
:str_default :str_default
string default string default
byte 0 byte 0
:str_main
string main
byte 0

View file

@ -64,7 +64,7 @@ global statement_datas_ends
; block_static_variables[1] = static variables inside this block inside this function ; block_static_variables[1] = static variables inside this block inside this function
; etc. ; etc.
global block_static_variables 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 local_variables
global block_depth global block_depth
global expressions global expressions

View file

@ -13,5 +13,8 @@ struct A { struct B *blah; }
struct B { struct A *blah; } struct B { struct A *blah; }
*/ */
int main(void) { int main(int argc, char **Argv) {
int i,j;
Argv+argc+i;
j;
} }

View file

@ -239,21 +239,31 @@ function parse_toplevel_declaration
string Functions should not have initializers. string Functions should not have initializers.
byte 0 byte 0
:parse_function_definition :parse_function_definition
local ret_type
local param_offset
if block_depth != 0 goto nested_function if block_depth != 0 goto nested_function
if function_param_has_no_name != 0 goto function_no_param_name if function_param_has_no_name != 0 goto function_no_param_name
p = types + type p = types + type
if *1p != TYPE_FUNCTION goto lbrace_after_declaration 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 ; initialized in main
global function_stmt_data_bytes_used global function_stmt_data_bytes_used
local_var_rbp_offset = 0
out = function_stmt_data + function_stmt_data_bytes_used out = function_stmt_data + function_stmt_data_bytes_used
out0 = out out0 = out
ident_list_add(function_statements, name, out) ident_list_add(function_statements, name, out)
; deal with function parameters ; 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 p = type + 1
name = function_param_names name = function_param_names
list = local_variables list = local_variables
@ -261,18 +271,21 @@ function parse_toplevel_declaration
list = *8list list = *8list
:fn_params_loop :fn_params_loop
if *1name == 0 goto fn_params_loop_end 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 = p < 32
c |= local_var_rbp_offset c |= param_offset
ident_list_add(list, name, c) ident_list_add(list, name, c)
param_offset += type_sizeof(p)
param_offset += 7
param_offset >= 3
param_offset <= 3
p += type_length(p) p += type_length(p)
name = memchr(name, 0) name = memchr(name, 0)
name += 1 name += 1
goto fn_params_loop goto fn_params_loop
:fn_params_loop_end :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. ; 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). ; it needs to be this way because of varargs functions (the function doesn't know how many arguments there are).
parse_statement(&token, &out) parse_statement(&token, &out)
@ -698,8 +711,9 @@ function parse_statement
out += 24 out += 24
p = local_variables p = local_variables
p += block_depth < 3 p += block_depth < 3
l_offset = local_var_rbp_offset ; local variables are stored below rbp
c = l_offset l_offset = 0 - local_var_rbp_offset
c = l_offset & 0xffffffff
c |= l_type < 32 c |= l_type < 32
ident_list_set(*8p, l_name, c) ident_list_set(*8p, l_name, c)
@ -3080,7 +3094,8 @@ function parse_expression
out += 4 out += 4
*4out = c > 32 ; extract type *4out = c > 32 ; extract type
out += 4 out += 4
*8out = c & 0xffffffff ; extract rbp offset c &= 0xffffffff
*8out = sign_extend_32_to_64(c) ; extract rbp offset
out += 8 out += 8
return out return out
:expression_integer :expression_integer
@ -4074,12 +4089,12 @@ function print_expression
:print_local_variable :print_local_variable
puts(.str_local_prefix) puts(.str_local_prefix)
expression += 8 expression += 8
putn(*8expression) putn_with_sign(*8expression)
putc(']) putc('])
expression += 8 expression += 8
return expression return expression
:str_local_prefix :str_local_prefix
string [rbp- string [rbp
byte 0 byte 0
:print_expr_function :print_expr_function
expression += 8 expression += 8

View file

@ -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 ; multiply two 64-bit signed numbers to a 128-bit number
function full_multiply_signed function full_multiply_signed
argument a argument a
@ -456,15 +464,27 @@ function fputn_signed
argument fd argument fd
argument n argument n
if n < 0 goto fputn_negative if n < 0 goto fputn_negative
fputn(fd, n)
fputn(fd, n) return
return
:fputn_negative :fputn_negative
fputc(fd, '-) fputc(fd, '-)
n = 0 - n n = 0 - n
fputn(fd, n) fputn(fd, n)
return 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 :hex_digits
string 0123456789abcdef string 0123456789abcdef
@ -527,6 +547,11 @@ function putn_signed
fputn_signed(1, n) fputn_signed(1, n)
return return
function putn_with_sign
argument n
fputn_with_sign(1, n)
return
function putnln function putnln
argument n argument n
fputn(1, n) fputn(1, n)
@ -539,6 +564,11 @@ function putnln_signed
fputc(1, 10) fputc(1, 10)
return return
function putnln_with_sign
argument n
fputn_with_sign(1, n)
fputc(1, 10)
return
function fputc function fputc
argument fd argument fd