aboutsummaryrefslogtreecommitdiff
path: root/src/comp/back
diff options
context:
space:
mode:
Diffstat (limited to 'src/comp/back')
-rw-r--r--src/comp/back/abi.rs46
-rw-r--r--src/comp/back/x86.rs159
2 files changed, 205 insertions, 0 deletions
diff --git a/src/comp/back/abi.rs b/src/comp/back/abi.rs
new file mode 100644
index 00000000..157bf876
--- /dev/null
+++ b/src/comp/back/abi.rs
@@ -0,0 +1,46 @@
+
+const int rc_base_field_refcnt = 0;
+
+const int task_field_refcnt = 0;
+const int task_field_stk = 2;
+const int task_field_runtime_sp = 3;
+const int task_field_rust_sp = 4;
+const int task_field_gc_alloc_chain = 5;
+const int task_field_dom = 6;
+const int n_visible_task_fields = 7;
+
+const int dom_field_interrupt_flag = 1;
+
+const int frame_glue_fns_field_mark = 0;
+const int frame_glue_fns_field_drop = 1;
+const int frame_glue_fns_field_reloc = 2;
+
+const int box_rc_field_refcnt = 0;
+const int box_rc_field_body = 1;
+
+const int general_code_alignment = 16;
+
+const int vec_elt_rc = 0;
+const int vec_elt_alloc = 1;
+const int vec_elt_fill = 2;
+const int vec_elt_data = 3;
+
+const int calltup_elt_out_ptr = 0;
+const int calltup_elt_task_ptr = 1;
+const int calltup_elt_indirect_args = 2;
+const int calltup_elt_ty_params = 3;
+const int calltup_elt_args = 4;
+const int calltup_elt_iterator_args = 5;
+
+const int worst_case_glue_call_args = 7;
+
+//
+// Local Variables:
+// mode: rust
+// fill-column: 78;
+// indent-tabs-mode: nil
+// c-basic-offset: 4
+// buffer-file-coding-system: utf-8-unix
+// compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
+// End:
+//
diff --git a/src/comp/back/x86.rs b/src/comp/back/x86.rs
new file mode 100644
index 00000000..fcf65cc0
--- /dev/null
+++ b/src/comp/back/x86.rs
@@ -0,0 +1,159 @@
+import lib.llvm.llvm;
+import lib.llvm.llvm.ModuleRef;
+import std._str;
+import std._int;
+import std._vec;
+
+const int wordsz = 4;
+
+fn istr(int i) -> str {
+ ret _int.to_str(i, 10u);
+}
+
+fn wstr(int i) -> str {
+ ret istr(i * wordsz);
+}
+
+fn save_callee_saves() -> vec[str] {
+ ret vec("pushl %ebp",
+ "pushl %edi",
+ "pushl %esi",
+ "pushl %ebx");
+}
+
+fn restore_callee_saves() -> vec[str] {
+ ret vec("popl %ebx",
+ "popl %esi",
+ "popl %edi",
+ "popl %ebp");
+}
+
+fn load_esp_from_rust_sp() -> vec[str] {
+ ret vec("movl " + wstr(abi.task_field_rust_sp) + "(%edx), %esp");
+}
+
+fn load_esp_from_runtime_sp() -> vec[str] {
+ ret vec("movl " + wstr(abi.task_field_runtime_sp) + "(%edx), %esp");
+}
+
+fn store_esp_to_rust_sp() -> vec[str] {
+ ret vec("movl %esp, " + wstr(abi.task_field_rust_sp) + "(%edx)");
+}
+
+fn store_esp_to_runtime_sp() -> vec[str] {
+ ret vec("movl %esp, " + wstr(abi.task_field_runtime_sp) + "(%edx)");
+}
+
+fn rust_activate_glue() -> vec[str] {
+ ret vec("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.
+ + vec("addl $20, " + wstr(abi.task_field_rust_sp) + "(%edx)")
+
+ + restore_callee_saves()
+ + vec("ret");
+}
+
+fn rust_yield_glue() -> vec[str] {
+ ret vec("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()
+ + vec("ret");
+}
+
+fn upcall_glue(int n_args) -> vec[str] {
+
+ /*
+ * 0, 4, 8, 12 are callee-saves
+ * 16 is retpc
+ * 20 is taskptr
+ * 24 is callee
+ * 28 .. (7+i) * 4 are args
+ */
+
+ fn copy_arg(uint i) -> str {
+ auto off = wstr(7 + (i as int));
+ auto m = vec("movl " + off + "(%ebp),%edx",
+ "movl %edx," + off + "(%esp)");
+ ret _str.connect(m, "\n\t");
+ }
+
+ auto carg = copy_arg;
+
+ ret
+ save_callee_saves()
+
+ + vec("movl %esp, %ebp # ebp = rust_sp",
+ "movl 20(%esp), %edx # edx = rust_task")
+
+ + store_esp_to_rust_sp()
+ + load_esp_from_runtime_sp()
+
+ + vec("subl $" + wstr(n_args + 1) + ", %esp # esp -= args",
+ "andl $~0xf, %esp # align esp down",
+ "movl %edx, (%esp) # arg[0] = rust_task ")
+
+ + _vec.init_fn[str](carg, n_args as uint)
+
+ + vec("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()
+ + vec("ret");
+
+}
+
+
+fn decl_glue(int align, str prefix, str name, vec[str] insns) -> str {
+ auto sym = prefix + name;
+ ret "\t.globl " + sym + "\n" +
+ "\t.balign " + istr(align) + "\n" +
+ sym + ":\n" +
+ "\t" + _str.connect(insns, "\n\t");
+}
+
+
+fn get_module_asm() -> str {
+ auto align = 4;
+ auto prefix = "";
+
+ auto glues =
+ vec(decl_glue(align, prefix,
+ "rust_activate_glue",
+ rust_activate_glue()),
+
+ decl_glue(align, prefix,
+ "rust_yield_glue",
+ rust_yield_glue()));
+
+ let int i = 0;
+ let int n_upcall_glues = 7;
+ while (i < n_upcall_glues) {
+ glues += decl_glue(align, prefix,
+ "rust_upcall_" + istr(i),
+ upcall_glue(i));
+ i += 1;
+ }
+
+ ret _str.connect(glues, "\n\n");
+}
+
+//
+// Local Variables:
+// mode: rust
+// fill-column: 78;
+// indent-tabs-mode: nil
+// c-basic-offset: 4
+// buffer-file-coding-system: utf-8-unix
+// compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
+// End:
+//