aboutsummaryrefslogtreecommitdiff
path: root/src/boot/llvm/llasm.ml
diff options
context:
space:
mode:
authorGraydon Hoare <[email protected]>2010-06-23 21:03:09 -0700
committerGraydon Hoare <[email protected]>2010-06-23 21:03:09 -0700
commitd6b7c96c3eb29b9244ece0c046d3f372ff432d04 (patch)
treeb425187e232966063ffc2f0d14c04a55d8f004ef /src/boot/llvm/llasm.ml
parentInitial git commit. (diff)
downloadrust-d6b7c96c3eb29b9244ece0c046d3f372ff432d04.tar.xz
rust-d6b7c96c3eb29b9244ece0c046d3f372ff432d04.zip
Populate tree.
Diffstat (limited to 'src/boot/llvm/llasm.ml')
-rw-r--r--src/boot/llvm/llasm.ml192
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:
+ *)