diff options
| author | Graydon Hoare <[email protected]> | 2010-06-23 21:03:09 -0700 |
|---|---|---|
| committer | Graydon Hoare <[email protected]> | 2010-06-23 21:03:09 -0700 |
| commit | d6b7c96c3eb29b9244ece0c046d3f372ff432d04 (patch) | |
| tree | b425187e232966063ffc2f0d14c04a55d8f004ef /src/boot/llvm/llasm.ml | |
| parent | Initial git commit. (diff) | |
| download | rust-d6b7c96c3eb29b9244ece0c046d3f372ff432d04.tar.xz rust-d6b7c96c3eb29b9244ece0c046d3f372ff432d04.zip | |
Populate tree.
Diffstat (limited to 'src/boot/llvm/llasm.ml')
| -rw-r--r-- | src/boot/llvm/llasm.ml | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/src/boot/llvm/llasm.ml b/src/boot/llvm/llasm.ml new file mode 100644 index 00000000..56448b07 --- /dev/null +++ b/src/boot/llvm/llasm.ml @@ -0,0 +1,192 @@ +(* + * machine-specific assembler routines. + *) + +open Common;; + +type asm_glue = + { + asm_activate_glue : Llvm.llvalue; + asm_yield_glue : Llvm.llvalue; + asm_upcall_glues : Llvm.llvalue array; + } +;; + +let n_upcall_glues = 7 +;; + +(* x86-specific asm. *) + +let x86_glue + (llctx:Llvm.llcontext) + (llmod:Llvm.llmodule) + (abi:Llabi.abi) + (sess:Session.sess) + : asm_glue = + let (prefix,align) = + match sess.Session.sess_targ with + Linux_x86_elf + | Win32_x86_pe -> ("",4) + | MacOS_x86_macho -> ("_", 16) + in + let save_callee_saves = + ["pushl %ebp"; + "pushl %edi"; + "pushl %esi"; + "pushl %ebx";] + in + let restore_callee_saves = + ["popl %ebx"; + "popl %esi"; + "popl %edi"; + "popl %ebp";] + in + let load_esp_from_rust_sp = ["movl 12(%edx), %esp"] in + let load_esp_from_runtime_sp = ["movl 8(%edx), %esp"] in + let store_esp_to_rust_sp = ["movl %esp, 12(%edx)"] in + let store_esp_to_runtime_sp = ["movl %esp, 8(%edx)"] in + let list_init i f = (Array.to_list (Array.init i f)) in + let list_init_concat i f = List.concat (list_init i f) in + + let glue = + [ + ("rust_activate_glue", + String.concat "\n\t" + (["movl 4(%esp), %edx # edx = rust_task"] + @ save_callee_saves + @ store_esp_to_runtime_sp + @ load_esp_from_rust_sp + (* + * This 'add' instruction is a bit surprising. + * See lengthy comment in boot/be/x86.ml activate_glue. + *) + @ ["addl $20, 12(%edx)"] + @ restore_callee_saves + @ ["ret"])); + + ("rust_yield_glue", + String.concat "\n\t" + + (["movl 0(%esp), %edx # edx = rust_task"] + @ load_esp_from_rust_sp + @ save_callee_saves + @ store_esp_to_rust_sp + @ load_esp_from_runtime_sp + @ restore_callee_saves + @ ["ret"])) + ] + @ list_init n_upcall_glues + begin + fun i -> + (* + * 0, 4, 8, 12 are callee-saves + * 16 is retpc + * 20 is taskptr + * 24 is callee + * 28 .. (7+i) * 4 are args + *) + + ((Printf.sprintf "rust_upcall_%d" i), + String.concat "\n\t" + (save_callee_saves + @ ["movl %esp, %ebp # ebp = rust_sp"; + "movl 20(%esp), %edx # edx = rust_task"] + @ store_esp_to_rust_sp + @ load_esp_from_runtime_sp + @ [Printf.sprintf + "subl $%d, %%esp # esp -= args" ((i+1)*4); + "andl $~0xf, %esp # align esp down"; + "movl %edx, (%esp) # arg[0] = rust_task "] + + @ (list_init_concat i + begin + fun j -> + [ Printf.sprintf "movl %d(%%ebp),%%edx" ((j+7)*4); + Printf.sprintf "movl %%edx,%d(%%esp)" ((j+1)*4) ] + end) + + @ ["movl 24(%ebp), %edx # edx = callee"; + "call *%edx # call *%edx"; + "movl 20(%ebp), %edx # edx = rust_task"] + @ load_esp_from_rust_sp + @ restore_callee_saves + @ ["ret"])) + end + in + + let _ = + Llvm.set_module_inline_asm llmod + begin + String.concat "\n" + begin + List.map + begin + fun (sym,asm) -> + Printf.sprintf + "\t.globl %s%s\n\t.balign %d\n%s%s:\n\t%s" + prefix sym align prefix sym asm + end + glue + end + end + in + + let decl_cdecl_fn name out_ty arg_tys = + let ty = Llvm.function_type out_ty arg_tys in + let fn = Llvm.declare_function name ty llmod in + Llvm.set_function_call_conv Llvm.CallConv.c fn; + fn + in + + let decl_glue s = + let task_ptr_ty = Llvm.pointer_type abi.Llabi.task_ty in + let void_ty = Llvm.void_type llctx in + decl_cdecl_fn s void_ty [| task_ptr_ty |] + in + + let decl_upcall n = + let task_ptr_ty = Llvm.pointer_type abi.Llabi.task_ty in + let word_ty = abi.Llabi.word_ty in + let callee_ty = word_ty in + let args_ty = + Array.append + [| task_ptr_ty; callee_ty |] + (Array.init n (fun _ -> word_ty)) + in + let name = Printf.sprintf "rust_upcall_%d" n in + decl_cdecl_fn name word_ty args_ty + in + { + asm_activate_glue = decl_glue "rust_activate_glue"; + asm_yield_glue = decl_glue "rust_yield_glue"; + asm_upcall_glues = Array.init n_upcall_glues decl_upcall; + } +;; + +(* x64-specific asm. *) +(* arm-specific asm. *) +(* ... *) + + +let get_glue + (llctx:Llvm.llcontext) + (llmod:Llvm.llmodule) + (abi:Llabi.abi) + (sess:Session.sess) + : asm_glue = + match sess.Session.sess_targ with + Linux_x86_elf + | Win32_x86_pe + | MacOS_x86_macho -> + x86_glue llctx llmod abi sess +;; + + +(* + * 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: + *) |