2010-09-23 17:46:31 -05:00
|
|
|
import lib.llvm.llvm;
|
|
|
|
import lib.llvm.llvm.ModuleRef;
|
|
|
|
import std._str;
|
|
|
|
import std._vec;
|
2010-10-22 18:15:06 -05:00
|
|
|
import std.os.target_os;
|
2010-09-23 19:16:34 -05:00
|
|
|
import util.common.istr;
|
2010-09-23 17:46:31 -05:00
|
|
|
|
|
|
|
const int wordsz = 4;
|
|
|
|
|
|
|
|
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] {
|
2010-11-14 15:04:01 -06:00
|
|
|
ret vec("movl " + wstr(abi.task_field_rust_sp) + "(%ecx), %esp");
|
2010-09-23 17:46:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn load_esp_from_runtime_sp() -> vec[str] {
|
2010-11-14 15:04:01 -06:00
|
|
|
ret vec("movl " + wstr(abi.task_field_runtime_sp) + "(%ecx), %esp");
|
2010-09-23 17:46:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn store_esp_to_rust_sp() -> vec[str] {
|
2010-11-14 15:04:01 -06:00
|
|
|
ret vec("movl %esp, " + wstr(abi.task_field_rust_sp) + "(%ecx)");
|
2010-09-23 17:46:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn store_esp_to_runtime_sp() -> vec[str] {
|
2010-11-14 15:04:01 -06:00
|
|
|
ret vec("movl %esp, " + wstr(abi.task_field_runtime_sp) + "(%ecx)");
|
2010-09-23 17:46:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn rust_activate_glue() -> vec[str] {
|
2010-11-14 15:04:01 -06:00
|
|
|
ret vec("movl 4(%esp), %ecx # ecx = rust_task")
|
2010-09-23 17:46:31 -05:00
|
|
|
+ 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.
|
2010-11-15 14:45:26 -06:00
|
|
|
+ vec("addl $20, " + wstr(abi.task_field_rust_sp) + "(%ecx)")
|
2010-09-23 17:46:31 -05:00
|
|
|
|
|
|
|
+ restore_callee_saves()
|
|
|
|
+ vec("ret");
|
|
|
|
}
|
|
|
|
|
|
|
|
fn rust_yield_glue() -> vec[str] {
|
2010-11-14 15:04:01 -06:00
|
|
|
ret vec("movl 0(%esp), %ecx # ecx = rust_task")
|
2010-09-23 17:46:31 -05:00
|
|
|
+ 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
|
2010-11-14 15:41:10 -06:00
|
|
|
* 20 .. (5+i) * 4 are args
|
|
|
|
*
|
|
|
|
* ecx is taskptr
|
|
|
|
* edx is callee
|
|
|
|
*
|
2010-09-23 17:46:31 -05:00
|
|
|
*/
|
|
|
|
|
|
|
|
fn copy_arg(uint i) -> str {
|
2010-11-14 15:41:10 -06:00
|
|
|
auto src_off = wstr(5 + (i as int));
|
2010-09-27 16:42:58 -05:00
|
|
|
auto dst_off = wstr(1 + (i as int));
|
2010-11-14 15:41:10 -06:00
|
|
|
auto m = vec("movl " + src_off + "(%ebp),%eax",
|
|
|
|
"movl %eax," + dst_off + "(%esp)");
|
2010-09-23 17:46:31 -05:00
|
|
|
ret _str.connect(m, "\n\t");
|
|
|
|
}
|
|
|
|
|
|
|
|
auto carg = copy_arg;
|
|
|
|
|
|
|
|
ret
|
|
|
|
save_callee_saves()
|
|
|
|
|
2010-11-14 15:41:10 -06:00
|
|
|
+ vec("movl %esp, %ebp # ebp = rust_sp")
|
2010-09-23 17:46:31 -05:00
|
|
|
|
|
|
|
+ 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",
|
2010-11-14 15:04:01 -06:00
|
|
|
"movl %ecx, (%esp) # arg[0] = rust_task ")
|
2010-09-23 17:46:31 -05:00
|
|
|
|
|
|
|
+ _vec.init_fn[str](carg, n_args as uint)
|
|
|
|
|
2010-11-14 15:41:10 -06:00
|
|
|
+ vec("movl %ecx, %edi # save task from ecx to edi",
|
2010-09-23 17:46:31 -05:00
|
|
|
"call *%edx # call *%edx",
|
2010-11-14 15:41:10 -06:00
|
|
|
"movl %edi, %ecx # restore edi-saved task to ecx")
|
2010-09-23 17:46:31 -05:00
|
|
|
|
|
|
|
+ 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");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-09-23 19:16:34 -05:00
|
|
|
fn decl_upcall_glue(int align, str prefix, uint n) -> str {
|
|
|
|
let int i = n as int;
|
|
|
|
ret decl_glue(align, prefix,
|
2010-09-24 16:56:04 -05:00
|
|
|
abi.upcall_glue_name(i),
|
2010-09-23 19:16:34 -05:00
|
|
|
upcall_glue(i));
|
|
|
|
}
|
|
|
|
|
2010-11-05 20:29:18 -05:00
|
|
|
fn get_symbol_prefix() -> str {
|
|
|
|
if (_str.eq(target_os(), "macos") ||
|
|
|
|
_str.eq(target_os(), "win32")) {
|
|
|
|
ret "_";
|
|
|
|
} else {
|
|
|
|
ret "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-23 17:46:31 -05:00
|
|
|
fn get_module_asm() -> str {
|
|
|
|
auto align = 4;
|
2010-10-22 18:15:06 -05:00
|
|
|
|
2010-11-05 20:29:18 -05:00
|
|
|
auto prefix = get_symbol_prefix();
|
2010-09-23 17:46:31 -05:00
|
|
|
|
|
|
|
auto glues =
|
|
|
|
vec(decl_glue(align, prefix,
|
2010-09-24 16:56:04 -05:00
|
|
|
abi.activate_glue_name(),
|
2010-09-23 17:46:31 -05:00
|
|
|
rust_activate_glue()),
|
|
|
|
|
|
|
|
decl_glue(align, prefix,
|
2010-09-24 16:56:04 -05:00
|
|
|
abi.yield_glue_name(),
|
2010-09-23 19:16:34 -05:00
|
|
|
rust_yield_glue()))
|
|
|
|
|
|
|
|
+ _vec.init_fn[str](bind decl_upcall_glue(align, prefix, _),
|
|
|
|
abi.n_upcall_glues as uint);
|
2010-09-23 17:46:31 -05:00
|
|
|
|
|
|
|
ret _str.connect(glues, "\n\n");
|
|
|
|
}
|
|
|
|
|
2010-09-23 19:16:34 -05:00
|
|
|
|
2010-09-23 17:46:31 -05:00
|
|
|
//
|
|
|
|
// 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:
|
|
|
|
//
|