mirror of
https://github.com/ProgramSnail/Lama.git
synced 2025-12-06 14:58:50 +00:00
Add check for argc in -g mode
This commit is contained in:
parent
deef68d031
commit
b444aa53e8
2 changed files with 69 additions and 18 deletions
|
|
@ -169,7 +169,6 @@ module ByteCode = struct
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let compile cmd insns =
|
let compile cmd insns =
|
||||||
(* let word_size = 4 in *)
|
|
||||||
let code = Buffer.create 256 in
|
let code = Buffer.create 256 in
|
||||||
let st = StringTab.create () in
|
let st = StringTab.create () in
|
||||||
let lmap = Stdlib.ref M.empty in
|
let lmap = Stdlib.ref M.empty in
|
||||||
|
|
|
||||||
|
|
@ -488,15 +488,24 @@ let compile_call env ?fname nargs tail =
|
||||||
push_args env (mov x (env#loc (Value.Arg (n - 1))) @ acc) (n - 1)
|
push_args env (mov x (env#loc (Value.Arg (n - 1))) @ acc) (n - 1)
|
||||||
in
|
in
|
||||||
let env, pushs = push_args env [] nargs in
|
let env, pushs = push_args env [] nargs in
|
||||||
let env, jump =
|
let env, setup_closure =
|
||||||
match fname with
|
match fname with
|
||||||
| Some fname -> (env, [ Jmp fname ])
|
| Some _ -> (env, [])
|
||||||
| None ->
|
| None ->
|
||||||
let closure, env = env#pop in
|
let closure, env = env#pop in
|
||||||
(env, [ Mov (closure, r15); JmpI r15 ])
|
(env, [ Mov (closure, r15) ])
|
||||||
|
in
|
||||||
|
let add_argc_counter =
|
||||||
|
if env#mode.is_debug then [ Mov (L nargs, r11) ] else []
|
||||||
|
in
|
||||||
|
let jump =
|
||||||
|
match fname with Some fname -> [ Jmp fname ] | None -> [ JmpI r15 ]
|
||||||
in
|
in
|
||||||
let _, env = env#allocate in
|
let _, env = env#allocate in
|
||||||
(env, pushs @ [ Mov (rbp, rsp); Pop rbp ] @ jump)
|
( env,
|
||||||
|
pushs
|
||||||
|
@ [ Mov (rbp, rsp); Pop rbp ]
|
||||||
|
@ setup_closure @ add_argc_counter @ jump )
|
||||||
in
|
in
|
||||||
let compile_common_call env fname nargs =
|
let compile_common_call env fname nargs =
|
||||||
let setup_arguments env nargs =
|
let setup_arguments env nargs =
|
||||||
|
|
@ -535,35 +544,47 @@ let compile_call env ?fname nargs tail =
|
||||||
( [ Push filler ],
|
( [ Push filler ],
|
||||||
[ Binop ("+", L (word_size * (1 + stack_arguments)), rsp) ] )
|
[ Binop ("+", L (word_size * (1 + stack_arguments)), rsp) ] )
|
||||||
in
|
in
|
||||||
|
let setup_closure env =
|
||||||
|
match fname with
|
||||||
|
| Some _ -> (env, [])
|
||||||
|
| None ->
|
||||||
|
let closure, env = env#pop in
|
||||||
|
(env, [ Mov (closure, r15) ])
|
||||||
|
in
|
||||||
let call env fname =
|
let call env fname =
|
||||||
match fname with
|
match fname with
|
||||||
| Some fname -> (env, [ Call fname ])
|
| Some fname -> (env, [ Call fname ])
|
||||||
| None ->
|
| None -> (env, [ CallI r15 ])
|
||||||
let closure, env = env#pop in
|
|
||||||
(env, [ Mov (closure, r15); CallI r15 ])
|
|
||||||
in
|
in
|
||||||
let move_result env =
|
let move_result env =
|
||||||
let y, env = env#allocate in
|
let y, env = env#allocate in
|
||||||
(env, [ Mov (rax, y) ])
|
(env, [ Mov (rax, y) ])
|
||||||
in
|
in
|
||||||
let add_printf_count =
|
let add_argc_counter =
|
||||||
match fname with
|
let argc_before_vararg =
|
||||||
| Some fname -> (
|
Option.map (fun fname -> List.assoc fname vararg_functions) fname
|
||||||
match List.assoc_opt fname vararg_functions with
|
in
|
||||||
| Some n -> [ Mov (L (nargs - n), r11) ]
|
match argc_before_vararg with
|
||||||
| None -> [])
|
(* For vararg functions we add counter of only vararg argumnets.
|
||||||
| _ -> []
|
It is used in assembly to unbox them. *)
|
||||||
|
| Some argc -> [ Mov (L (nargs - argc), r11) ]
|
||||||
|
(* For all functions in debug mode we add arguments counter.
|
||||||
|
It is checked in the prologue of the function. *)
|
||||||
|
| None when env#mode.is_debug -> [ Mov (L nargs, r11) ]
|
||||||
|
| None -> []
|
||||||
in
|
in
|
||||||
let stack_slots, env, setup_args_code = setup_arguments env nargs in
|
let stack_slots, env, setup_args_code = setup_arguments env nargs in
|
||||||
let push_registers, pop_registers = protect_registers env in
|
let push_registers, pop_registers = protect_registers env in
|
||||||
let align_prologue, align_epilogue =
|
let align_prologue, align_epilogue =
|
||||||
align_stack (List.length push_registers) stack_slots
|
align_stack (List.length push_registers) stack_slots
|
||||||
in
|
in
|
||||||
|
let env, setup_closure = setup_closure env in
|
||||||
let env, call = call env fname in
|
let env, call = call env fname in
|
||||||
let env, move_result = move_result env in
|
let env, move_result = move_result env in
|
||||||
( env,
|
( env,
|
||||||
push_registers @ align_prologue @ setup_args_code @ add_printf_count
|
push_registers @ align_prologue @ setup_args_code @ setup_closure
|
||||||
@ call @ align_epilogue @ List.rev pop_registers @ move_result )
|
@ add_argc_counter @ call @ align_epilogue @ List.rev pop_registers
|
||||||
|
@ move_result )
|
||||||
in
|
in
|
||||||
let compile_safe_point_call env fname nargs =
|
let compile_safe_point_call env fname nargs =
|
||||||
let setup_arguments env nargs =
|
let setup_arguments env nargs =
|
||||||
|
|
@ -779,6 +800,37 @@ let compile cmd env imports code =
|
||||||
in
|
in
|
||||||
func @ arguments @ variables)
|
func @ arguments @ variables)
|
||||||
in
|
in
|
||||||
|
let env, check_argc =
|
||||||
|
if f = cmd#topname || not env#mode.is_debug then (env, [])
|
||||||
|
else
|
||||||
|
let argc_correct_label = f ^ "_argc_correct" in
|
||||||
|
let pat_addr, env =
|
||||||
|
env#string
|
||||||
|
"Function %s called with incorrect arguments count. \
|
||||||
|
Expected: %d. Actual: %d\\n"
|
||||||
|
in
|
||||||
|
let name_addr, env = env#string name in
|
||||||
|
let pat_loc, env = env#allocate in
|
||||||
|
let name_loc, env = env#allocate in
|
||||||
|
let expected_loc, env = env#allocate in
|
||||||
|
let actual_loc, env = env#allocate in
|
||||||
|
let env, fail_call =
|
||||||
|
compile_call env ~fname:"failure" 4 false
|
||||||
|
in
|
||||||
|
let _, env = env#pop in
|
||||||
|
( env,
|
||||||
|
[
|
||||||
|
Meta "# Check arguments count";
|
||||||
|
Binop ("cmp", L nargs, r11);
|
||||||
|
CJmp ("e", argc_correct_label);
|
||||||
|
Mov (r11, actual_loc);
|
||||||
|
Mov (L nargs, expected_loc);
|
||||||
|
Mov (name_addr, name_loc);
|
||||||
|
Mov (pat_addr, pat_loc);
|
||||||
|
]
|
||||||
|
@ fail_call
|
||||||
|
@ [ Label argc_correct_label ] )
|
||||||
|
in
|
||||||
env#assert_empty_stack;
|
env#assert_empty_stack;
|
||||||
let has_closure = closure <> [] in
|
let has_closure = closure <> [] in
|
||||||
let env = env#enter f nargs nlocals has_closure in
|
let env = env#enter f nargs nlocals has_closure in
|
||||||
|
|
@ -841,7 +893,7 @@ let compile cmd env imports code =
|
||||||
List.map
|
List.map
|
||||||
(fun i -> Call ("init" ^ i))
|
(fun i -> Call ("init" ^ i))
|
||||||
(List.filter (fun i -> i <> "Std") imports)
|
(List.filter (fun i -> i <> "Std") imports)
|
||||||
else [] )
|
else [] @ check_argc )
|
||||||
| END ->
|
| END ->
|
||||||
let x, env = env#pop in
|
let x, env = env#pop in
|
||||||
env#assert_empty_stack;
|
env#assert_empty_stack;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue