Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade LLVM #10758

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions mk/llvm.mk
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ endif
# dependencies. In these cases, commit a change that touches
# the stamp in the source dir.
$$(LLVM_STAMP_$(1)): $(S)src/rustllvm/llvm-auto-clean-trigger
@$$(call E, make: cleaning llvm)
$(Q)$(MAKE) clean-llvm
@$$(call E, make: done cleaning llvm)
touch $$@

endef
Expand Down
173 changes: 30 additions & 143 deletions src/librustc/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,111 +82,8 @@ pub fn WriteOutputFile(
}
}

pub mod jit {

use back::link::llvm_err;
use driver::session::Session;
use lib::llvm::llvm;
use lib::llvm::{ModuleRef, ContextRef, ExecutionEngineRef};

use std::c_str::ToCStr;
use std::cast;
use std::local_data;
use std::unstable::intrinsics;

struct LLVMJITData {
ee: ExecutionEngineRef,
llcx: ContextRef
}

pub trait Engine {}
impl Engine for LLVMJITData {}

impl Drop for LLVMJITData {
fn drop(&mut self) {
unsafe {
llvm::LLVMDisposeExecutionEngine(self.ee);
llvm::LLVMContextDispose(self.llcx);
}
}
}

pub fn exec(sess: Session,
c: ContextRef,
m: ModuleRef,
stacks: bool) {
unsafe {
let manager = llvm::LLVMRustPrepareJIT(intrinsics::morestack_addr());

// We need to tell JIT where to resolve all linked
// symbols from. The equivalent of -lstd, -lcore, etc.
// By default the JIT will resolve symbols from the extra and
// core linked into rustc. We don't want that,
// incase the user wants to use an older extra library.

// We custom-build a JIT execution engine via some rust wrappers
// first. This wrappers takes ownership of the module passed in.
let ee = llvm::LLVMRustBuildJIT(manager, m, stacks);
if ee.is_null() {
llvm::LLVMContextDispose(c);
llvm_err(sess, ~"Could not create the JIT");
}

// Next, we need to get a handle on the _rust_main function by
// looking up it's corresponding ValueRef and then requesting that
// the execution engine compiles the function.
let fun = "_rust_main".with_c_str(|entry| {
llvm::LLVMGetNamedFunction(m, entry)
});
if fun.is_null() {
llvm::LLVMDisposeExecutionEngine(ee);
llvm::LLVMContextDispose(c);
llvm_err(sess, ~"Could not find _rust_main in the JIT");
}

// Finally, once we have the pointer to the code, we can do some
// closure magic here to turn it straight into a callable rust
// closure
let code = llvm::LLVMGetPointerToGlobal(ee, fun);
assert!(!code.is_null());
let func: extern "Rust" fn() = cast::transmute(code);
func();

// Currently there is no method of re-using the executing engine
// from LLVM in another call to the JIT. While this kinda defeats
// the purpose of having a JIT in the first place, there isn't
// actually much code currently which would re-use data between
// different invocations of this. Additionally, the compilation
// model currently isn't designed to support this scenario.
//
// We can't destroy the engine/context immediately here, however,
// because of annihilation. The JIT code contains drop glue for any
// types defined in the crate we just ran, and if any of those boxes
// are going to be dropped during annihilation, the drop glue must
// be run. Hence, we need to transfer ownership of this jit engine
// to the caller of this function. To be convenient for now, we
// shove it into TLS and have someone else remove it later on.
let data = ~LLVMJITData { ee: ee, llcx: c };
set_engine(data as ~Engine);
}
}

// The stage1 compiler won't work, but that doesn't really matter. TLS
// changed only very recently to allow storage of owned values.
local_data_key!(engine_key: ~Engine)

fn set_engine(engine: ~Engine) {
local_data::set(engine_key, engine)
}

pub fn consume_engine() -> Option<~Engine> {
local_data::pop(engine_key)
}
}

pub mod write {

use back::link::jit;
use back::link::{WriteOutputFile, output_type};
use back::link::{output_type_assembly, output_type_bitcode};
use back::link::{output_type_exe, output_type_llvm_assembly};
Expand Down Expand Up @@ -307,48 +204,38 @@ pub mod write {
})
}

if sess.opts.jit {
// If we are using JIT, go ahead and create and execute the
// engine now. JIT execution takes ownership of the module and
// context, so don't dispose
jit::exec(sess, llcx, llmod, true);
} else {
// Create a codegen-specific pass manager to emit the actual
// assembly or object files. This may not end up getting used,
// but we make it anyway for good measure.
let cpm = llvm::LLVMCreatePassManager();
llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod);
llvm::LLVMRustAddLibraryInfo(cpm, llmod);

match output_type {
output_type_none => {}
output_type_bitcode => {
output.with_c_str(|buf| {
llvm::LLVMWriteBitcodeToFile(llmod, buf);
})
}
output_type_llvm_assembly => {
output.with_c_str(|output| {
llvm::LLVMRustPrintModule(cpm, llmod, output)
})
}
output_type_assembly => {
WriteOutputFile(sess, tm, cpm, llmod, output, lib::llvm::AssemblyFile);
}
output_type_exe | output_type_object => {
WriteOutputFile(sess, tm, cpm, llmod, output, lib::llvm::ObjectFile);
}
// Create a codegen-specific pass manager to emit the actual
// assembly or object files. This may not end up getting used,
// but we make it anyway for good measure.
let cpm = llvm::LLVMCreatePassManager();
llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod);
llvm::LLVMRustAddLibraryInfo(cpm, llmod);

match output_type {
output_type_none => {}
output_type_bitcode => {
output.with_c_str(|buf| {
llvm::LLVMWriteBitcodeToFile(llmod, buf);
})
}
output_type_llvm_assembly => {
output.with_c_str(|output| {
llvm::LLVMRustPrintModule(cpm, llmod, output)
})
}
output_type_assembly => {
WriteOutputFile(sess, tm, cpm, llmod, output, lib::llvm::AssemblyFile);
}
output_type_exe | output_type_object => {
WriteOutputFile(sess, tm, cpm, llmod, output, lib::llvm::ObjectFile);
}

llvm::LLVMDisposePassManager(cpm);
}

llvm::LLVMDisposePassManager(cpm);

llvm::LLVMRustDisposeTargetMachine(tm);
// the jit takes ownership of these two items
if !sess.opts.jit {
llvm::LLVMDisposeModule(llmod);
llvm::LLVMContextDispose(llcx);
}
llvm::LLVMDisposeModule(llmod);
llvm::LLVMContextDispose(llcx);
if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); }
}
}
Expand Down Expand Up @@ -711,8 +598,8 @@ pub fn sanitize(s: &str) -> ~str {
',' => result.push_str("$C$"),

// '.' doesn't occur in types and functions, so reuse it
// for ':'
':' => result.push_char('.'),
// for ':' and '-'
'-' | ':' => result.push_char('.'),

// These are legal symbols
'a' .. 'z'
Expand Down
20 changes: 2 additions & 18 deletions src/librustc/back/upcall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,10 @@ use middle::trans::type_::Type;
use lib::llvm::{ModuleRef, ValueRef};

pub struct Upcalls {
trace: ValueRef,
rust_personality: ValueRef,
reset_stack_limit: ValueRef
}

macro_rules! upcall (
(fn $name:ident($($arg:expr),+) -> $ret:expr) => ({
let fn_ty = Type::func([ $($arg),* ], &$ret);
base::decl_cdecl_fn(llmod, ~"upcall_" + stringify!($name), fn_ty)
});
(nothrow fn $name:ident($($arg:expr),+) -> $ret:expr) => ({
let fn_ty = Type::func([ $($arg),* ], &$ret);
let decl = base::decl_cdecl_fn(llmod, ~"upcall_" + stringify!($name), fn_ty);
base::set_no_unwind(decl);
decl
});
(nothrow fn $name:ident -> $ret:expr) => ({
let fn_ty = Type::func([], &$ret);
let decl = base::decl_cdecl_fn(llmod, ~"upcall_" + stringify!($name), fn_ty);
Expand All @@ -39,13 +27,9 @@ macro_rules! upcall (
})
)

pub fn declare_upcalls(targ_cfg: @session::config, llmod: ModuleRef) -> @Upcalls {
let opaque_ptr = Type::i8().ptr_to();
let int_ty = Type::int(targ_cfg.arch);

pub fn declare_upcalls(_targ_cfg: @session::config,
llmod: ModuleRef) -> @Upcalls {
@Upcalls {
trace: upcall!(fn trace(opaque_ptr, opaque_ptr, int_ty) -> Type::void()),
rust_personality: upcall!(nothrow fn rust_personality -> Type::i32()),
reset_stack_limit: upcall!(nothrow fn reset_stack_limit -> Type::void())
}
}
7 changes: 0 additions & 7 deletions src/librustc/driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -419,11 +419,6 @@ pub fn stop_after_phase_5(sess: Session) -> bool {
debug!("not building executable, returning early from compile_input");
return true;
}

if sess.opts.jit {
debug!("running JIT, returning early from compile_input");
return true;
}
return false;
}

Expand Down Expand Up @@ -751,7 +746,6 @@ pub fn build_session_options(binary: @str,
} else { No }
};
let gc = debugging_opts & session::gc != 0;
let jit = debugging_opts & session::jit != 0;
let extra_debuginfo = debugging_opts & session::extra_debug_info != 0;
let debuginfo = debugging_opts & session::debug_info != 0 ||
extra_debuginfo;
Expand Down Expand Up @@ -802,7 +796,6 @@ pub fn build_session_options(binary: @str,
extra_debuginfo: extra_debuginfo,
lint_opts: lint_opts,
save_temps: save_temps,
jit: jit,
output_type: output_type,
addl_lib_search_paths: @mut addl_lib_search_paths,
ar: ar,
Expand Down
51 changes: 22 additions & 29 deletions src/librustc/driver/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,30 +44,28 @@ pub static time_llvm_passes: uint = 1 << 3;
pub static trans_stats: uint = 1 << 4;
pub static asm_comments: uint = 1 << 5;
pub static no_verify: uint = 1 << 6;
pub static trace: uint = 1 << 7;
pub static coherence: uint = 1 << 8;
pub static borrowck_stats: uint = 1 << 9;
pub static borrowck_note_pure: uint = 1 << 10;
pub static borrowck_note_loan: uint = 1 << 11;
pub static no_landing_pads: uint = 1 << 12;
pub static debug_llvm: uint = 1 << 13;
pub static count_type_sizes: uint = 1 << 14;
pub static meta_stats: uint = 1 << 15;
pub static no_opt: uint = 1 << 16;
pub static gc: uint = 1 << 17;
pub static jit: uint = 1 << 18;
pub static debug_info: uint = 1 << 19;
pub static extra_debug_info: uint = 1 << 20;
pub static print_link_args: uint = 1 << 21;
pub static no_debug_borrows: uint = 1 << 22;
pub static lint_llvm: uint = 1 << 23;
pub static print_llvm_passes: uint = 1 << 24;
pub static no_vectorize_loops: uint = 1 << 25;
pub static no_vectorize_slp: uint = 1 << 26;
pub static no_prepopulate_passes: uint = 1 << 27;
pub static use_softfp: uint = 1 << 28;
pub static gen_crate_map: uint = 1 << 29;
pub static prefer_dynamic: uint = 1 << 30;
pub static coherence: uint = 1 << 7;
pub static borrowck_stats: uint = 1 << 8;
pub static borrowck_note_pure: uint = 1 << 9;
pub static borrowck_note_loan: uint = 1 << 10;
pub static no_landing_pads: uint = 1 << 11;
pub static debug_llvm: uint = 1 << 12;
pub static count_type_sizes: uint = 1 << 13;
pub static meta_stats: uint = 1 << 14;
pub static no_opt: uint = 1 << 15;
pub static gc: uint = 1 << 16;
pub static debug_info: uint = 1 << 17;
pub static extra_debug_info: uint = 1 << 18;
pub static print_link_args: uint = 1 << 19;
pub static no_debug_borrows: uint = 1 << 20;
pub static lint_llvm: uint = 1 << 21;
pub static print_llvm_passes: uint = 1 << 22;
pub static no_vectorize_loops: uint = 1 << 23;
pub static no_vectorize_slp: uint = 1 << 24;
pub static no_prepopulate_passes: uint = 1 << 25;
pub static use_softfp: uint = 1 << 26;
pub static gen_crate_map: uint = 1 << 27;
pub static prefer_dynamic: uint = 1 << 28;

pub fn debugging_opts_map() -> ~[(&'static str, &'static str, uint)] {
~[("verbose", "in general, enable more debug printouts", verbose),
Expand All @@ -79,7 +77,6 @@ pub fn debugging_opts_map() -> ~[(&'static str, &'static str, uint)] {
("trans-stats", "gather trans statistics", trans_stats),
("asm-comments", "generate comments into the assembly (may change behavior)", asm_comments),
("no-verify", "skip LLVM verification", no_verify),
("trace", "emit trace logs", trace),
("coherence", "perform coherence checking", coherence),
("borrowck-stats", "gather borrowck statistics", borrowck_stats),
("borrowck-note-pure", "note where purity is req'd",
Expand All @@ -95,7 +92,6 @@ pub fn debugging_opts_map() -> ~[(&'static str, &'static str, uint)] {
("no-opt", "do not optimize, even if -O is passed", no_opt),
("print-link-args", "Print the arguments passed to the linker", print_link_args),
("gc", "Garbage collect shared data (experimental)", gc),
("jit", "Execute using JIT (experimental)", jit),
("extra-debug-info", "Extra debugging info (experimental)",
extra_debug_info),
("debug-info", "Produce debug info (experimental)", debug_info),
Expand Down Expand Up @@ -146,7 +142,6 @@ pub struct options {
extra_debuginfo: bool,
lint_opts: ~[(lint::lint, lint::level)],
save_temps: bool,
jit: bool,
output_type: back::link::output_type,
addl_lib_search_paths: @mut HashSet<Path>, // This is mutable for rustpkg, which
// updates search paths based on the
Expand Down Expand Up @@ -311,7 +306,6 @@ impl Session_ {
pub fn asm_comments(&self) -> bool { self.debugging_opt(asm_comments) }
pub fn no_verify(&self) -> bool { self.debugging_opt(no_verify) }
pub fn lint_llvm(&self) -> bool { self.debugging_opt(lint_llvm) }
pub fn trace(&self) -> bool { self.debugging_opt(trace) }
pub fn coherence(&self) -> bool { self.debugging_opt(coherence) }
pub fn borrowck_stats(&self) -> bool { self.debugging_opt(borrowck_stats) }
pub fn borrowck_note_pure(&self) -> bool {
Expand Down Expand Up @@ -370,7 +364,6 @@ pub fn basic_options() -> @options {
extra_debuginfo: false,
lint_opts: ~[],
save_temps: false,
jit: false,
output_type: link::output_type_exe,
addl_lib_search_paths: @mut HashSet::new(),
ar: None,
Expand Down
4 changes: 0 additions & 4 deletions src/librustc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,10 +363,6 @@ pub fn monitor(f: proc(@diagnostic::Emitter)) {
let _finally = finally { ch: ch };

f(demitter);

// Due reasons explain in #7732, if there was a jit execution context it
// must be consumed and passed along to our parent task.
back::link::jit::consume_engine()
}) {
result::Ok(_) => { /* fallthrough */ }
result::Err(_) => {
Expand Down
12 changes: 0 additions & 12 deletions src/librustc/lib/llvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1441,18 +1441,6 @@ pub mod llvm {
call. */
pub fn LLVMRustGetLastError() -> *c_char;

/** Prepare the JIT. Returns a memory manager that can load crates. */
pub fn LLVMRustPrepareJIT(__morestack: *()) -> *();

/** Load a crate into the memory manager. */
pub fn LLVMRustLoadCrate(MM: *(), Filename: *c_char) -> bool;

/** Execute the JIT engine. */
pub fn LLVMRustBuildJIT(MM: *(),
M: ModuleRef,
EnableSegmentedStacks: bool)
-> ExecutionEngineRef;

/// Print the pass timings since static dtors aren't picking them up.
pub fn LLVMRustPrintPassTimings();

Expand Down
Loading