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;
}
}
-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");
}
}
}
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,
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(); }
}
}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<PassRef> {
- 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!();
- }
-}
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>", "DIR"),
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),
(~"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),
]
}
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 {
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,
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;
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};
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};
/** Creates a pass manager. */
#[fast_ffi]
pub fn LLVMCreatePassManager() -> PassManagerRef;
+
/** Creates a function-by-function pass manager */
#[fast_ffi]
pub fn LLVMCreateFunctionPassManagerForModule(M: ModuleRef)
#[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);
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]
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();
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);
}
}
}
}
-
/* Memory-managed interface to target data. */
pub struct target_data_res {
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;
pub mod x86_64;
pub mod rpath;
pub mod target_strs;
- pub mod passes;
}
pub mod metadata;
}
if getopts::opt_maybe_str(matches, "passes") == Some(~"list") {
- back::passes::list_passes();
+ unsafe { lib::llvm::llvm::LLVMRustPrintPasses(); }
return;
}
impl<T> Repr<*Box<T>> for @T {}
impl<T> Repr<*Box<Vec<T>>> for @[T] {}
impl Repr<*String> for ~str {}
+impl Repr<*Box<String>> for @str {}
// sure would be nice to have this
// impl<T> Repr<*Vec<T>> for ~[T] {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#include <stdio.h>
+
#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<Pass*>(P);
-}
+using namespace llvm;
-inline LLVMPassRef wrap(const Pass *P) {
- return reinterpret_cast<LLVMPassRef>(const_cast<Pass*>(P));
-}
+extern cl::opt<bool> EnableARMEHABI;
-template<typename T>
-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);
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<FunctionPassManager>(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<PassManager>(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<PassManager>(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);
}
using namespace llvm;
using namespace llvm::sys;
-static const char *LLVMRustError;
-
-extern cl::opt<bool> EnableARMEHABI;
+const char *LLVMRustError;
extern "C" LLVMMemoryBufferRef
LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) {
return LLVMRustError;
}
-extern "C" void LLVMAddBasicAliasAnalysisPass(LLVMPassManagerRef PM);
-
-extern "C" void LLVMRustAddPrintModulePass(LLVMPassManagerRef PMR,
- LLVMModuleRef M,
- const char* path) {
- PassManager *PM = unwrap<PassManager>(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.
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<PassManager>(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<char **>(&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,
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);
LLVMRustCreateMemoryBufferWithContentsOfFile
-LLVMRustEnableTimePasses
LLVMRustWriteOutputFile
LLVMRustGetLastError
LLVMRustConstSmallInt
LLVMRustLoadCrate
LLVMRustPrepareJIT
LLVMRustBuildJIT
-LLVMRustParseBitcode
-LLVMRustParseAssemblyFile
LLVMRustPrintPassTimings
LLVMRustStartMultithreading
LLVMCreateObjectFile
LLVMAddArgumentPromotionPass
LLVMAddAttribute
LLVMAddBasicAliasAnalysisPass
-LLVMRustAddPrintModulePass
LLVMAddCFGSimplificationPass
LLVMAddCase
LLVMAddClause
LLVMStructSetBody
LLVMInlineAsm
LLVMInitializePasses
-LLVMAddPass
-LLVMCreatePass
-LLVMDestroyPass
LLVMDIBuilderCreate
LLVMDIBuilderDispose
LLVMDIBuilderFinalize
LLVMDIBuilderCreateUnionType
LLVMDIBuilderCreateTemplateTypeParameter
LLVMSetUnnamedAddr
+LLVMRustAddPass
+LLVMRustAddAnalysisPasses
+LLVMRustAddLibraryInfo
+LLVMRustCreateTargetMachine
+LLVMRustRunFunctionPassManager
+LLVMRustPrintModule
+LLVMRustDisposeTargetMachine
+LLVMRustAddBuilderLibraryInfo
+LLVMRustSetLLVMOptions
+LLVMRustPrintPasses
+LLVMRustSetNormalizedTarget
+LLVMRustAddAlwaysInlinePass
#include <fcntl.h>
#include <unistd.h>
#endif
+
+extern const char* LLVMRustError;