diff options
| author | Graydon Hoare <[email protected]> | 2011-03-10 17:25:11 -0800 |
|---|---|---|
| committer | Graydon Hoare <[email protected]> | 2011-03-10 17:30:08 -0800 |
| commit | 3aac5059ee986126851cb4f8bd312f1fb5f9ddea (patch) | |
| tree | d451418a7792e1f170a6b5e2b5713627b6aa04b4 /src/comp | |
| parent | rustc: Build up a list of upvars inside foreach bodies (diff) | |
| download | rust-3aac5059ee986126851cb4f8bd312f1fb5f9ddea.tar.xz rust-3aac5059ee986126851cb4f8bd312f1fb5f9ddea.zip | |
Move the glue code to a .o file. This reduces how much asm we print
in each "translation unit".
Part of it is not repetitive and should probably be moved to a .ll file, but
for now we autogen all of it.
(Modified somewhat by graydon while integrating).
Diffstat (limited to 'src/comp')
| -rw-r--r-- | src/comp/driver/rustc.rs | 16 | ||||
| -rw-r--r-- | src/comp/middle/trans.rs | 150 |
2 files changed, 108 insertions, 58 deletions
diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs index f26dd02e..00d41fff 100644 --- a/src/comp/driver/rustc.rs +++ b/src/comp/driver/rustc.rs @@ -84,6 +84,7 @@ fn usage(session.session sess, str argv0) { log ""; log " -o <filename> write output to <filename>"; log " -nowarn suppress wrong-compiler warning"; + log " -glue generate glue.bc file"; log " -shared compile a shared-library crate"; log " -pp pretty-print the input instead of compiling"; log " -h display this message"; @@ -113,6 +114,7 @@ impure fn main(vec[str] args) { let bool do_warn = true; let bool shared = false; let bool pretty = false; + let bool glue = false; auto i = 1u; auto len = _vec.len[str](args); @@ -123,6 +125,8 @@ impure fn main(vec[str] args) { if (_str.byte_len(arg) > 0u && arg.(0) == '-' as u8) { if (_str.eq(arg, "-nowarn")) { do_warn = false; + } else if (_str.eq(arg, "-glue")) { + glue = true; } else if (_str.eq(arg, "-shared")) { shared = true; } else if (_str.eq(arg, "-pp")) { @@ -159,6 +163,18 @@ impure fn main(vec[str] args) { warn_wrong_compiler(); } + if (glue) { + alt (output_file) { + case (none[str]) { + middle.trans.make_common_glue("glue.bc"); + } + case (some[str](?s)) { + middle.trans.make_common_glue(s); + } + } + ret; + } + alt (input_file) { case (none[str]) { usage(sess, args.(0)); diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 32a12c23..936a12f3 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -839,32 +839,44 @@ fn decl_upcall_glue(ModuleRef llmod, type_names tn, uint _n) -> ValueRef { ret decl_fastcall_fn(llmod, s, T_fn(args, T_int())); } -fn get_upcall(@crate_ctxt cx, str name, int n_args) -> ValueRef { - if (cx.upcalls.contains_key(name)) { - ret cx.upcalls.get(name); +fn get_upcall(&hashmap[str, ValueRef] upcalls, + type_names tn, ModuleRef llmod, + str name, int n_args) -> ValueRef { + if (upcalls.contains_key(name)) { + ret upcalls.get(name); } - auto inputs = vec(T_taskptr(cx.tn)); + auto inputs = vec(T_taskptr(tn)); inputs += _vec.init_elt[TypeRef](T_int(), n_args as uint); auto output = T_int(); - auto f = decl_cdecl_fn(cx.llmod, name, T_fn(inputs, output)); - cx.upcalls.insert(name, f); + auto f = decl_cdecl_fn(llmod, name, T_fn(inputs, output)); + upcalls.insert(name, f); ret f; } fn trans_upcall(@block_ctxt cx, str name, vec[ValueRef] args) -> result { + auto cxx = cx.fcx.ccx; + auto t = trans_upcall2(cx.build, cxx.glues, cx.fcx.lltaskptr, + cxx.upcalls, cxx.tn, cxx.llmod, name, args); + ret res(cx, t); +} + +fn trans_upcall2(builder b, @glue_fns glues, ValueRef lltaskptr, + &hashmap[str, ValueRef] upcalls, + type_names tn, ModuleRef llmod, str name, + vec[ValueRef] args) -> ValueRef { let int n = _vec.len[ValueRef](args) as int; - let ValueRef llupcall = get_upcall(cx.fcx.ccx, name, n); + let ValueRef llupcall = get_upcall(upcalls, tn, llmod, name, n); llupcall = llvm.LLVMConstPointerCast(llupcall, T_int()); - let ValueRef llglue = cx.fcx.ccx.glues.upcall_glues.(n); + let ValueRef llglue = glues.upcall_glues.(n); let vec[ValueRef] call_args = vec(llupcall); - call_args += cx.build.PtrToInt(cx.fcx.lltaskptr, T_int()); + call_args += b.PtrToInt(lltaskptr, T_int()); for (ValueRef a in args) { - call_args += cx.build.ZExtOrBitCast(a, T_int()); + call_args += b.ZExtOrBitCast(a, T_int()); } - ret res(cx, cx.build.FastCall(llglue, call_args)); + ret b.FastCall(llglue, call_args); } fn trans_non_gc_free(@block_ctxt cx, ValueRef v) -> result { @@ -5537,28 +5549,21 @@ fn i2p(ValueRef v, TypeRef t) -> ValueRef { ret llvm.LLVMConstIntToPtr(v, t); } -fn trans_exit_task_glue(@crate_ctxt cx) { +fn trans_exit_task_glue(@glue_fns glues, + &hashmap[str, ValueRef] upcalls, + type_names tn, ModuleRef llmod) { let vec[TypeRef] T_args = vec(); let vec[ValueRef] V_args = vec(); - auto llfn = cx.glues.exit_task_glue; + auto llfn = glues.exit_task_glue; let ValueRef lltaskptr = llvm.LLVMGetParam(llfn, 3u); - auto fcx = @rec(llfn=llfn, - lltaskptr=lltaskptr, - llenv=C_null(T_opaque_closure_ptr(cx.tn)), - llretptr=C_null(T_ptr(T_nil())), - mutable llself=none[ValueRef], - mutable lliterbody=none[ValueRef], - llargs=new_def_hash[ValueRef](), - llobjfields=new_def_hash[ValueRef](), - lllocals=new_def_hash[ValueRef](), - llupvars=new_def_hash[ValueRef](), - lltydescs=new_def_hash[ValueRef](), - ccx=cx); - auto bcx = new_top_block_ctxt(fcx); - trans_upcall(bcx, "upcall_exit", V_args); - bcx.build.RetVoid(); + auto entrybb = llvm.LLVMAppendBasicBlock(llfn, _str.buf("entry")); + auto build = new_builder(entrybb); + + trans_upcall2(build, glues, lltaskptr, + upcalls, tn, llmod, "upcall_exit", V_args); + build.RetVoid(); } fn create_typedefs(@crate_ctxt cx) { @@ -5567,22 +5572,22 @@ fn create_typedefs(@crate_ctxt cx) { llvm.LLVMAddTypeName(cx.llmod, _str.buf("tydesc"), T_tydesc(cx.tn)); } -fn create_crate_constant(@crate_ctxt cx) { +fn create_crate_constant(ValueRef crate_ptr, @glue_fns glues) { - let ValueRef crate_addr = p2i(cx.crate_ptr); + let ValueRef crate_addr = p2i(crate_ptr); let ValueRef activate_glue_off = - llvm.LLVMConstSub(p2i(cx.glues.activate_glue), crate_addr); + llvm.LLVMConstSub(p2i(glues.activate_glue), crate_addr); let ValueRef yield_glue_off = - llvm.LLVMConstSub(p2i(cx.glues.yield_glue), crate_addr); + llvm.LLVMConstSub(p2i(glues.yield_glue), crate_addr); let ValueRef exit_task_glue_off = - llvm.LLVMConstSub(p2i(cx.glues.exit_task_glue), crate_addr); + llvm.LLVMConstSub(p2i(glues.exit_task_glue), crate_addr); let ValueRef crate_val = C_struct(vec(C_null(T_int()), // ptrdiff_t image_base_off - p2i(cx.crate_ptr), // uintptr_t self_addr + p2i(crate_ptr), // uintptr_t self_addr C_null(T_int()), // ptrdiff_t debug_abbrev_off C_null(T_int()), // size_t debug_abbrev_sz C_null(T_int()), // ptrdiff_t debug_info_off @@ -5598,7 +5603,7 @@ fn create_crate_constant(@crate_ctxt cx) { C_int(abi.abi_x86_rustc_fastcall) // uintptr_t abi_tag )); - llvm.LLVMSetInitializer(cx.crate_ptr, crate_val); + llvm.LLVMSetInitializer(crate_ptr, crate_val); } fn find_main_fn(@crate_ctxt cx) -> ValueRef { @@ -5700,26 +5705,28 @@ fn check_module(ModuleRef llmod) { // TODO: run the linter here also, once there are llvm-c bindings for it. } -fn make_no_op_type_glue(ModuleRef llmod, type_names tn) -> ValueRef { +fn decl_no_op_type_glue(ModuleRef llmod, type_names tn) -> ValueRef { auto ty = T_fn(vec(T_taskptr(tn), T_ptr(T_i8())), T_void()); - auto fun = decl_fastcall_fn(llmod, abi.no_op_type_glue_name(), ty); + ret decl_fastcall_fn(llmod, abi.no_op_type_glue_name(), ty); +} + +fn make_no_op_type_glue(ValueRef fun) { auto bb_name = _str.buf("_rust_no_op_type_glue_bb"); auto llbb = llvm.LLVMAppendBasicBlock(fun, bb_name); new_builder(llbb).RetVoid(); - ret fun; } -fn make_memcpy_glue(ModuleRef llmod) -> ValueRef { - - // We're not using the LLVM memcpy intrinsic. It appears to call through - // to the platform memcpy in some cases, which is not terribly safe to run - // on a rust stack. - +fn decl_memcpy_glue(ModuleRef llmod) -> ValueRef { auto p8 = T_ptr(T_i8()); auto ty = T_fn(vec(p8, p8, T_int()), T_void()); - auto fun = decl_fastcall_fn(llmod, abi.memcpy_glue_name(), ty); + ret decl_fastcall_fn(llmod, abi.memcpy_glue_name(), ty); +} +fn make_memcpy_glue(ValueRef fun) { + // We're not using the LLVM memcpy intrinsic. It appears to call through + // to the platform memcpy in some cases, which is not terribly safe to run + // on a rust stack. auto initbb = llvm.LLVMAppendBasicBlock(fun, _str.buf("init")); auto hdrbb = llvm.LLVMAppendBasicBlock(fun, _str.buf("hdr")); auto loopbb = llvm.LLVMAppendBasicBlock(fun, _str.buf("loop")); @@ -5751,18 +5758,18 @@ fn make_memcpy_glue(ModuleRef llmod) -> ValueRef { // End block auto eb = new_builder(endbb); eb.RetVoid(); - ret fun; } -fn make_bzero_glue(ModuleRef llmod) -> ValueRef { - - // We're not using the LLVM memset intrinsic. Same as with memcpy. - +fn decl_bzero_glue(ModuleRef llmod) -> ValueRef { auto p8 = T_ptr(T_i8()); auto ty = T_fn(vec(p8, T_int()), T_void()); - auto fun = decl_fastcall_fn(llmod, abi.bzero_glue_name(), ty); + ret decl_fastcall_fn(llmod, abi.bzero_glue_name(), ty); +} +fn make_bzero_glue(ModuleRef llmod) -> ValueRef { + // We're not using the LLVM memset intrinsic. Same as with memcpy. + auto fun = decl_bzero_glue(llmod); auto initbb = llvm.LLVMAppendBasicBlock(fun, _str.buf("init")); auto hdrbb = llvm.LLVMAppendBasicBlock(fun, _str.buf("hdr")); auto loopbb = llvm.LLVMAppendBasicBlock(fun, _str.buf("loop")); @@ -6008,14 +6015,16 @@ fn make_glues(ModuleRef llmod, type_names tn) -> @glue_fns { upcall_glues = _vec.init_fn[ValueRef](bind decl_upcall_glue(llmod, tn, _), abi.n_upcall_glues as uint), - no_op_type_glue = make_no_op_type_glue(llmod, tn), - memcpy_glue = make_memcpy_glue(llmod), - bzero_glue = make_bzero_glue(llmod), + no_op_type_glue = decl_no_op_type_glue(llmod, tn), + memcpy_glue = decl_memcpy_glue(llmod), + bzero_glue = decl_bzero_glue(llmod), vec_append_glue = make_vec_append_glue(llmod, tn)); } -fn trans_crate(session.session sess, @ast.crate crate, str output, - bool shared) { +fn make_common_glue(str output) { + // FIXME: part of this is repetitive and is probably a good idea + // to autogen it, but things like the memcpy implementation are not + // and it might be better to just check in a .ll file. auto llmod = llvm.LLVMModuleCreateWithNameInContext(_str.buf("rust_out"), llvm.LLVMGetGlobalContext()); @@ -6027,8 +6036,35 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, let ValueRef crate_ptr = llvm.LLVMAddGlobal(llmod, T_crate(tn), _str.buf("rust_crate")); + auto intrinsics = declare_intrinsics(llmod); + llvm.LLVMSetModuleInlineAsm(llmod, _str.buf(x86.get_module_asm())); + auto glues = make_glues(llmod, tn); + create_crate_constant(crate_ptr, glues); + make_memcpy_glue(glues.memcpy_glue); + + trans_exit_task_glue(glues, new_str_hash[ValueRef](), tn, llmod); + + check_module(llmod); + + llvm.LLVMWriteBitcodeToFile(llmod, _str.buf(output)); + llvm.LLVMDisposeModule(llmod); +} + +fn trans_crate(session.session sess, @ast.crate crate, str output, + bool shared) { + auto llmod = + llvm.LLVMModuleCreateWithNameInContext(_str.buf("rust_out"), + llvm.LLVMGetGlobalContext()); + + llvm.LLVMSetDataLayout(llmod, _str.buf(x86.get_data_layout())); + llvm.LLVMSetTarget(llmod, _str.buf(x86.get_target_triple())); + auto td = mk_target_data(x86.get_data_layout()); + auto tn = mk_type_names(); + let ValueRef crate_ptr = + llvm.LLVMAddGlobal(llmod, T_crate(tn), _str.buf("rust_crate")); + auto intrinsics = declare_intrinsics(llmod); auto glues = make_glues(llmod, tn); @@ -6069,9 +6105,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, trans_constants(cx, crate); trans_mod(cx, crate.node.module); - trans_exit_task_glue(cx); trans_vec_append_glue(cx); - create_crate_constant(cx); if (!shared) { trans_main_fn(cx, cx.crate_ptr); } |