diff options
Diffstat (limited to 'src/comp')
| -rw-r--r-- | src/comp/back/abi.rs | 2 | ||||
| -rw-r--r-- | src/comp/back/x86.rs | 28 | ||||
| -rw-r--r-- | src/comp/lib/llvm.rs | 15 | ||||
| -rw-r--r-- | src/comp/middle/trans.rs | 67 | ||||
| -rw-r--r-- | src/comp/util/common.rs | 5 |
5 files changed, 95 insertions, 22 deletions
diff --git a/src/comp/back/abi.rs b/src/comp/back/abi.rs index 157bf876..1a349a7b 100644 --- a/src/comp/back/abi.rs +++ b/src/comp/back/abi.rs @@ -34,6 +34,8 @@ const int calltup_elt_iterator_args = 5; const int worst_case_glue_call_args = 7; +const int n_upcall_glues = 7; + // // Local Variables: // mode: rust diff --git a/src/comp/back/x86.rs b/src/comp/back/x86.rs index fcf65cc0..bfe50200 100644 --- a/src/comp/back/x86.rs +++ b/src/comp/back/x86.rs @@ -1,15 +1,11 @@ import lib.llvm.llvm; import lib.llvm.llvm.ModuleRef; import std._str; -import std._int; import std._vec; +import util.common.istr; const int wordsz = 4; -fn istr(int i) -> str { - ret _int.to_str(i, 10u); -} - fn wstr(int i) -> str { ret istr(i * wordsz); } @@ -122,6 +118,13 @@ fn decl_glue(int align, str prefix, str name, vec[str] insns) -> str { } +fn decl_upcall_glue(int align, str prefix, uint n) -> str { + let int i = n as int; + ret decl_glue(align, prefix, + "rust_upcall_" + istr(i), + upcall_glue(i)); +} + fn get_module_asm() -> str { auto align = 4; auto prefix = ""; @@ -133,20 +136,15 @@ fn get_module_asm() -> str { 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; - } + rust_yield_glue())) + + + _vec.init_fn[str](bind decl_upcall_glue(align, prefix, _), + abi.n_upcall_glues as uint); ret _str.connect(glues, "\n\n"); } + // // Local Variables: // mode: rust diff --git a/src/comp/lib/llvm.rs b/src/comp/lib/llvm.rs index f0c4428c..e5db62c7 100644 --- a/src/comp/lib/llvm.rs +++ b/src/comp/lib/llvm.rs @@ -25,8 +25,19 @@ type LongLong = i64; type Long = i32; type Bool = int; -fn True() -> Bool { ret 1; } -fn False() -> Bool { ret 0; } + +const Bool True = 1; +const Bool False = 0; + +// Consts for the LLVM CallConv type, pre-cast to uint. +// FIXME: figure out a way to merge these with the native +// typedef and/or a tag type in the native module below. + +const uint LLVMCCallConv = 0u; +const uint LLVMFastCallConv = 8u; +const uint LLVMColdCallConv = 9u; +const uint LLVMX86StdcallCallConv = 64u; +const uint LLVMX86FastcallCallConv = 65u; native mod llvm = llvm_lib { diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 1b1c5b2d..b1e1306e 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -6,6 +6,9 @@ import std._vec.rustrt.vbuf; import front.ast; import driver.session; import back.x86; +import back.abi; + +import util.common.istr; import lib.llvm.llvm; import lib.llvm.builder; @@ -18,8 +21,13 @@ import lib.llvm.llvm.BasicBlockRef; import lib.llvm.False; import lib.llvm.True; +type glue_fns = rec(ValueRef activate_glue, + ValueRef yield_glue, + vec[ValueRef] upcall_glues); + type trans_ctxt = rec(session.session sess, ModuleRef llmod, + @glue_fns glues, str path); fn T_nil() -> TypeRef { @@ -34,9 +42,53 @@ fn T_fn(vec[TypeRef] inputs, TypeRef output) -> TypeRef { ret llvm.LLVMFunctionType(output, _vec.buf[TypeRef](inputs), _vec.len[TypeRef](inputs), - False()); + False); +} + +fn T_ptr(TypeRef t) -> TypeRef { + ret llvm.LLVMPointerType(t, 0u); +} + +fn T_struct(vec[TypeRef] elts) -> TypeRef { + ret llvm.LLVMStructType(_vec.buf[TypeRef](elts), + _vec.len[TypeRef](elts), + False); +} + +fn T_opaque() -> TypeRef { + ret llvm.LLVMOpaqueType(); +} + +fn T_task() -> TypeRef { + ret T_struct(vec(T_int(), // Refcount + T_opaque())); // Rest is opaque for now +} + +fn decl_cdecl_fn(ModuleRef llmod, str name, + vec[TypeRef] inputs, TypeRef output) -> ValueRef { + let TypeRef llty = T_fn(inputs, output); + let ValueRef llfn = + llvm.LLVMAddFunction(llmod, _str.buf(name), llty); + llvm.LLVMSetFunctionCallConv(llfn, lib.llvm.LLVMCCallConv); + ret llfn; +} + +fn decl_glue(ModuleRef llmod, str s) -> ValueRef { + ret decl_cdecl_fn(llmod, s, vec(T_ptr(T_task())), T_nil()); } +fn decl_upcall(ModuleRef llmod, uint _n) -> ValueRef { + let int n = _n as int; + let str s = "rust_upcall_" + istr(n); + let vec[TypeRef] args = + vec(T_ptr(T_task()), // taskptr + T_int()) // callee + + _vec.init_elt[TypeRef](T_int(), n as uint); + + ret decl_cdecl_fn(llmod, s, args, T_int()); +} + + type terminator = fn(&trans_ctxt cx, builder b); fn trans_log(&trans_ctxt cx, builder b, &ast.atom a) { @@ -71,10 +123,9 @@ fn trans_block(&trans_ctxt cx, ValueRef llfn, &ast.block b, terminator t) { fn trans_fn(&trans_ctxt cx, &ast._fn f) { let vec[TypeRef] args = vec(); - let TypeRef llty = T_fn(args, T_nil()); - let ValueRef llfn = - llvm.LLVMAddFunction(cx.llmod, _str.buf(cx.path), llty); + let ValueRef llfn = decl_cdecl_fn(cx.llmod, cx.path, args, T_nil()); auto term = default_terminate; + trans_block(cx, llfn, f.body, term); } @@ -103,7 +154,13 @@ fn trans_crate(session.session sess, ast.crate crate) { llvm.LLVMSetModuleInlineAsm(llmod, _str.buf(x86.get_module_asm())); - auto cx = rec(sess=sess, llmod=llmod, path=""); + auto glues = @rec(activate_glue = decl_glue(llmod, "rust_activate_glue"), + yield_glue = decl_glue(llmod, "rust_yield_glue"), + upcall_glues = + _vec.init_fn[ValueRef](bind decl_upcall(llmod, _), + abi.n_upcall_glues as uint)); + + auto cx = rec(sess=sess, llmod=llmod, glues=glues, path=""); trans_mod(cx, crate.module); llvm.LLVMWriteBitcodeToFile(llmod, _str.buf("rust_out.bc")); diff --git a/src/comp/util/common.rs b/src/comp/util/common.rs index 9952c89b..7456a8c8 100644 --- a/src/comp/util/common.rs +++ b/src/comp/util/common.rs @@ -1,4 +1,5 @@ import std._uint; +import std._int; type pos = rec(uint line, uint col); type span = rec(str filename, pos lo, pos hi); @@ -41,6 +42,10 @@ fn new_str_hash[V]() -> std.map.hashmap[str,V] { ret std.map.mk_hashmap[str,V](hasher, eqer); } +fn istr(int i) -> str { + ret _int.to_str(i, 10u); +} + // // Local Variables: // mode: rust |