rust/src/boot/be/abi.ml

211 lines
6.4 KiB
OCaml

(*
* The 'abi' structure is pretty much just a grab-bag of machine
* dependencies and structure-layout information. Part of the latter
* is shared with trans and semant.
*
* Make some attempt to factor it as time goes by.
*)
(* Word offsets for structure fields in rust-internal.h, and elsewhere in
compiler. *)
let rc_base_field_refcnt = 0;;
let task_field_refcnt = rc_base_field_refcnt;;
let task_field_stk = task_field_refcnt + 1;;
let task_field_runtime_sp = task_field_stk + 1;;
let task_field_rust_sp = task_field_runtime_sp + 1;;
let task_field_gc_alloc_chain = task_field_rust_sp + 1;;
let task_field_dom = task_field_gc_alloc_chain + 1;;
let n_visible_task_fields = task_field_dom + 1;;
let dom_field_interrupt_flag = 0;;
let frame_glue_fns_field_mark = 0;;
let frame_glue_fns_field_drop = 1;;
let frame_glue_fns_field_reloc = 2;;
let exterior_rc_slot_field_refcnt = 0;;
let exterior_rc_slot_field_body = 1;;
let exterior_gc_slot_alloc_base = (-3);;
let exterior_gc_slot_field_prev = (-3);;
let exterior_gc_slot_field_next = (-2);;
let exterior_gc_slot_field_ctrl = (-1);;
let exterior_gc_slot_field_refcnt = 0;;
let exterior_gc_slot_field_body = 1;;
let exterior_rc_header_size = 1;;
let exterior_gc_header_size = 4;;
let exterior_gc_malloc_return_adjustment = 3;;
let stk_field_valgrind_id = 0 + 1;;
let stk_field_limit = stk_field_valgrind_id + 1;;
let stk_field_data = stk_field_limit + 1;;
let binding_size = 2;;
let binding_field_item = 0;;
let binding_field_binding = 1;;
let general_code_alignment = 16;;
let tydesc_field_first_param = 0;;
let tydesc_field_size = 1;;
let tydesc_field_align = 2;;
let tydesc_field_copy_glue = 3;;
let tydesc_field_drop_glue = 4;;
let tydesc_field_free_glue = 5;;
let tydesc_field_mark_glue = 6;;
let tydesc_field_obj_drop_glue = 7;;
let vec_elt_rc = 0;;
let vec_elt_alloc = 1;;
let vec_elt_fill = 2;;
let vec_elt_data = 3;;
let calltup_elt_out_ptr = 0;;
let calltup_elt_task_ptr = 1;;
let calltup_elt_ty_params = 2;;
let calltup_elt_args = 3;;
let calltup_elt_iterator_args = 4;;
let calltup_elt_indirect_args = 5;;
let iterator_args_elt_block_fn = 0;;
let iterator_args_elt_outer_frame_ptr = 1;;
let indirect_args_elt_closure = 0;;
(* ty_params, src, dst, tydesc, taskptr. *)
let worst_case_glue_call_args = 5;;
type abi =
{
abi_word_sz: int64;
abi_word_bits: Il.bits;
abi_word_ty: Common.ty_mach;
abi_is_2addr_machine: bool;
abi_has_pcrel_data: bool;
abi_has_pcrel_code: bool;
abi_n_hardregs: int;
abi_str_of_hardreg: (int -> string);
abi_prealloc_quad: (Il.quad' -> Il.quad');
abi_constrain_vregs: (Il.quad -> Bits.t array -> unit);
abi_emit_fn_prologue: (Il.emitter
-> Common.size (* framesz *)
-> Common.size (* callsz *)
-> Common.nabi
-> Common.fixup (* grow_task *)
-> unit);
abi_emit_fn_epilogue: (Il.emitter -> unit);
abi_emit_fn_tail_call: (Il.emitter
-> int64 (* caller_callsz *)
-> int64 (* caller_argsz *)
-> Il.code (* callee_code *)
-> int64 (* callee_argsz *)
-> unit);
abi_clobbers: (Il.quad -> Il.hreg list);
abi_emit_native_call: (Il.emitter
-> Il.cell (* ret *)
-> Common.nabi
-> Common.fixup (* callee *)
-> Il.operand array (* args *)
-> unit);
abi_emit_native_void_call: (Il.emitter
-> Common.nabi
-> Common.fixup (* callee *)
-> Il.operand array (* args *)
-> unit);
abi_emit_native_call_in_thunk: (Il.emitter
-> Il.cell (* ret *)
-> Common.nabi
-> Il.operand (* callee *)
-> Il.operand array (* args *)
-> unit);
abi_emit_inline_memcpy: (Il.emitter
-> int64 (* n_bytes *)
-> Il.reg (* dst_ptr *)
-> Il.reg (* src_ptr *)
-> Il.reg (* tmp_reg *)
-> bool (* ascending *)
-> unit);
(* Global glue. *)
abi_activate: (Il.emitter -> unit);
abi_yield: (Il.emitter -> unit);
abi_unwind: (Il.emitter -> Common.nabi -> Common.fixup -> unit);
abi_gc: (Il.emitter -> unit);
abi_get_next_pc_thunk:
((Il.reg (* output *)
* Common.fixup (* thunk in objfile *)
* (Il.emitter -> unit)) (* fn to make thunk *)
option);
abi_sp_reg: Il.reg;
abi_fp_reg: Il.reg;
abi_dwarf_fp_reg: int;
abi_tp_cell: Il.cell;
abi_implicit_args_sz: int64;
abi_frame_base_sz: int64;
abi_frame_info_sz: int64;
abi_spill_slot: (Il.spill -> Il.mem);
}
;;
let load_fixup_addr
(e:Il.emitter)
(out_reg:Il.reg)
(fix:Common.fixup)
(rty:Il.referent_ty)
: unit =
let cell = Il.Reg (out_reg, Il.AddrTy rty) in
let op = Il.ImmPtr (fix, rty) in
Il.emit e (Il.lea cell op);
;;
let load_fixup_codeptr
(e:Il.emitter)
(out_reg:Il.reg)
(fixup:Common.fixup)
(has_pcrel_code:bool)
(indirect:bool)
: Il.code =
if indirect
then
begin
load_fixup_addr e out_reg fixup (Il.ScalarTy (Il.AddrTy Il.CodeTy));
Il.CodePtr (Il.Cell (Il.Mem (Il.RegIn (out_reg, None),
Il.ScalarTy (Il.AddrTy Il.CodeTy))))
end
else
if has_pcrel_code
then (Il.CodePtr (Il.ImmPtr (fixup, Il.CodeTy)))
else
begin
load_fixup_addr e out_reg fixup Il.CodeTy;
Il.CodePtr (Il.Cell (Il.Reg (out_reg, Il.AddrTy Il.CodeTy)))
end
;;
(*
* Local Variables:
* fill-column: 78;
* indent-tabs-mode: nil
* buffer-file-coding-system: utf-8-unix
* compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
* End:
*)