rust/src/comp/back/x86.rs

240 lines
6.0 KiB
Rust
Raw Normal View History

import lib::llvm::llvm;
import lib::llvm::llvm::ModuleRef;
import std::str;
import std::vec;
import std::os::target_os;
import util::common::istr;
const int wordsz = 4;
fn wstr(int i) -> str {
ret istr(i * wordsz);
}
fn start() -> vec[str] {
ret [".cfi_startproc"];
}
fn end() -> vec[str] {
ret [".cfi_endproc"];
}
fn save_callee_saves() -> vec[str] {
ret ["pushl %ebp",
"pushl %edi",
"pushl %esi",
"pushl %ebx"];
}
fn save_callee_saves_with_cfi() -> vec[str] {
auto offset = 8;
auto t;
t = ["pushl %ebp"];
t += [".cfi_def_cfa_offset " + istr(offset)];
t += [".cfi_offset %ebp, -" + istr(offset)];
t += ["pushl %edi"];
offset += 4;
t += [".cfi_def_cfa_offset " + istr(offset)];
t += ["pushl %esi"];
offset += 4;
t += [".cfi_def_cfa_offset " + istr(offset)];
t += ["pushl %ebx"];
offset += 4;
t += [".cfi_def_cfa_offset " + istr(offset)];
ret t;
}
fn restore_callee_saves() -> vec[str] {
ret ["popl %ebx",
"popl %esi",
"popl %edi",
"popl %ebp"];
}
2011-03-09 15:05:22 -05:00
fn load_esp_from_rust_sp_first_arg() -> vec[str] {
ret ["movl " + wstr(abi::task_field_rust_sp) + "(%ecx), %esp"];
}
2011-03-09 15:05:22 -05:00
fn load_esp_from_runtime_sp_first_arg() -> vec[str] {
ret ["movl " + wstr(abi::task_field_runtime_sp) + "(%ecx), %esp"];
}
2011-03-09 15:05:22 -05:00
fn store_esp_to_rust_sp_first_arg() -> vec[str] {
ret ["movl %esp, " + wstr(abi::task_field_rust_sp) + "(%ecx)"];
}
2011-03-09 15:05:22 -05:00
fn store_esp_to_runtime_sp_first_arg() -> vec[str] {
ret ["movl %esp, " + wstr(abi::task_field_runtime_sp) + "(%ecx)"];
}
2011-03-09 15:05:22 -05:00
fn load_esp_from_rust_sp_second_arg() -> vec[str] {
ret ["movl " + wstr(abi::task_field_rust_sp) + "(%edx), %esp"];
2011-03-09 15:05:22 -05:00
}
fn load_esp_from_runtime_sp_second_arg() -> vec[str] {
ret ["movl " + wstr(abi::task_field_runtime_sp) + "(%edx), %esp"];
2011-03-09 15:05:22 -05:00
}
fn store_esp_to_rust_sp_second_arg() -> vec[str] {
ret ["movl %esp, " + wstr(abi::task_field_rust_sp) + "(%edx)"];
2011-03-09 15:05:22 -05:00
}
fn store_esp_to_runtime_sp_second_arg() -> vec[str] {
ret ["movl %esp, " + wstr(abi::task_field_runtime_sp) + "(%edx)"];
2011-03-09 15:05:22 -05:00
}
fn native_glue(int n_args, abi::native_glue_type ngt) -> vec[str] {
let bool pass_task;
alt (ngt) {
case (abi::ngt_rust) { pass_task = true; }
case (abi::ngt_pure_rust) { pass_task = true; }
case (abi::ngt_cdecl) { pass_task = false; }
}
/*
* 0, 4, 8, 12 are callee-saves
* 16 is retpc
* 20 .. (5+i) * 4 are args
*
* ecx is taskptr
* edx is callee
*
*/
fn copy_arg(bool pass_task, uint i) -> str {
if (i == 0u && pass_task) {
ret "movl %edx, (%esp)";
}
auto dst_off = wstr(0 + (i as int));
auto src_off;
if (pass_task) {
src_off = wstr(4 + (i as int));
} else {
src_off = wstr(5 + (i as int));
}
auto m = ["movl " + src_off + "(%ebp),%eax",
"movl %eax," + dst_off + "(%esp)"];
ret str::connect(m, "\n\t");
}
auto carg = bind copy_arg(pass_task, _);
ret
start()
+ save_callee_saves_with_cfi()
+ ["movl %esp, %ebp # ebp = rust_sp"]
+ [".cfi_def_cfa_register %ebp"]
2011-03-09 15:05:22 -05:00
+ store_esp_to_rust_sp_second_arg()
+ load_esp_from_runtime_sp_second_arg()
+ ["subl $" + wstr(n_args) + ", %esp # esp -= args",
"andl $~0xf, %esp # align esp down"]
+ vec::init_fn[str](carg, (n_args) as uint)
+ ["movl %edx, %edi # save task from edx to edi",
2011-03-09 15:05:22 -05:00
"call *%ecx # call *%ecx",
"movl %edi, %edx # restore edi-saved task to edx"]
2011-03-09 15:05:22 -05:00
+ load_esp_from_rust_sp_second_arg()
+ restore_callee_saves()
+ ["ret"]
+ end();
}
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 decl_native_glue(int align, str prefix, abi::native_glue_type ngt, uint n)
-> str {
let int i = n as int;
ret decl_glue(align, prefix,
abi::native_glue_name(i, ngt),
native_glue(i, ngt));
}
fn get_symbol_prefix() -> str {
if (str::eq(target_os(), "macos") ||
str::eq(target_os(), "win32")) {
ret "_";
} else {
ret "";
}
}
fn get_module_asm() -> str {
auto align = 4;
auto prefix = get_symbol_prefix();
2011-05-24 18:23:39 -04:00
let vec[str] glues =
[]
+ vec::init_fn[str](bind decl_native_glue(align, prefix,
abi::ngt_rust, _), (abi::n_native_glues + 1) as uint)
+ vec::init_fn[str](bind decl_native_glue(align, prefix,
abi::ngt_pure_rust, _), (abi::n_native_glues + 1) as uint)
+ vec::init_fn[str](bind decl_native_glue(align, prefix,
abi::ngt_cdecl, _), (abi::n_native_glues + 1) as uint);
ret str::connect(glues, "\n\n");
}
fn get_meta_sect_name() -> str {
if (str::eq(target_os(), "macos")) {
ret "__DATA,__note.rustc";
}
if (str::eq(target_os(), "win32")) {
ret ".note.rustc";
}
ret ".note.rustc";
}
fn get_data_layout() -> str {
if (str::eq(target_os(), "macos")) {
ret "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64" +
"-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" +
"-n8:16:32";
}
if (str::eq(target_os(), "win32")) {
ret "e-p:32:32-f64:64:64-i64:64:64-f80:32:32-n8:16:32";
}
ret "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32";
}
fn get_target_triple() -> str {
if (str::eq(target_os(), "macos")) {
ret "i686-apple-darwin";
}
if (str::eq(target_os(), "win32")) {
ret "i686-pc-mingw32";
}
2011-05-05 17:20:27 -07:00
ret "i686-unknown-linux-gnu";
}
//
// 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 $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//