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).
This commit is contained in:
parent
7454b53411
commit
3aac5059ee
3 changed files with 123 additions and 72 deletions
29
src/Makefile
29
src/Makefile
|
@ -86,7 +86,6 @@ ifdef CFG_WINDOWSY
|
|||
endif
|
||||
CFG_RUNTIME := rustrt.dll
|
||||
CFG_STDLIB := std.dll
|
||||
CFG_OBJ_SUFFIX := .o
|
||||
CFG_EXE_SUFFIX := .exe
|
||||
CFG_BOOT := ./rustboot.exe
|
||||
CFG_RUSTC := ./rustc.exe
|
||||
|
@ -101,7 +100,6 @@ ifdef CFG_UNIXY
|
|||
CFG_INFO := $(info cfg: unix-y environment)
|
||||
CFG_BOOT := ./rustboot
|
||||
CFG_RUSTC := ./rustc
|
||||
CFG_OBJ_SUFFIX := .o
|
||||
CFG_RUN_TARG = LD_LIBRARY_PATH=. $(CFG_VALGRIND) $(1)
|
||||
CFG_GCC := 1
|
||||
ifdef MINGW_CROSS
|
||||
|
@ -114,7 +112,6 @@ ifdef CFG_UNIXY
|
|||
ifdef CFG_VALGRIND
|
||||
CFG_VALGRIND += wine
|
||||
endif
|
||||
CFG_OBJ_SUFFIX := .o
|
||||
CFG_EXE_SUFFIX := .exe
|
||||
CFG_GCC_CFLAGS := -march=i686
|
||||
CFG_GCC_LINK_FLAGS := -shared
|
||||
|
@ -302,15 +299,15 @@ RUNTIME_HDR := rt/globals.h \
|
|||
rt/test/rust_test_util.h
|
||||
|
||||
RUNTIME_INCS := -Irt/isaac -Irt/uthash
|
||||
RUNTIME_OBJS := $(RUNTIME_CS:.cpp=$(CFG_OBJ_SUFFIX))
|
||||
RUNTIME_OBJS := $(RUNTIME_CS:.cpp=.o)
|
||||
RUNTIME_LIBS := $(CFG_RUNTIME_LIBS)
|
||||
|
||||
STDLIB_CRATE := lib/std.rc
|
||||
STDLIB_INPUTS := $(wildcard lib/*.rc lib/*.rs lib/*/*.rs)
|
||||
COMPILER_CRATE := comp/rustc.rc
|
||||
COMPILER_INPUTS := $(wildcard comp/*.rc comp/*.rs comp/*/*.rs)
|
||||
COMPILER_INPUTS := $(wildcard comp/rustc.rc comp/*.rs comp/*/*.rs)
|
||||
|
||||
GENERATED := boot/fe/lexer.ml boot/util/version.ml
|
||||
GENERATED := boot/fe/lexer.ml boot/util/version.ml glue.o
|
||||
|
||||
all: $(CFG_RUSTC) $(MKFILES) $(GENERATED)
|
||||
|
||||
|
@ -329,7 +326,7 @@ $(CFG_STDLIB): $(STDLIB_CRATE) $(CFG_BOOT) $(MKFILES)
|
|||
@$(call CFG_ECHO, compile: $<)
|
||||
$(BOOT) -shared -o $@ $(STDLIB_CRATE)
|
||||
|
||||
%$(CFG_OBJ_SUFFIX): %.cpp $(MKFILES)
|
||||
%.o: %.cpp $(MKFILES)
|
||||
@$(call CFG_ECHO, compile: $<)
|
||||
$(CFG_QUIET)$(call CFG_COMPILE_C, $@, $(RUNTIME_INCS)) $<
|
||||
|
||||
|
@ -368,8 +365,12 @@ $(CFG_RUSTC): $(COMPILER_INPUTS) $(CFG_BOOT) $(CFG_RUNTIME) $(CFG_STDLIB)
|
|||
$(BOOT) -minimal -o $@ $<
|
||||
$(CFG_QUIET)chmod 0755 $@
|
||||
|
||||
glue.bc: $(CFG_RUSTC)
|
||||
@$(call CFG_ECHO, generate: $@)
|
||||
$(RUSTC) -o $@ -glue
|
||||
|
||||
self: $(CFG_RUSTC)
|
||||
@$(call CFG_ECHO, compile: $<)
|
||||
@$(call CFG_ECHO, compile: $(COMPILER_CRATE))
|
||||
$(RUSTC) $(COMPILER_CRATE)
|
||||
|
||||
|
||||
|
@ -758,9 +759,9 @@ test/bench/shootout/%.boot$(CFG_EXE_SUFFIX): \
|
|||
@$(call CFG_ECHO, assemble [llvm]: $<)
|
||||
$(CFG_QUIET)gcc $(CFG_GCC_CFLAGS) -o $@ -c $<
|
||||
|
||||
%.rustc$(CFG_EXE_SUFFIX): %.o $(CFG_RUNTIME)
|
||||
%.rustc$(CFG_EXE_SUFFIX): %.o $(CFG_RUNTIME) glue.o
|
||||
@$(call CFG_ECHO, link [llvm]: $<)
|
||||
$(CFG_QUIET)gcc $(CFG_GCC_CFLAGS) -o $@ $< -L. -lrustrt
|
||||
$(CFG_QUIET)gcc $(CFG_GCC_CFLAGS) glue.o -o $@ $< -L. -lrustrt
|
||||
@# dsymutil sometimes fails or prints a warning, but the
|
||||
@# program still runs. Since it simplifies debugging other
|
||||
@# programs, I\'ll live with the noise.
|
||||
|
@ -797,7 +798,7 @@ C_DEPFILES := $(RUNTIME_CS:%.cpp=%.d)
|
|||
%.d: %.cpp $(MKFILES)
|
||||
@$(call CFG_ECHO, dep: $<)
|
||||
$(CFG_QUIET)$(call CFG_DEPEND_C, $@ \
|
||||
$(patsubst %.cpp, %$(CFG_OBJ_SUFFIX), $<), \
|
||||
$(patsubst %.cpp, %.o, $<), \
|
||||
$(RUNTIME_INCS)) $< $(CFG_PATH_MUNGE) >$@.tmp \
|
||||
&& mv $@.tmp $@
|
||||
|
||||
|
@ -914,12 +915,12 @@ clean:
|
|||
$(CFG_QUIET)rm -f $(ML_DEPFILES:%.d=%.d.tmp)
|
||||
$(CFG_QUIET)rm -f $(C_DEPFILES:%.d=%.d.tmp)
|
||||
$(CFG_QUIET)rm -f $(CRATE_DEPFILES:%.d=%.d.tmp)
|
||||
$(CFG_QUIET)rm -f $(GENERATED)
|
||||
$(CFG_QUIET)rm -f $(GENERATED) glue.bc glue.s
|
||||
$(CFG_QUIET)rm -f $(CFG_BOOT) $(CFG_RUNTIME) $(CFG_STDLIB)
|
||||
$(CFG_QUIET)rm -Rf $(PKG_NAME)-*.tar.gz dist
|
||||
$(CFG_QUIET)rm -f $(foreach ext,cmx cmi cmo cma o a d exe,\
|
||||
$(CFG_QUIET)rm -f $(foreach ext,cmx cmi cmo cma bc o a d exe,\
|
||||
$(wildcard boot/*/*.$(ext) boot/*/*/*.$(ext)))
|
||||
$(CFG_QUIET)rm -Rf $(foreach ext,out llvm x86 boot rustc o s exe dSYM,\
|
||||
$(CFG_QUIET)rm -Rf $(foreach ext,out llvm x86 boot rustc bc o s exe dSYM,\
|
||||
$(wildcard test/*/*.$(ext)))
|
||||
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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,12 +6015,43 @@ 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 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());
|
||||
|
||||
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);
|
||||
|
||||
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 =
|
||||
|
@ -6027,8 +6065,6 @@ 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"));
|
||||
|
||||
llvm.LLVMSetModuleInlineAsm(llmod, _str.buf(x86.get_module_asm()));
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue