diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index db61042b9ff98..ccebf88ec38b6 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -27,7 +27,6 @@ use std::char; use std::hash::Streaming; use std::hash; use std::io; -use std::libc::{c_int, c_uint}; use std::os::consts::{macos, freebsd, linux, android, win32}; use std::os; use std::ptr; @@ -67,37 +66,19 @@ pub fn llvm_err(sess: Session, msg: ~str) -> ! { } } -pub fn WriteOutputFile(sess: Session, - PM: lib::llvm::PassManagerRef, M: ModuleRef, - Triple: &str, - Cpu: &str, - Feature: &str, +pub fn WriteOutputFile( + sess: Session, + Target: lib::llvm::TargetMachineRef, + PM: lib::llvm::PassManagerRef, + M: ModuleRef, Output: &str, - // FIXME: When #2334 is fixed, change - // c_uint to FileType - FileType: c_uint, - OptLevel: c_int, - EnableSegmentedStacks: bool) { + FileType: lib::llvm::FileType) { unsafe { - do Triple.with_c_str |Triple| { - do Cpu.with_c_str |Cpu| { - do Feature.with_c_str |Feature| { - do Output.with_c_str |Output| { - let result = llvm::LLVMRustWriteOutputFile( - PM, - M, - Triple, - Cpu, - Feature, - Output, - FileType, - OptLevel, - EnableSegmentedStacks); - if (!result) { - llvm_err(sess, ~"Could not write output"); - } - } - } + do Output.with_c_str |Output| { + let result = llvm::LLVMRustWriteOutputFile( + Target, PM, M, Output, FileType); + if !result { + llvm_err(sess, ~"Could not write output"); } } } @@ -231,25 +212,15 @@ pub mod write { use driver::session::Session; use driver::session; use lib::llvm::llvm; - use lib::llvm::{ModuleRef, mk_pass_manager, mk_target_data}; - use lib::llvm::{ContextRef}; + use lib::llvm::{ModuleRef, ContextRef}; use lib; - use back::passes; - use std::c_str::ToCStr; - use std::libc::{c_int, c_uint}; + use std::libc::c_uint; use std::path::Path; use std::run; use std::str; - pub fn is_object_or_assembly_or_exe(ot: output_type) -> bool { - match ot { - output_type_assembly | output_type_object | output_type_exe => true, - _ => false - } - } - pub fn run_passes(sess: Session, llcx: ContextRef, llmod: ModuleRef, @@ -258,163 +229,178 @@ pub mod write { unsafe { llvm::LLVMInitializePasses(); - let opts = sess.opts; - if sess.time_llvm_passes() { llvm::LLVMRustEnableTimePasses(); } - let td = mk_target_data(sess.targ_cfg.target_strs.data_layout); - let pm = mk_pass_manager(); - llvm::LLVMAddTargetData(td.lltd, pm.llpm); - - // Generate a pre-optimization intermediate file if -save-temps - // was specified. - if opts.save_temps { - match output_type { - output_type_bitcode => { - if opts.optimize != session::No { - let filename = output.with_filetype("no-opt.bc"); - do filename.with_c_str |buf| { - llvm::LLVMWriteBitcodeToFile(llmod, buf); - } - } - } - _ => { - let filename = output.with_filetype("bc"); - do filename.with_c_str |buf| { - llvm::LLVMWriteBitcodeToFile(llmod, buf); - } - } + // Only initialize the platforms supported by Rust here, because + // using --llvm-root will have multiple platforms that rustllvm + // doesn't actually link to and it's pointless to put target info + // into the registry that Rust can not generate machine code for. + llvm::LLVMInitializeX86TargetInfo(); + llvm::LLVMInitializeX86Target(); + llvm::LLVMInitializeX86TargetMC(); + llvm::LLVMInitializeX86AsmPrinter(); + llvm::LLVMInitializeX86AsmParser(); + + llvm::LLVMInitializeARMTargetInfo(); + llvm::LLVMInitializeARMTarget(); + llvm::LLVMInitializeARMTargetMC(); + llvm::LLVMInitializeARMAsmPrinter(); + llvm::LLVMInitializeARMAsmParser(); + + llvm::LLVMInitializeMipsTargetInfo(); + llvm::LLVMInitializeMipsTarget(); + llvm::LLVMInitializeMipsTargetMC(); + llvm::LLVMInitializeMipsAsmPrinter(); + llvm::LLVMInitializeMipsAsmParser(); + + if sess.opts.save_temps { + do output.with_filetype("no-opt.bc").with_c_str |buf| { + llvm::LLVMWriteBitcodeToFile(llmod, buf); } } - let mut mpm = passes::PassManager::new(td.lltd); - - if !sess.no_verify() { - mpm.add_pass_from_name("verify"); - } + // Copy what clan does by turning on loop vectorization at O2 and + // slp vectorization at O3 + let vectorize_loop = !sess.no_vectorize_loops() && + (sess.opts.optimize == session::Default || + sess.opts.optimize == session::Aggressive); + let vectorize_slp = !sess.no_vectorize_slp() && + sess.opts.optimize == session::Aggressive; + llvm::LLVMRustSetLLVMOptions(sess.print_llvm_passes(), + vectorize_loop, + vectorize_slp, + sess.time_llvm_passes()); + + let OptLevel = match sess.opts.optimize { + session::No => lib::llvm::CodeGenLevelNone, + session::Less => lib::llvm::CodeGenLevelLess, + session::Default => lib::llvm::CodeGenLevelDefault, + session::Aggressive => lib::llvm::CodeGenLevelAggressive, + }; - let passes = if sess.opts.custom_passes.len() > 0 { - sess.opts.custom_passes.clone() - } else { - if sess.lint_llvm() { - mpm.add_pass_from_name("lint"); + let tm = do sess.targ_cfg.target_strs.target_triple.with_c_str |T| { + do sess.opts.target_cpu.with_c_str |CPU| { + do sess.opts.target_feature.with_c_str |Features| { + llvm::LLVMRustCreateTargetMachine( + T, CPU, Features, + lib::llvm::CodeModelDefault, + lib::llvm::RelocPIC, + OptLevel, + true + ) + } } - passes::create_standard_passes(opts.optimize) }; + // Create the two optimizing pass managers. These mirror what clang + // does, and are by populated by LLVM's default PassManagerBuilder. + // Each manager has a different set of passes, but they also share + // some common passes. Each one is initialized with the analyis + // passes the target requires, and then further passes are added. + let fpm = llvm::LLVMCreateFunctionPassManagerForModule(llmod); + let mpm = llvm::LLVMCreatePassManager(); + llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod); + llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod); + + // If we're verifying or linting, add them to the function pass + // manager. + let addpass = |pass: &str| { + do pass.with_c_str |s| { llvm::LLVMRustAddPass(fpm, s) } + }; + if !sess.no_verify() { assert!(addpass("verify")); } + if sess.lint_llvm() { assert!(addpass("lint")); } + + // Create the PassManagerBuilder for LLVM. We configure it with + // reasonable defaults and prepare it to actually populate the pass + // manager. + let builder = llvm::LLVMPassManagerBuilderCreate(); + match sess.opts.optimize { + session::No => { + // Don't add lifetime intrinsics add O0 + llvm::LLVMRustAddAlwaysInlinePass(builder, false); + } + // numeric values copied from clang + session::Less => { + llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, + 225); + } + session::Default | session::Aggressive => { + llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, + 275); + } + } + llvm::LLVMPassManagerBuilderSetOptLevel(builder, OptLevel as c_uint); + llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod); + + // Use the builder to populate the function/module pass managers. + llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(builder, fpm); + llvm::LLVMPassManagerBuilderPopulateModulePassManager(builder, mpm); + llvm::LLVMPassManagerBuilderDispose(builder); + + for pass in sess.opts.custom_passes.iter() { + do pass.with_c_str |s| { + if !llvm::LLVMRustAddPass(mpm, s) { + sess.warn(fmt!("Unknown pass %s, ignoring", *pass)); + } + } + } + + // Finally, run the actual optimization passes + llvm::LLVMRustRunFunctionPassManager(fpm, llmod); + llvm::LLVMRunPassManager(mpm, llmod); - debug!("Passes: %?", passes); - passes::populate_pass_manager(sess, &mut mpm, passes); + // Deallocate managers that we're now done with + llvm::LLVMDisposePassManager(fpm); + llvm::LLVMDisposePassManager(mpm); - debug!("Running Module Optimization Pass"); - mpm.run(llmod); + if sess.opts.save_temps { + do output.with_filetype("bc").with_c_str |buf| { + llvm::LLVMWriteBitcodeToFile(llmod, buf); + } + } - if opts.jit { + 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 and return. + // 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); - if sess.time_llvm_passes() { - llvm::LLVMRustPrintPassTimings(); - } - return; - } else if is_object_or_assembly_or_exe(output_type) { - let LLVMOptNone = 0 as c_int; // -O0 - let LLVMOptLess = 1 as c_int; // -O1 - let LLVMOptDefault = 2 as c_int; // -O2, -Os - let LLVMOptAggressive = 3 as c_int; // -O3 - - let CodeGenOptLevel = match opts.optimize { - session::No => LLVMOptNone, - session::Less => LLVMOptLess, - session::Default => LLVMOptDefault, - session::Aggressive => LLVMOptAggressive - }; - - let FileType = match output_type { - output_type_object | output_type_exe => lib::llvm::ObjectFile, - _ => lib::llvm::AssemblyFile - }; - - // Write optimized bitcode if --save-temps was on. - - if opts.save_temps { - // Always output the bitcode file with --save-temps - - let filename = output.with_filetype("opt.bc"); - do filename.with_c_str |buf| { - llvm::LLVMWriteBitcodeToFile(llmod, buf) - }; - // Save the assembly file if -S is used - if output_type == output_type_assembly { - WriteOutputFile( - sess, - pm.llpm, - llmod, - sess.targ_cfg.target_strs.target_triple, - opts.target_cpu, - opts.target_feature, - output.to_str(), - lib::llvm::AssemblyFile as c_uint, - CodeGenOptLevel, - true); + match output_type { + output_type_none => {} + output_type_bitcode => { + do output.with_c_str |buf| { + llvm::LLVMWriteBitcodeToFile(llmod, buf); + } } - - // Save the object file for -c or --save-temps alone - // This .o is needed when an exe is built - if output_type == output_type_object || - output_type == output_type_exe { - WriteOutputFile( - sess, - pm.llpm, - llmod, - sess.targ_cfg.target_strs.target_triple, - opts.target_cpu, - opts.target_feature, - output.to_str(), - lib::llvm::ObjectFile as c_uint, - CodeGenOptLevel, - true); + output_type_llvm_assembly => { + do output.with_c_str |output| { + llvm::LLVMRustPrintModule(cpm, llmod, output) + } + } + output_type_assembly => { + WriteOutputFile(sess, tm, cpm, llmod, output.to_str(), + lib::llvm::AssemblyFile); + } + output_type_exe | output_type_object => { + WriteOutputFile(sess, tm, cpm, llmod, output.to_str(), + lib::llvm::ObjectFile); } - } else { - // If we aren't saving temps then just output the file - // type corresponding to the '-c' or '-S' flag used - WriteOutputFile( - sess, - pm.llpm, - llmod, - sess.targ_cfg.target_strs.target_triple, - opts.target_cpu, - opts.target_feature, - output.to_str(), - FileType as c_uint, - CodeGenOptLevel, - true); } - // Clean up and return - llvm::LLVMDisposeModule(llmod); - llvm::LLVMContextDispose(llcx); - if sess.time_llvm_passes() { - llvm::LLVMRustPrintPassTimings(); - } - return; + llvm::LLVMDisposePassManager(cpm); } - if output_type == output_type_llvm_assembly { - // Given options "-S --emit-llvm": output LLVM assembly - do output.with_c_str |buf_o| { - llvm::LLVMRustAddPrintModulePass(pm.llpm, llmod, buf_o); - } - } else { - // If only a bitcode file is asked for by using the - // '--emit-llvm' flag, then output it here - do output.with_c_str |buf| { - llvm::LLVMWriteBitcodeToFile(llmod, buf); - } + 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(); } } } diff --git a/src/librustc/back/passes.rs b/src/librustc/back/passes.rs deleted file mode 100644 index bb5ddc1ae7715..0000000000000 --- a/src/librustc/back/passes.rs +++ /dev/null @@ -1,349 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::c_str::ToCStr; -use std::io; - -use driver::session::{OptLevel, No, Less, Aggressive}; -use driver::session::{Session}; -use lib::llvm::{PassRef, ModuleRef,PassManagerRef,TargetDataRef}; -use lib::llvm::llvm; -use lib; - -pub struct PassManager { - priv llpm: PassManagerRef -} - -impl Drop for PassManager { - fn drop(&self) { - unsafe { - llvm::LLVMDisposePassManager(self.llpm); - } - } -} - -impl PassManager { - pub fn new(td: TargetDataRef) -> PassManager { - unsafe { - let pm = PassManager { - llpm: llvm::LLVMCreatePassManager() - }; - llvm::LLVMAddTargetData(td, pm.llpm); - - return pm; - } - } - - pub fn add_pass(&mut self, pass:PassRef) { - unsafe { - llvm::LLVMAddPass(self.llpm, pass); - } - } - - pub fn add_pass_from_name(&mut self, name:&str) { - let pass = create_pass(name).unwrap(); - self.add_pass(pass); - } - - pub fn run(&self, md:ModuleRef) -> bool { - unsafe { - llvm::LLVMRunPassManager(self.llpm, md) == lib::llvm::True - } - } -} - -pub fn create_standard_passes(level: OptLevel) -> ~[~str] { - let mut passes = ~[]; - - // mostly identical to clang 3.3, all differences are documented with comments - - if level != No { - passes.push(~"targetlibinfo"); - passes.push(~"no-aa"); - // "tbaa" omitted, we don't emit clang-style type-based alias analysis information - passes.push(~"basicaa"); - passes.push(~"globalopt"); - passes.push(~"ipsccp"); - passes.push(~"deadargelim"); - passes.push(~"instcombine"); - passes.push(~"simplifycfg"); - } - - passes.push(~"basiccg"); - - if level != No { - passes.push(~"prune-eh"); - } - - passes.push(~"inline-cost"); - - if level == No || level == Less { - passes.push(~"always-inline"); - } else { - passes.push(~"inline"); - } - - if level != No { - passes.push(~"functionattrs"); - if level == Aggressive { - passes.push(~"argpromotion"); - } - passes.push(~"sroa"); - passes.push(~"domtree"); - passes.push(~"early-cse"); - passes.push(~"lazy-value-info"); - passes.push(~"jump-threading"); - passes.push(~"correlated-propagation"); - passes.push(~"simplifycfg"); - passes.push(~"instcombine"); - passes.push(~"tailcallelim"); - passes.push(~"simplifycfg"); - passes.push(~"reassociate"); - passes.push(~"domtree"); - passes.push(~"loops"); - passes.push(~"loop-simplify"); - passes.push(~"lcssa"); - passes.push(~"loop-rotate"); - passes.push(~"licm"); - passes.push(~"lcssa"); - passes.push(~"loop-unswitch"); - passes.push(~"instcombine"); - passes.push(~"scalar-evolution"); - passes.push(~"loop-simplify"); - passes.push(~"lcssa"); - passes.push(~"indvars"); - passes.push(~"loop-idiom"); - passes.push(~"loop-deletion"); - if level == Aggressive { - passes.push(~"loop-simplify"); - passes.push(~"lcssa"); - passes.push(~"loop-vectorize"); - passes.push(~"loop-simplify"); - passes.push(~"lcssa"); - passes.push(~"scalar-evolution"); - passes.push(~"loop-simplify"); - passes.push(~"lcssa"); - } - if level != Less { - passes.push(~"loop-unroll"); - passes.push(~"memdep"); - passes.push(~"gvn"); - } - passes.push(~"memdep"); - passes.push(~"memcpyopt"); - passes.push(~"sccp"); - passes.push(~"instcombine"); - passes.push(~"lazy-value-info"); - passes.push(~"jump-threading"); - passes.push(~"correlated-propagation"); - passes.push(~"domtree"); - passes.push(~"memdep"); - passes.push(~"dse"); - passes.push(~"adce"); - passes.push(~"simplifycfg"); - passes.push(~"instcombine"); - // clang does `strip-dead-prototypes` here, since it does not emit them - } - - // rustc emits dead prototypes, so always ask LLVM to strip them - passes.push(~"strip-dead-prototypes"); - - if level != Less { - passes.push(~"globaldce"); - passes.push(~"constmerge"); - } - - passes -} - -pub fn populate_pass_manager(sess: Session, pm: &mut PassManager, pass_list:&[~str]) { - for nm in pass_list.iter() { - match create_pass(*nm) { - Some(p) => pm.add_pass(p), - None => sess.warn(fmt!("Unknown pass %s", *nm)) - } - } -} - -pub fn create_pass(name:&str) -> Option { - do name.with_c_str |s| { - unsafe { - let p = llvm::LLVMCreatePass(s); - if p.is_null() { - None - } else { - Some(p) - } - } - } -} - -pub fn list_passes() { - io::println("\nAvailable Passes:"); - - io::println("\nAnalysis Passes:"); - for &(name, desc) in analysis_passes.iter() { - printfln!(" %-30s -- %s", name, desc); - } - io::println("\nTransformation Passes:"); - for &(name, desc) in transform_passes.iter() { - printfln!(" %-30s -- %s", name, desc); - } - io::println("\nUtility Passes:"); - for &(name, desc) in utility_passes.iter() { - printfln!(" %-30s -- %s", name, desc); - } -} - -/** Analysis Passes */ -pub static analysis_passes : &'static [(&'static str, &'static str)] = &'static [ - ("aa-eval", "Exhausive Alias Analysis Precision Evaluator"), - ("asan", "AddressSanitizer"), - ("basicaa", "Basic Alias Analysis"), - ("basiccg", "Basic CallGraph Construction"), - ("block-freq", "Block Frequency Analysis"), - ("cost-model", "Cost Model Analysis"), - ("count-aa", "Count Alias Analysis Query Responses"), - ("da", "Dependence Analysis"), - ("debug-aa", "AA Use Debugger"), - ("domfrontier", "Dominance Frontier Construction"), - ("domtree", "Dominator Tree Construction"), - ("globalsmodref-aa", "Simple mod/ref analysis for globals"), - ("instcount", "Count the various types of Instructions"), - ("intervals", "Interval Partition Construction"), - ("iv-users", "Induction Variable Users"), - ("lazy-value-info", "Lazy Value Information Analysis"), - ("libcall-aa", "LibCall Alias Analysis"), - ("lint", "Statically lint-check LLVM IR"), - ("loops", "Natural Loop Information"), - ("memdep", "Memory Dependence Analysis"), - ("module-debuginfo", "Decodes module-level debug info"), - ("profile-estimator", "Estimate profiling information"), - ("profile-loader", "Load profile information from llvmprof.out"), - ("profile-verifier", "Verify profiling information"), - ("regions", "Detect single entry single exit regions"), - ("scalar-evolution", "Scalar Evolution Analysis"), - ("scev-aa", "Scalar Evolution-based Alias Analysis"), - ("tbaa", "Type-Based Alias Analysis"), - ("tsan", "ThreadSanitizer"), -]; - -/** Transformation Passes */ -pub static transform_passes : &'static [(&'static str, &'static str)] = &'static [ - ("adce", "Aggressive Dead Code Elimination"), - ("always-inline", "Inliner for #[inline] functions"), - ("argpromotion", "Promote 'by reference' arguments to scalars"), - ("bb-vectorize", "Basic-Block Vectorization"), - ("block-placement", "Profile Guided Basic Block Placement"), - ("bounds-checking", "Run-time bounds checking"), - ("break-crit-edges", "Break critical edges in CFG"), - ("codegenprepare", "Optimize for code generation"), - ("constmerge", "Merge Duplicate Global Constants"), - ("constprop", "Simple constant propagation"), - ("correlated-propagation", "Value Propagation"), - ("da", "Data Layout"), - ("dce", "Dead Code Elimination"), - ("deadargelim", "Dead Argument Elimination"), - ("die", "Dead Instruction Elimination"), - ("dse", "Dead Store Elimination"), - ("early-cse", "Early CSE"), - ("functionattrs", "Deduce function attributes"), - ("globaldce", "Dead Global Elimination"), - ("globalopt", "Global Variable Optimizer"), - ("gvn", "Global Value Numbering"), - ("indvars", "Canonicalize Induction Variables"), - ("inline", "Function Integration/Inlining"), - ("insert-edge-profiling", "Insert instrumentation for edge profiling"), - ("insert-gcov-profiling", "Insert instrumentation for GCOV profiling"), - ("insert-optimal-edge-profiling", "Insert optimal instrumentation for edge profiling"), - ("instcombine", "Combine redundant instructions"), - ("instsimplify", "Remove redundant instructions"), - ("ipconstprop", "Interprocedural constant propagation"), - ("ipsccp", "Interprocedural Sparse Conditional Constant Propagation"), - ("jump-threading", "Jump Threading"), - ("lcssa", "Loop-Closed SSA Form Pass"), - ("licm", "Loop Invariant Code Motion"), - ("loop-deletion", "Delete dead loops"), - ("loop-extract", "Extract loops into new functions"), - ("loop-extract-single", "Extract at most one loop into a new function"), - ("loop-idiom", "Recognise loop idioms"), - ("loop-instsimplify", "Simplify instructions in loops"), - ("loop-reduce", "Loop Strength Reduction"), - ("loop-rotate", "Rotate Loops"), - ("loop-simplify", "Canonicalize natural loops"), - ("loop-unroll", "Unroll loops"), - ("loop-unswitch", "Unswitch loops"), - ("loop-vectorize", "Loop Vectorization"), - ("lower-expect", "Lower 'expect' Intrinsics"), - ("mem2reg", "Promote Memory to Register"), - ("memcpyopt", "MemCpy Optimization"), - ("mergefunc", "Merge Functions"), - ("mergereturn", "Unify function exit nodes"), - ("partial-inliner", "Partial Inliner"), - ("prune-eh", "Remove unused exception handling info"), - ("reassociate", "Reassociate expressions"), - ("reg2mem", "Demote all values to stack slots"), - ("scalarrepl", "Scalar Replacement of Aggregates (DT)"), - ("scalarrepl-ssa", "Scalar Replacement of Aggregates (SSAUp)"), - ("sccp", "Sparse Conditional Constant Propagation"), - ("simplifycfg", "Simplify the CFG"), - ("sink", "Code sinking"), - ("strip", "Strip all symbols from a module"), - ("strip-dead-debug-info", "Strip debug info for unused symbols"), - ("strip-dead-prototypes", "Strip Unused Function Prototypes"), - ("strip-debug-declare", "Strip all llvm.dbg.declare intrinsics"), - ("strip-nondebug", "Strip all symbols, except dbg symbols, from a module"), - ("sroa", "Scalar Replacement of Aggregates"), - ("tailcallelim", "Tail Call Elimination"), -]; - -/** Utility Passes */ -static utility_passes : &'static [(&'static str, &'static str)] = &'static [ - ("instnamer", "Assign names to anonymous instructions"), - ("verify", "Module Verifier"), -]; - -#[test] -fn passes_exist() { - let mut failed = ~[]; - unsafe { llvm::LLVMInitializePasses(); } - for &(name,_) in analysis_passes.iter() { - let pass = create_pass(name); - if !pass.is_some() { - failed.push(name); - } else { - unsafe { llvm::LLVMDestroyPass(pass.unwrap()) } - } - } - for &(name,_) in transform_passes.iter() { - let pass = create_pass(name); - if !pass.is_some() { - failed.push(name); - } else { - unsafe { llvm::LLVMDestroyPass(pass.unwrap()) } - } - } - for &(name,_) in utility_passes.iter() { - let pass = create_pass(name); - if !pass.is_some() { - failed.push(name); - } else { - unsafe { llvm::LLVMDestroyPass(pass.unwrap()) } - } - } - - if failed.len() > 0 { - io::println("Some passes don't exist:"); - for &n in failed.iter() { - printfln!(" %s", n); - } - fail!(); - } -} diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index e0c5a729b3f88..003840b85a167 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -848,8 +848,9 @@ pub fn optgroups() -> ~[getopts::groups::OptGroup] { optopt("", "opt-level", "Optimize with possible levels 0-3", "LEVEL"), optopt("", "passes", "Comma or space separated list of pass names to use. \ - Overrides the default passes for optimization levels,\n\ - a value of \"list\" will list the available passes.", "NAMES"), + Appends to the default list of passes to run for the \ + specified current optimization level. A value of \ + \"list\" will list all of the available passes", "NAMES"), optopt( "", "out-dir", "Write output to compiler-chosen filename in ", "DIR"), diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index 50b29ff16be1a..912fc606f0a34 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -76,6 +76,9 @@ pub static print_link_args: uint = 1 << 23; pub static no_debug_borrows: uint = 1 << 24; pub static lint_llvm: uint = 1 << 25; pub static once_fns: uint = 1 << 26; +pub static print_llvm_passes: uint = 1 << 27; +pub static no_vectorize_loops: uint = 1 << 28; +pub static no_vectorize_slp: uint = 1 << 29; pub fn debugging_opts_map() -> ~[(~str, ~str, uint)] { ~[(~"verbose", ~"in general, enable more debug printouts", verbose), @@ -120,6 +123,15 @@ pub fn debugging_opts_map() -> ~[(~str, ~str, uint)] { (~"once-fns", ~"Allow 'once fn' closures to deinitialize captured variables", once_fns), + (~"print-llvm-passes", + ~"Prints the llvm optimization passes being run", + print_llvm_passes), + (~"no-vectorize-loops", + ~"Don't run the loop vectorization optimization passes", + no_vectorize_loops), + (~"no-vectorize-slp", + ~"Don't run LLVM's SLP vectorization passes", + no_vectorize_slp), ] } @@ -305,6 +317,15 @@ impl Session_ { self.opts.optimize == No && !self.debugging_opt(no_debug_borrows) } pub fn once_fns(@self) -> bool { self.debugging_opt(once_fns) } + pub fn print_llvm_passes(@self) -> bool { + self.debugging_opt(print_llvm_passes) + } + pub fn no_vectorize_loops(@self) -> bool { + self.debugging_opt(no_vectorize_loops) + } + pub fn no_vectorize_slp(@self) -> bool { + self.debugging_opt(no_vectorize_slp) + } // pointless function, now... pub fn str_of(@self, id: ast::ident) -> @str { diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index 60f8a1773fc84..220b082fab1cf 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -170,7 +170,6 @@ pub enum AtomicOrdering { SequentiallyConsistent = 7 } -// FIXME: Not used right now, but will be once #2334 is fixed // Consts for the LLVMCodeGenFileType type (in include/llvm/c/TargetMachine.h) pub enum FileType { AssemblyFile = 0, @@ -192,6 +191,29 @@ pub enum AsmDialect { AD_Intel = 1 } +pub enum CodeGenOptLevel { + CodeGenLevelNone = 0, + CodeGenLevelLess = 1, + CodeGenLevelDefault = 2, + CodeGenLevelAggressive = 3, +} + +pub enum RelocMode { + RelocDefault = 0, + RelocStatic = 1, + RelocPIC = 2, + RelocDynamicNoPic = 3, +} + +pub enum CodeGenModel { + CodeModelDefault = 0, + CodeModelJITDefault = 1, + CodeModelSmall = 2, + CodeModelKernel = 3, + CodeModelMedium = 4, + CodeModelLarge = 5, +} + // Opaque pointer types pub enum Module_opaque {} pub type ModuleRef = *Module_opaque; @@ -223,6 +245,8 @@ pub enum SectionIterator_opaque {} pub type SectionIteratorRef = *SectionIterator_opaque; pub enum Pass_opaque {} pub type PassRef = *Pass_opaque; +pub enum TargetMachine_opaque {} +pub type TargetMachineRef = *TargetMachine_opaque; pub mod debuginfo { use super::{ValueRef}; @@ -266,7 +290,8 @@ pub mod llvm { use super::{Bool, BuilderRef, ContextRef, MemoryBufferRef, ModuleRef}; use super::{ObjectFileRef, Opcode, PassManagerRef, PassManagerBuilderRef}; use super::{SectionIteratorRef, TargetDataRef, TypeKind, TypeRef, UseRef}; - use super::{ValueRef, PassRef}; + use super::{ValueRef, TargetMachineRef, FileType}; + use super::{CodeGenModel, RelocMode, CodeGenOptLevel}; use super::debuginfo::*; use std::libc::{c_char, c_int, c_longlong, c_ushort, c_uint, c_ulonglong}; @@ -1614,6 +1639,7 @@ pub mod llvm { /** Creates a pass manager. */ #[fast_ffi] pub fn LLVMCreatePassManager() -> PassManagerRef; + /** Creates a function-by-function pass manager */ #[fast_ffi] pub fn LLVMCreateFunctionPassManagerForModule(M: ModuleRef) @@ -1643,15 +1669,6 @@ pub mod llvm { #[fast_ffi] pub fn LLVMInitializePasses(); - #[fast_ffi] - pub fn LLVMAddPass(PM: PassManagerRef, P: PassRef); - - #[fast_ffi] - pub fn LLVMCreatePass(PassName: *c_char) -> PassRef; - - #[fast_ffi] - pub fn LLVMDestroyPass(P: PassRef); - /** Adds a verification pass. */ #[fast_ffi] pub fn LLVMAddVerifierPass(PM: PassManagerRef); @@ -1808,20 +1825,6 @@ pub mod llvm { pub fn LLVMRustCreateMemoryBufferWithContentsOfFile(Path: *c_char) -> MemoryBufferRef; - #[fast_ffi] - pub fn LLVMRustWriteOutputFile(PM: PassManagerRef, - M: ModuleRef, - Triple: *c_char, - Cpu: *c_char, - Feature: *c_char, - Output: *c_char, - // FIXME: When #2334 is fixed, - // change c_uint to FileType - FileType: c_uint, - OptLevel: c_int, - EnableSegmentedStacks: bool) - -> bool; - /** Returns a string describing the last error caused by an LLVMRust* call. */ #[fast_ffi] @@ -1842,24 +1845,6 @@ pub mod llvm { EnableSegmentedStacks: bool) -> ExecutionEngineRef; - /** Parses the bitcode in the given memory buffer. */ - #[fast_ffi] - pub fn LLVMRustParseBitcode(MemBuf: MemoryBufferRef) -> ModuleRef; - - /** Parses LLVM asm in the given file */ - #[fast_ffi] - pub fn LLVMRustParseAssemblyFile(Filename: *c_char, C: ContextRef) - -> ModuleRef; - - #[fast_ffi] - pub fn LLVMRustAddPrintModulePass(PM: PassManagerRef, - M: ModuleRef, - Output: *c_char); - - /** Turn on LLVM pass-timing. */ - #[fast_ffi] - pub fn LLVMRustEnableTimePasses(); - /// Print the pass timings since static dtors aren't picking them up. #[fast_ffi] pub fn LLVMRustPrintPassTimings(); @@ -2097,6 +2082,55 @@ pub mod llvm { LineNo: c_uint, ColumnNo: c_uint) -> ValueRef; + + pub fn LLVMInitializeX86TargetInfo(); + pub fn LLVMInitializeX86Target(); + pub fn LLVMInitializeX86TargetMC(); + pub fn LLVMInitializeX86AsmPrinter(); + pub fn LLVMInitializeX86AsmParser(); + pub fn LLVMInitializeARMTargetInfo(); + pub fn LLVMInitializeARMTarget(); + pub fn LLVMInitializeARMTargetMC(); + pub fn LLVMInitializeARMAsmPrinter(); + pub fn LLVMInitializeARMAsmParser(); + pub fn LLVMInitializeMipsTargetInfo(); + pub fn LLVMInitializeMipsTarget(); + pub fn LLVMInitializeMipsTargetMC(); + pub fn LLVMInitializeMipsAsmPrinter(); + pub fn LLVMInitializeMipsAsmParser(); + + pub fn LLVMRustAddPass(PM: PassManagerRef, Pass: *c_char) -> bool; + pub fn LLVMRustCreateTargetMachine(Triple: *c_char, + CPU: *c_char, + Features: *c_char, + Model: CodeGenModel, + Reloc: RelocMode, + Level: CodeGenOptLevel, + EnableSegstk: bool) -> TargetMachineRef; + pub fn LLVMRustDisposeTargetMachine(T: TargetMachineRef); + pub fn LLVMRustAddAnalysisPasses(T: TargetMachineRef, + PM: PassManagerRef, + M: ModuleRef); + pub fn LLVMRustAddBuilderLibraryInfo(PMB: PassManagerBuilderRef, + M: ModuleRef); + pub fn LLVMRustAddLibraryInfo(PM: PassManagerRef, M: ModuleRef); + pub fn LLVMRustRunFunctionPassManager(PM: PassManagerRef, M: ModuleRef); + pub fn LLVMRustWriteOutputFile(T: TargetMachineRef, + PM: PassManagerRef, + M: ModuleRef, + Output: *c_char, + FileType: FileType) -> bool; + pub fn LLVMRustPrintModule(PM: PassManagerRef, + M: ModuleRef, + Output: *c_char); + pub fn LLVMRustSetLLVMOptions(PrintPasses: bool, + VectorizeLoops: bool, + VectorizeSLP: bool, + TimePasses: bool); + pub fn LLVMRustPrintPasses(); + pub fn LLVMRustSetNormalizedTarget(M: ModuleRef, triple: *c_char); + pub fn LLVMRustAddAlwaysInlinePass(P: PassManagerBuilderRef, + AddLifetimes: bool); } } @@ -2244,7 +2278,6 @@ impl TypeNames { } } - /* Memory-managed interface to target data. */ pub struct target_data_res { diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs index 1318ef2c8958d..9f99a0c92e534 100644 --- a/src/librustc/middle/trans/context.rs +++ b/src/librustc/middle/trans/context.rs @@ -137,7 +137,7 @@ impl CrateContext { llvm::LLVMSetDataLayout(llmod, buf) }; do targ_triple.with_c_str |buf| { - llvm::LLVMSetTarget(llmod, buf) + llvm::LLVMRustSetNormalizedTarget(llmod, buf) }; let targ_cfg = sess.targ_cfg; diff --git a/src/librustc/rustc.rs b/src/librustc/rustc.rs index 33407c91bcc23..06b3f6aae2710 100644 --- a/src/librustc/rustc.rs +++ b/src/librustc/rustc.rs @@ -92,7 +92,6 @@ pub mod back { pub mod x86_64; pub mod rpath; pub mod target_strs; - pub mod passes; } pub mod metadata; @@ -232,7 +231,7 @@ pub fn run_compiler(args: &[~str], demitter: diagnostic::Emitter) { } if getopts::opt_maybe_str(matches, "passes") == Some(~"list") { - back::passes::list_passes(); + unsafe { lib::llvm::llvm::LLVMRustPrintPasses(); } return; } diff --git a/src/libstd/unstable/raw.rs b/src/libstd/unstable/raw.rs index bdf84604fb37f..a538566fa1898 100644 --- a/src/libstd/unstable/raw.rs +++ b/src/libstd/unstable/raw.rs @@ -57,6 +57,7 @@ impl<'self> Repr> for &'self str {} impl Repr<*Box> for @T {} impl Repr<*Box>> for @[T] {} impl Repr<*String> for ~str {} +impl Repr<*Box> for @str {} // sure would be nice to have this // impl Repr<*Vec> for ~[T] {} diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 32b6df4e1dd59..56ba56cf89377 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -8,29 +8,29 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#include + #include "rustllvm.h" -using namespace llvm; +#include "llvm/Support/CBindingWrapping.h" +#include "llvm/Target/TargetLibraryInfo.h" +#include "llvm/Transforms/IPO/PassManagerBuilder.h" -// Pass conversion fns -typedef struct LLVMOpaquePass *LLVMPassRef; +#include "llvm-c/Transforms/PassManagerBuilder.h" -inline Pass *unwrap(LLVMPassRef P) { - return reinterpret_cast(P); -} +using namespace llvm; -inline LLVMPassRef wrap(const Pass *P) { - return reinterpret_cast(const_cast(P)); -} +extern cl::opt EnableARMEHABI; -template -inline T *unwrap(LLVMPassRef P) { - T *Q = (T*)unwrap(P); - assert(Q && "Invalid cast!"); - return Q; -} +typedef struct LLVMOpaquePass *LLVMPassRef; +typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef; + +DEFINE_STDCXX_CONVERSION_FUNCTIONS(Pass, LLVMPassRef) +DEFINE_STDCXX_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef) +DEFINE_STDCXX_CONVERSION_FUNCTIONS(PassManagerBuilder, LLVMPassManagerBuilderRef) -extern "C" void LLVMInitializePasses() { +extern "C" void +LLVMInitializePasses() { PassRegistry &Registry = *PassRegistry::getPassRegistry(); initializeCore(Registry); initializeCodeGen(Registry); @@ -45,26 +45,185 @@ extern "C" void LLVMInitializePasses() { initializeTarget(Registry); } -extern "C" void LLVMAddPass(LLVMPassManagerRef PM, LLVMPassRef P) { - PassManagerBase * pm = unwrap(PM); - Pass * p = unwrap(P); - - pm->add(p); -} +extern "C" bool +LLVMRustAddPass(LLVMPassManagerRef PM, const char *PassName) { + PassManagerBase *pm = unwrap(PM); -extern "C" LLVMPassRef LLVMCreatePass(const char * PassName) { StringRef SR(PassName); - PassRegistry * PR = PassRegistry::getPassRegistry(); + PassRegistry *PR = PassRegistry::getPassRegistry(); - const PassInfo * PI = PR->getPassInfo(SR); + const PassInfo *PI = PR->getPassInfo(SR); if (PI) { - return wrap(PI->createPass()); - } else { - return (LLVMPassRef)0; + pm->add(PI->createPass()); + return true; + } + return false; +} + +extern "C" LLVMTargetMachineRef +LLVMRustCreateTargetMachine(const char *triple, + const char *cpu, + const char *feature, + CodeModel::Model CM, + Reloc::Model RM, + CodeGenOpt::Level OptLevel, + bool EnableSegmentedStacks) { + std::string Error; + Triple Trip(Triple::normalize(triple)); + const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Trip.getTriple(), + Error); + if (TheTarget == NULL) { + LLVMRustError = Error.c_str(); + return NULL; + } + + TargetOptions Options; + Options.EnableSegmentedStacks = EnableSegmentedStacks; + Options.FixedStackSegmentSize = 2 * 1024 * 1024; // XXX: This is too big. + Options.FloatABIType = + (Trip.getEnvironment() == Triple::GNUEABIHF) ? FloatABI::Hard : + FloatABI::Default; + + TargetMachine *TM = TheTarget->createTargetMachine(Trip.getTriple(), + cpu, + feature, + Options, + RM, + CM, + OptLevel); + return wrap(TM); +} + +extern "C" void +LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) { + delete unwrap(TM); +} + +// Unfortunately, LLVM doesn't expose a C API to add the corresponding analysis +// passes for a target to a pass manager. We export that functionality through +// this function. +extern "C" void +LLVMRustAddAnalysisPasses(LLVMTargetMachineRef TM, + LLVMPassManagerRef PMR, + LLVMModuleRef M) { + PassManagerBase *PM = unwrap(PMR); + PM->add(new DataLayout(unwrap(M))); + unwrap(TM)->addAnalysisPasses(*PM); +} + +// Unfortunately, the LLVM C API doesn't provide a way to set the `LibraryInfo` +// field of a PassManagerBuilder, we expose our own method of doing so. +extern "C" void +LLVMRustAddBuilderLibraryInfo(LLVMPassManagerBuilderRef PMB, LLVMModuleRef M) { + Triple TargetTriple(unwrap(M)->getTargetTriple()); + unwrap(PMB)->LibraryInfo = new TargetLibraryInfo(TargetTriple); +} + +// Unfortunately, the LLVM C API doesn't provide a way to create the +// TargetLibraryInfo pass, so we use this method to do so. +extern "C" void +LLVMRustAddLibraryInfo(LLVMPassManagerRef PMB, LLVMModuleRef M) { + Triple TargetTriple(unwrap(M)->getTargetTriple()); + unwrap(PMB)->add(new TargetLibraryInfo(TargetTriple)); +} + +// Unfortunately, the LLVM C API doesn't provide an easy way of iterating over +// all the functions in a module, so we do that manually here. You'll find +// similar code in clang's BackendUtil.cpp file. +extern "C" void +LLVMRustRunFunctionPassManager(LLVMPassManagerRef PM, LLVMModuleRef M) { + FunctionPassManager *P = unwrap(PM); + P->doInitialization(); + for (Module::iterator I = unwrap(M)->begin(), + E = unwrap(M)->end(); I != E; ++I) + if (!I->isDeclaration()) + P->run(*I); + P->doFinalization(); +} + +extern "C" void +LLVMRustSetLLVMOptions(bool PrintPasses, + bool VectorizeLoops, + bool VectorizeSLP, + bool TimePasses) { + // Initializing the command-line options more than once is not allowed. So, + // check if they've already been initialized. (This could happen if we're + // being called from rustpkg, for example). If the arguments change, then + // that's just kinda unfortunate. + static bool initialized = false; + if (initialized) return; + + int argc = 3; + const char *argv[20] = {"rustc", + "-arm-enable-ehabi", + "-arm-enable-ehabi-descriptors"}; + if (PrintPasses) { + argv[argc++] = "-debug-pass"; + argv[argc++] = "Structure"; + } + if (VectorizeLoops) { + argv[argc++] = "-vectorize-loops"; + } + if (VectorizeSLP) { + argv[argc++] = "-vectorize-slp"; } + if (TimePasses) { + argv[argc++] = "-time-passes"; + } + cl::ParseCommandLineOptions(argc, argv); + initialized = true; +} + +extern "C" bool +LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, + LLVMPassManagerRef PMR, + LLVMModuleRef M, + const char *path, + TargetMachine::CodeGenFileType FileType) { + PassManager *PM = unwrap(PMR); + + std::string ErrorInfo; + raw_fd_ostream OS(path, ErrorInfo, sys::fs::F_Binary); + if (ErrorInfo != "") { + LLVMRustError = ErrorInfo.c_str(); + return false; + } + formatted_raw_ostream FOS(OS); + + unwrap(Target)->addPassesToEmitFile(*PM, FOS, FileType, false); + PM->run(*unwrap(M)); + return true; +} + +extern "C" void +LLVMRustPrintModule(LLVMPassManagerRef PMR, + LLVMModuleRef M, + const char* path) { + PassManager *PM = unwrap(PMR); + std::string ErrorInfo; + raw_fd_ostream OS(path, ErrorInfo, sys::fs::F_Binary); + formatted_raw_ostream FOS(OS); + PM->add(createPrintModulePass(&FOS)); + PM->run(*unwrap(M)); +} + +extern "C" void +LLVMRustPrintPasses() { + LLVMInitializePasses(); + struct MyListener : PassRegistrationListener { + void passEnumerate(const PassInfo *info) { + if (info->getPassArgument() && *info->getPassArgument()) { + printf("%15s - %s\n", info->getPassArgument(), + info->getPassName()); + } + } + } listener; + + PassRegistry *PR = PassRegistry::getPassRegistry(); + PR->enumerateWith(&listener); } -extern "C" void LLVMDestroyPass(LLVMPassRef PassRef) { - Pass *p = unwrap(PassRef); - delete p; +extern "C" void +LLVMRustAddAlwaysInlinePass(LLVMPassManagerBuilderRef PMB, bool AddLifetimes) { + unwrap(PMB)->Inliner = createAlwaysInlinerPass(AddLifetimes); } diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 5b8c6bc883fb5..40ee486ec2d9c 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -20,9 +20,7 @@ using namespace llvm; using namespace llvm::sys; -static const char *LLVMRustError; - -extern cl::opt EnableARMEHABI; +const char *LLVMRustError; extern "C" LLVMMemoryBufferRef LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) { @@ -36,62 +34,6 @@ extern "C" const char *LLVMRustGetLastError(void) { return LLVMRustError; } -extern "C" void LLVMAddBasicAliasAnalysisPass(LLVMPassManagerRef PM); - -extern "C" void LLVMRustAddPrintModulePass(LLVMPassManagerRef PMR, - LLVMModuleRef M, - const char* path) { - PassManager *PM = unwrap(PMR); - std::string ErrorInfo; - raw_fd_ostream OS(path, ErrorInfo, sys::fs::F_Binary); - formatted_raw_ostream FOS(OS); - PM->add(createPrintModulePass(&FOS)); - PM->run(*unwrap(M)); -} - -void LLVMInitializeX86TargetInfo(); -void LLVMInitializeX86Target(); -void LLVMInitializeX86TargetMC(); -void LLVMInitializeX86AsmPrinter(); -void LLVMInitializeX86AsmParser(); - - -void LLVMInitializeARMTargetInfo(); -void LLVMInitializeARMTarget(); -void LLVMInitializeARMTargetMC(); -void LLVMInitializeARMAsmPrinter(); -void LLVMInitializeARMAsmParser(); - -void LLVMInitializeMipsTargetInfo(); -void LLVMInitializeMipsTarget(); -void LLVMInitializeMipsTargetMC(); -void LLVMInitializeMipsAsmPrinter(); -void LLVMInitializeMipsAsmParser(); -// Only initialize the platforms supported by Rust here, -// because using --llvm-root will have multiple platforms -// that rustllvm doesn't actually link to and it's pointless to put target info -// into the registry that Rust can not generate machine code for. - -void LLVMRustInitializeTargets() { - LLVMInitializeX86TargetInfo(); - LLVMInitializeX86Target(); - LLVMInitializeX86TargetMC(); - LLVMInitializeX86AsmPrinter(); - LLVMInitializeX86AsmParser(); - - LLVMInitializeARMTargetInfo(); - LLVMInitializeARMTarget(); - LLVMInitializeARMTargetMC(); - LLVMInitializeARMAsmPrinter(); - LLVMInitializeARMAsmParser(); - - LLVMInitializeMipsTargetInfo(); - LLVMInitializeMipsTarget(); - LLVMInitializeMipsTargetMC(); - LLVMInitializeMipsAsmPrinter(); - LLVMInitializeMipsAsmParser(); -} - // Custom memory manager for MCJITting. It needs special features // that the generic JIT memory manager doesn't entail. Based on // code from LLI, change where needed for Rust. @@ -367,85 +309,9 @@ LLVMRustBuildJIT(void* mem, return wrap(EE); } -extern "C" bool -LLVMRustWriteOutputFile(LLVMPassManagerRef PMR, - LLVMModuleRef M, - const char *triple, - const char *cpu, - const char *feature, - const char *path, - TargetMachine::CodeGenFileType FileType, - CodeGenOpt::Level OptLevel, - bool EnableSegmentedStacks) { - - LLVMRustInitializeTargets(); - - // Initializing the command-line options more than once is not - // allowed. So, check if they've already been initialized. - // (This could happen if we're being called from rustpkg, for - // example.) - if (!EnableARMEHABI) { - int argc = 3; - const char* argv[] = {"rustc", "-arm-enable-ehabi", - "-arm-enable-ehabi-descriptors"}; - cl::ParseCommandLineOptions(argc, argv); - } - - Triple Trip(Triple::normalize(triple)); - - TargetOptions Options; - Options.EnableSegmentedStacks = EnableSegmentedStacks; - Options.FixedStackSegmentSize = 2 * 1024 * 1024; // XXX: This is too big. - Options.FloatABIType = - (Trip.getEnvironment() == Triple::GNUEABIHF) ? FloatABI::Hard : - FloatABI::Default; - - PassManager *PM = unwrap(PMR); - - std::string Err; - std::string FeaturesStr(feature); - std::string CPUStr(cpu); - const Target *TheTarget = TargetRegistry::lookupTarget(Trip.getTriple(), Err); - TargetMachine *Target = - TheTarget->createTargetMachine(Trip.getTriple(), CPUStr, FeaturesStr, - Options, Reloc::PIC_, - CodeModel::Default, OptLevel); - Target->addAnalysisPasses(*PM); - - bool NoVerify = false; - std::string ErrorInfo; - raw_fd_ostream OS(path, ErrorInfo, - sys::fs::F_Binary); - if (ErrorInfo != "") { - LLVMRustError = ErrorInfo.c_str(); - return false; - } - formatted_raw_ostream FOS(OS); - - bool foo = Target->addPassesToEmitFile(*PM, FOS, FileType, NoVerify); - assert(!foo); - (void)foo; - PM->run(*unwrap(M)); - delete Target; - return true; -} - -extern "C" LLVMModuleRef LLVMRustParseAssemblyFile(LLVMContextRef C, - const char *Filename) { - SMDiagnostic d; - Module *m = ParseAssemblyFile(Filename, d, *unwrap(C)); - if (m) { - return wrap(m); - } else { - LLVMRustError = d.getMessage().str().c_str(); - return NULL; - } -} - -extern "C" LLVMModuleRef LLVMRustParseBitcode(LLVMMemoryBufferRef MemBuf) { - LLVMModuleRef M; - return LLVMParseBitcode(MemBuf, &M, const_cast(&LLVMRustError)) - ? NULL : M; +extern "C" void +LLVMRustSetNormalizedTarget(LLVMModuleRef M, const char *triple) { + unwrap(M)->setTargetTriple(Triple::normalize(triple)); } extern "C" LLVMValueRef LLVMRustConstSmallInt(LLVMTypeRef IntTy, unsigned N, @@ -463,11 +329,6 @@ extern "C" LLVMValueRef LLVMRustConstInt(LLVMTypeRef IntTy, return LLVMConstInt(IntTy, N, SignExtend); } -extern bool llvm::TimePassesIsEnabled; -extern "C" void LLVMRustEnableTimePasses() { - TimePassesIsEnabled = true; -} - extern "C" void LLVMRustPrintPassTimings() { raw_fd_ostream OS (2, false); // stderr. TimerGroup::printAll(OS); diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in index 75a55fdf88a41..e2cec6a04f346 100644 --- a/src/rustllvm/rustllvm.def.in +++ b/src/rustllvm/rustllvm.def.in @@ -1,5 +1,4 @@ LLVMRustCreateMemoryBufferWithContentsOfFile -LLVMRustEnableTimePasses LLVMRustWriteOutputFile LLVMRustGetLastError LLVMRustConstSmallInt @@ -7,8 +6,6 @@ LLVMRustConstInt LLVMRustLoadCrate LLVMRustPrepareJIT LLVMRustBuildJIT -LLVMRustParseBitcode -LLVMRustParseAssemblyFile LLVMRustPrintPassTimings LLVMRustStartMultithreading LLVMCreateObjectFile @@ -28,7 +25,6 @@ LLVMAddAlias LLVMAddArgumentPromotionPass LLVMAddAttribute LLVMAddBasicAliasAnalysisPass -LLVMRustAddPrintModulePass LLVMAddCFGSimplificationPass LLVMAddCase LLVMAddClause @@ -589,9 +585,6 @@ LLVMStructCreateNamed LLVMStructSetBody LLVMInlineAsm LLVMInitializePasses -LLVMAddPass -LLVMCreatePass -LLVMDestroyPass LLVMDIBuilderCreate LLVMDIBuilderDispose LLVMDIBuilderFinalize @@ -616,3 +609,15 @@ LLVMDIBuilderCreateEnumerationType LLVMDIBuilderCreateUnionType LLVMDIBuilderCreateTemplateTypeParameter LLVMSetUnnamedAddr +LLVMRustAddPass +LLVMRustAddAnalysisPasses +LLVMRustAddLibraryInfo +LLVMRustCreateTargetMachine +LLVMRustRunFunctionPassManager +LLVMRustPrintModule +LLVMRustDisposeTargetMachine +LLVMRustAddBuilderLibraryInfo +LLVMRustSetLLVMOptions +LLVMRustPrintPasses +LLVMRustSetNormalizedTarget +LLVMRustAddAlwaysInlinePass diff --git a/src/rustllvm/rustllvm.h b/src/rustllvm/rustllvm.h index eeefb19883eb3..94bb00aab7757 100644 --- a/src/rustllvm/rustllvm.h +++ b/src/rustllvm/rustllvm.h @@ -59,3 +59,5 @@ #include #include #endif + +extern const char* LLVMRustError;