rustc: Update LLVM
This commit updates the LLVM submodule in use to the current HEAD of the LLVM repository. This is primarily being done to start picking up unwinding support for MSVC, which is currently unimplemented in the revision of LLVM we are using. Along the way a few changes had to be made: * As usual, lots of C++ debuginfo bindings in LLVM changed, so there were some significant changes to our RustWrapper.cpp * As usual, some pass management changed in LLVM, so clang was re-scrutinized to ensure that we're doing the same thing as clang. * Some optimization options are now passed directly into the `PassManagerBuilder` instead of through CLI switches to LLVM. * The `NoFramePointerElim` option was removed from LLVM, favoring instead the `no-frame-pointer-elim` function attribute instead. Additionally, LLVM has picked up some new optimizations which required fixing an existing soundness hole in the IR we generate. It appears that the current LLVM we use does not expose this hole. When an enum is moved, the previous slot in memory is overwritten with a bit pattern corresponding to "dropped". When the drop glue for this slot is run, however, the switch on the discriminant can often start executing the `unreachable` block of the switch due to the discriminant now being outside the normal range. This was patched over locally for now by having the `unreachable` block just change to a `ret void`.
This commit is contained in:
parent
71a8d313c8
commit
f9d4149c29
@ -976,6 +976,9 @@ extern {
|
||||
pub fn LLVMAddDereferenceableAttr(Fn: ValueRef, index: c_uint, bytes: uint64_t);
|
||||
pub fn LLVMAddFunctionAttribute(Fn: ValueRef, index: c_uint, PA: uint64_t);
|
||||
pub fn LLVMAddFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *const c_char);
|
||||
pub fn LLVMAddFunctionAttrStringValue(Fn: ValueRef, index: c_uint,
|
||||
Name: *const c_char,
|
||||
Value: *const c_char);
|
||||
pub fn LLVMRemoveFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *const c_char);
|
||||
pub fn LLVMGetFunctionAttr(Fn: ValueRef) -> c_ulonglong;
|
||||
pub fn LLVMRemoveFunctionAttr(Fn: ValueRef, val: c_ulonglong);
|
||||
@ -1920,6 +1923,7 @@ extern {
|
||||
VarInfo: DIVariable,
|
||||
AddrOps: *const i64,
|
||||
AddrOpsCount: c_uint,
|
||||
DL: ValueRef,
|
||||
InsertAtEnd: BasicBlockRef)
|
||||
-> ValueRef;
|
||||
|
||||
@ -1928,6 +1932,7 @@ extern {
|
||||
VarInfo: DIVariable,
|
||||
AddrOps: *const i64,
|
||||
AddrOpsCount: c_uint,
|
||||
DL: ValueRef,
|
||||
InsertBefore: ValueRef)
|
||||
-> ValueRef;
|
||||
|
||||
@ -2035,7 +2040,6 @@ extern {
|
||||
Level: CodeGenOptLevel,
|
||||
EnableSegstk: bool,
|
||||
UseSoftFP: bool,
|
||||
NoFramePointerElim: bool,
|
||||
PositionIndependentExecutable: bool,
|
||||
FunctionSections: bool,
|
||||
DataSections: bool) -> TargetMachineRef;
|
||||
@ -2046,6 +2050,11 @@ extern {
|
||||
pub fn LLVMRustAddBuilderLibraryInfo(PMB: PassManagerBuilderRef,
|
||||
M: ModuleRef,
|
||||
DisableSimplifyLibCalls: bool);
|
||||
pub fn LLVMRustConfigurePassManagerBuilder(PMB: PassManagerBuilderRef,
|
||||
OptLevel: CodeGenOptLevel,
|
||||
MergeFunctions: bool,
|
||||
SLPVectorize: bool,
|
||||
LoopVectorize: bool);
|
||||
pub fn LLVMRustAddLibraryInfo(PM: PassManagerRef, M: ModuleRef,
|
||||
DisableSimplifyLibCalls: bool);
|
||||
pub fn LLVMRustRunFunctionPassManager(PM: PassManagerRef, M: ModuleRef);
|
||||
@ -2116,6 +2125,12 @@ extern {
|
||||
pub fn LLVMWriteSMDiagnosticToString(d: SMDiagnosticRef, s: RustStringRef);
|
||||
}
|
||||
|
||||
// LLVM requires symbols from this library, but apparently they're not printed
|
||||
// during llvm-config?
|
||||
#[cfg(windows)]
|
||||
#[link(name = "ole32")]
|
||||
extern {}
|
||||
|
||||
pub fn SetInstructionCallConv(instr: ValueRef, cc: CallConv) {
|
||||
unsafe {
|
||||
LLVMSetInstructionCallConv(instr, cc as c_uint);
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
use back::lto;
|
||||
use back::link::{get_cc_prog, remove};
|
||||
use session::config::{OutputFilenames, NoDebugInfo, Passes, SomePasses, AllPasses};
|
||||
use session::config::{OutputFilenames, Passes, SomePasses, AllPasses};
|
||||
use session::Session;
|
||||
use session::config;
|
||||
use llvm;
|
||||
@ -188,10 +188,6 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef {
|
||||
let opt_level = get_llvm_opt_level(sess.opts.optimize);
|
||||
let use_softfp = sess.opts.cg.soft_float;
|
||||
|
||||
// FIXME: #11906: Omitting frame pointers breaks retrieving the value of a parameter.
|
||||
let no_fp_elim = (sess.opts.debuginfo != NoDebugInfo) ||
|
||||
!sess.target.target.options.eliminate_frame_pointer;
|
||||
|
||||
let any_library = sess.crate_types.borrow().iter().any(|ty| {
|
||||
*ty != config::CrateTypeExecutable
|
||||
});
|
||||
@ -237,7 +233,6 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef {
|
||||
opt_level,
|
||||
true /* EnableSegstk */,
|
||||
use_softfp,
|
||||
no_fp_elim,
|
||||
!any_library && reloc_model == llvm::RelocPIC,
|
||||
ffunction_sections,
|
||||
fdata_sections,
|
||||
@ -279,6 +274,9 @@ struct ModuleConfig {
|
||||
no_prepopulate_passes: bool,
|
||||
no_builtins: bool,
|
||||
time_passes: bool,
|
||||
vectorize_loop: bool,
|
||||
vectorize_slp: bool,
|
||||
merge_functions: bool,
|
||||
}
|
||||
|
||||
unsafe impl Send for ModuleConfig { }
|
||||
@ -301,6 +299,9 @@ impl ModuleConfig {
|
||||
no_prepopulate_passes: false,
|
||||
no_builtins: false,
|
||||
time_passes: false,
|
||||
vectorize_loop: false,
|
||||
vectorize_slp: false,
|
||||
merge_functions: false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -309,6 +310,18 @@ impl ModuleConfig {
|
||||
self.no_prepopulate_passes = sess.opts.cg.no_prepopulate_passes;
|
||||
self.no_builtins = trans.no_builtins;
|
||||
self.time_passes = sess.time_passes();
|
||||
|
||||
// Copy what clang does by turning on loop vectorization at O2 and
|
||||
// slp vectorization at O3. Otherwise configure other optimization aspects
|
||||
// of this pass manager builder.
|
||||
self.vectorize_loop = !sess.opts.cg.no_vectorize_loops &&
|
||||
(sess.opts.optimize == config::Default ||
|
||||
sess.opts.optimize == config::Aggressive);
|
||||
self.vectorize_slp = !sess.opts.cg.no_vectorize_slp &&
|
||||
sess.opts.optimize == config::Aggressive;
|
||||
|
||||
self.merge_functions = sess.opts.optimize == config::Default ||
|
||||
sess.opts.optimize == config::Aggressive;
|
||||
}
|
||||
}
|
||||
|
||||
@ -448,27 +461,26 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
|
||||
let pass = CString::new(pass).unwrap();
|
||||
llvm::LLVMRustAddPass(fpm, pass.as_ptr())
|
||||
};
|
||||
if !config.no_verify { assert!(addpass("verify")); }
|
||||
|
||||
if !config.no_verify { assert!(addpass("verify")); }
|
||||
if !config.no_prepopulate_passes {
|
||||
llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
|
||||
llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
|
||||
populate_llvm_passes(fpm, mpm, llmod, opt_level,
|
||||
config.no_builtins);
|
||||
populate_llvm_passes(fpm, mpm, llmod, opt_level, &config);
|
||||
}
|
||||
|
||||
for pass in &config.passes {
|
||||
let pass = CString::new(pass.clone()).unwrap();
|
||||
if !llvm::LLVMRustAddPass(mpm, pass.as_ptr()) {
|
||||
cgcx.handler.warn(&format!("unknown pass {:?}, ignoring", pass));
|
||||
if !addpass(pass) {
|
||||
cgcx.handler.warn(&format!("unknown pass `{}`, ignoring",
|
||||
pass));
|
||||
}
|
||||
}
|
||||
|
||||
for pass in &cgcx.plugin_passes {
|
||||
let pass = CString::new(pass.clone()).unwrap();
|
||||
if !llvm::LLVMRustAddPass(mpm, pass.as_ptr()) {
|
||||
cgcx.handler.err(&format!("a plugin asked for LLVM pass {:?} but LLVM \
|
||||
does not recognize it", pass));
|
||||
if !addpass(pass) {
|
||||
cgcx.handler.err(&format!("a plugin asked for LLVM pass \
|
||||
`{}` but LLVM does not \
|
||||
recognize it", pass));
|
||||
}
|
||||
}
|
||||
|
||||
@ -520,7 +532,6 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
|
||||
llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod);
|
||||
llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
|
||||
f(cpm);
|
||||
llvm::LLVMDisposePassManager(cpm);
|
||||
}
|
||||
|
||||
if config.emit_bc {
|
||||
@ -537,13 +548,15 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
|
||||
let out = path2cstr(&out);
|
||||
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
||||
llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr());
|
||||
llvm::LLVMDisposePassManager(cpm);
|
||||
})
|
||||
}
|
||||
|
||||
if config.emit_asm {
|
||||
let path = output_names.with_extension(&format!("{}.s", name_extra));
|
||||
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
||||
write_output_file(cgcx.handler, tm, cpm, llmod, &path, llvm::AssemblyFileType);
|
||||
write_output_file(cgcx.handler, tm, cpm, llmod, &path,
|
||||
llvm::AssemblyFileType);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1008,16 +1021,9 @@ unsafe fn configure_llvm(sess: &Session) {
|
||||
use std::sync::Once;
|
||||
static INIT: Once = Once::new();
|
||||
|
||||
// Copy what clang does by turning on loop vectorization at O2 and
|
||||
// slp vectorization at O3
|
||||
let vectorize_loop = !sess.opts.cg.no_vectorize_loops &&
|
||||
(sess.opts.optimize == config::Default ||
|
||||
sess.opts.optimize == config::Aggressive);
|
||||
let vectorize_slp = !sess.opts.cg.no_vectorize_slp &&
|
||||
sess.opts.optimize == config::Aggressive;
|
||||
|
||||
let mut llvm_c_strs = Vec::new();
|
||||
let mut llvm_args = Vec::new();
|
||||
|
||||
{
|
||||
let mut add = |arg: &str| {
|
||||
let s = CString::new(arg).unwrap();
|
||||
@ -1025,8 +1031,6 @@ unsafe fn configure_llvm(sess: &Session) {
|
||||
llvm_c_strs.push(s);
|
||||
};
|
||||
add("rustc"); // fake program name
|
||||
if vectorize_loop { add("-vectorize-loops"); }
|
||||
if vectorize_slp { add("-vectorize-slp"); }
|
||||
if sess.time_llvm_passes() { add("-time-passes"); }
|
||||
if sess.print_llvm_passes() { add("-debug-pass=Structure"); }
|
||||
|
||||
@ -1084,41 +1088,40 @@ unsafe fn populate_llvm_passes(fpm: llvm::PassManagerRef,
|
||||
mpm: llvm::PassManagerRef,
|
||||
llmod: ModuleRef,
|
||||
opt: llvm::CodeGenOptLevel,
|
||||
no_builtins: bool) {
|
||||
config: &ModuleConfig) {
|
||||
// Create the PassManagerBuilder for LLVM. We configure it with
|
||||
// reasonable defaults and prepare it to actually populate the pass
|
||||
// manager.
|
||||
let builder = llvm::LLVMPassManagerBuilderCreate();
|
||||
|
||||
llvm::LLVMRustConfigurePassManagerBuilder(builder, opt,
|
||||
config.merge_functions,
|
||||
config.vectorize_slp,
|
||||
config.vectorize_loop);
|
||||
|
||||
llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod, config.no_builtins);
|
||||
|
||||
// Here we match what clang does (kinda). For O0 we only inline
|
||||
// always-inline functions (but don't add lifetime intrinsics), at O1 we
|
||||
// inline with lifetime intrinsics, and O2+ we add an inliner with a
|
||||
// thresholds copied from clang.
|
||||
match opt {
|
||||
llvm::CodeGenLevelNone => {
|
||||
// Don't add lifetime intrinsics at O0
|
||||
llvm::LLVMRustAddAlwaysInlinePass(builder, false);
|
||||
}
|
||||
llvm::CodeGenLevelLess => {
|
||||
llvm::LLVMRustAddAlwaysInlinePass(builder, true);
|
||||
}
|
||||
// numeric values copied from clang
|
||||
llvm::CodeGenLevelDefault => {
|
||||
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder,
|
||||
225);
|
||||
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 225);
|
||||
}
|
||||
llvm::CodeGenLevelAggressive => {
|
||||
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder,
|
||||
275);
|
||||
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 275);
|
||||
}
|
||||
}
|
||||
llvm::LLVMPassManagerBuilderSetOptLevel(builder, opt as c_uint);
|
||||
llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod, no_builtins);
|
||||
|
||||
// Use the builder to populate the function/module pass managers.
|
||||
llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(builder, fpm);
|
||||
llvm::LLVMPassManagerBuilderPopulateModulePassManager(builder, mpm);
|
||||
llvm::LLVMPassManagerBuilderDispose(builder);
|
||||
|
||||
match opt {
|
||||
llvm::CodeGenLevelDefault | llvm::CodeGenLevelAggressive => {
|
||||
llvm::LLVMRustAddPass(mpm, "mergefunc\0".as_ptr() as *const _);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
|
@ -1029,11 +1029,26 @@ pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
|
||||
}
|
||||
General(ity, ref cases, _) => {
|
||||
let ccx = bcx.ccx();
|
||||
let unr_cx = fcx.new_temp_block("enum-variant-iter-unr");
|
||||
Unreachable(unr_cx);
|
||||
|
||||
// See the comments in trans/base.rs for more information (inside
|
||||
// iter_structural_ty), but the gist here is that if the enum's
|
||||
// discriminant is *not* in the range that we're expecting (in which
|
||||
// case we'll take the fall-through branch on the switch
|
||||
// instruction) then we can't just optimize this to an Unreachable
|
||||
// block.
|
||||
//
|
||||
// Currently we still have filling drop, so this means that the drop
|
||||
// glue for enums may be called when the enum has been paved over
|
||||
// with the "I've been dropped" value. In this case the default
|
||||
// branch of the switch instruction will actually be taken at
|
||||
// runtime, so the basic block isn't actually unreachable, so we
|
||||
// need to make it do something with defined behavior. In this case
|
||||
// we just return early from the function.
|
||||
let ret_void_cx = fcx.new_temp_block("enum-variant-iter-ret-void");
|
||||
RetVoid(ret_void_cx, DebugLoc::None);
|
||||
|
||||
let discr_val = trans_get_discr(bcx, r, value, None);
|
||||
let llswitch = Switch(bcx, discr_val, unr_cx.llbb, cases.len());
|
||||
let llswitch = Switch(bcx, discr_val, ret_void_cx.llbb, cases.len());
|
||||
let bcx_next = fcx.new_temp_block("enum-variant-iter-next");
|
||||
|
||||
for (discr, case) in cases.iter().enumerate() {
|
||||
|
@ -12,6 +12,7 @@
|
||||
use libc::{c_uint, c_ulonglong};
|
||||
use llvm::{self, ValueRef, AttrHelper};
|
||||
use middle::ty::{self, ClosureTyper};
|
||||
use session::config::NoDebugInfo;
|
||||
use syntax::abi;
|
||||
use syntax::ast;
|
||||
pub use syntax::attr::InlineAttr;
|
||||
@ -106,6 +107,20 @@ pub fn from_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRe
|
||||
use syntax::attr::*;
|
||||
inline(llfn, find_inline_attr(Some(ccx.sess().diagnostic()), attrs));
|
||||
|
||||
// FIXME: #11906: Omitting frame pointers breaks retrieving the value of a
|
||||
// parameter.
|
||||
let no_fp_elim = (ccx.sess().opts.debuginfo != NoDebugInfo) ||
|
||||
!ccx.sess().target.target.options.eliminate_frame_pointer;
|
||||
if no_fp_elim {
|
||||
unsafe {
|
||||
let attr = "no-frame-pointer-elim\0".as_ptr() as *const _;
|
||||
let val = "true\0".as_ptr() as *const _;
|
||||
llvm::LLVMAddFunctionAttrStringValue(llfn,
|
||||
llvm::FunctionIndex as c_uint,
|
||||
attr, val);
|
||||
}
|
||||
}
|
||||
|
||||
for attr in attrs {
|
||||
if attr.check_name("no_stack_check") {
|
||||
split_stack(llfn, false);
|
||||
|
@ -480,9 +480,23 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
|
||||
}
|
||||
(_match::Switch, Some(lldiscrim_a)) => {
|
||||
cx = f(cx, lldiscrim_a, cx.tcx().types.isize);
|
||||
let unr_cx = fcx.new_temp_block("enum-iter-unr");
|
||||
Unreachable(unr_cx);
|
||||
let llswitch = Switch(cx, lldiscrim_a, unr_cx.llbb,
|
||||
|
||||
// Create a fall-through basic block for the "else" case of
|
||||
// the switch instruction we're about to generate. Note that
|
||||
// we do **not** use an Unreachable instruction here, even
|
||||
// though most of the time this basic block will never be hit.
|
||||
//
|
||||
// When an enum is dropped it's contents are currently
|
||||
// overwritten to DTOR_DONE, which means the discriminant
|
||||
// could have changed value to something not within the actual
|
||||
// range of the discriminant. Currently this function is only
|
||||
// used for drop glue so in this case we just return quickly
|
||||
// from the outer function, and any other use case will only
|
||||
// call this for an already-valid enum in which case the `ret
|
||||
// void` will never be hit.
|
||||
let ret_void_cx = fcx.new_temp_block("enum-iter-ret-void");
|
||||
RetVoid(ret_void_cx, DebugLoc::None);
|
||||
let llswitch = Switch(cx, lldiscrim_a, ret_void_cx.llbb,
|
||||
n_variants);
|
||||
let next_cx = fcx.new_temp_block("enum-iter-next");
|
||||
|
||||
|
@ -1673,7 +1673,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
DIB(cx),
|
||||
containing_scope,
|
||||
enum_name.as_ptr(),
|
||||
UNKNOWN_FILE_METADATA,
|
||||
file_metadata,
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
bytes_to_bits(enum_type_size),
|
||||
bytes_to_bits(enum_type_align),
|
||||
|
@ -484,10 +484,10 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
let param_metadata = unsafe {
|
||||
llvm::LLVMDIBuilderCreateTemplateTypeParameter(
|
||||
DIB(cx),
|
||||
file_metadata,
|
||||
ptr::null_mut(),
|
||||
name.as_ptr(),
|
||||
actual_self_type_metadata,
|
||||
ptr::null_mut(),
|
||||
file_metadata,
|
||||
0,
|
||||
0)
|
||||
};
|
||||
@ -518,10 +518,10 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
let param_metadata = unsafe {
|
||||
llvm::LLVMDIBuilderCreateTemplateTypeParameter(
|
||||
DIB(cx),
|
||||
file_metadata,
|
||||
ptr::null_mut(),
|
||||
name.as_ptr(),
|
||||
actual_type_metadata,
|
||||
ptr::null_mut(),
|
||||
file_metadata,
|
||||
0,
|
||||
0)
|
||||
};
|
||||
@ -580,12 +580,14 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
loc.line,
|
||||
loc.col.to_usize()));
|
||||
unsafe {
|
||||
let debug_loc = llvm::LLVMGetCurrentDebugLocation(cx.raw_builder());
|
||||
let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
|
||||
DIB(cx),
|
||||
alloca,
|
||||
metadata,
|
||||
address_operations.as_ptr(),
|
||||
address_operations.len() as c_uint,
|
||||
debug_loc,
|
||||
bcx.llbb);
|
||||
|
||||
llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr);
|
||||
|
2
src/llvm
2
src/llvm
@ -1 +1 @@
|
||||
Subproject commit bff69076975642c64e76dbeaa53476bfa7212086
|
||||
Subproject commit 8cbcdf1b72e1b23679646f6faca265f76b20d379
|
@ -103,9 +103,6 @@ extern "C" LLVMExecutionEngineRef LLVMBuildExecutionEngine(LLVMModuleRef mod)
|
||||
std::string error_str;
|
||||
TargetOptions options;
|
||||
|
||||
options.JITEmitDebugInfo = true;
|
||||
options.NoFramePointerElim = true;
|
||||
|
||||
RustJITMemoryManager *mm = new RustJITMemoryManager;
|
||||
|
||||
ExecutionEngine *ee =
|
||||
|
@ -15,12 +15,19 @@
|
||||
#include "llvm/Support/CBindingWrapping.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Host.h"
|
||||
#if LLVM_VERSION_MINOR >= 7
|
||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||
#include "llvm/Analysis/TargetTransformInfo.h"
|
||||
#else
|
||||
#include "llvm/Target/TargetLibraryInfo.h"
|
||||
#endif
|
||||
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
|
||||
|
||||
|
||||
#include "llvm-c/Transforms/PassManagerBuilder.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::legacy;
|
||||
|
||||
extern cl::opt<bool> EnableARMEHABI;
|
||||
|
||||
@ -71,7 +78,6 @@ LLVMRustCreateTargetMachine(const char *triple,
|
||||
CodeGenOpt::Level OptLevel,
|
||||
bool EnableSegmentedStacks,
|
||||
bool UseSoftFloat,
|
||||
bool NoFramePointerElim,
|
||||
bool PositionIndependentExecutable,
|
||||
bool FunctionSections,
|
||||
bool DataSections) {
|
||||
@ -91,12 +97,12 @@ LLVMRustCreateTargetMachine(const char *triple,
|
||||
|
||||
TargetOptions Options;
|
||||
Options.PositionIndependentExecutable = PositionIndependentExecutable;
|
||||
Options.NoFramePointerElim = NoFramePointerElim;
|
||||
Options.FloatABIType = FloatABI::Default;
|
||||
Options.UseSoftFloat = UseSoftFloat;
|
||||
if (UseSoftFloat) {
|
||||
Options.FloatABIType = FloatABI::Soft;
|
||||
}
|
||||
Options.DataSections = DataSections;
|
||||
Options.FunctionSections = FunctionSections;
|
||||
|
||||
TargetMachine *TM = TheTarget->createTargetMachine(Trip.getTriple(),
|
||||
real_cpu,
|
||||
@ -105,8 +111,6 @@ LLVMRustCreateTargetMachine(const char *triple,
|
||||
RM,
|
||||
CM,
|
||||
OptLevel);
|
||||
TM->setDataSections(DataSections);
|
||||
TM->setFunctionSections(FunctionSections);
|
||||
return wrap(TM);
|
||||
}
|
||||
|
||||
@ -123,12 +127,32 @@ LLVMRustAddAnalysisPasses(LLVMTargetMachineRef TM,
|
||||
LLVMPassManagerRef PMR,
|
||||
LLVMModuleRef M) {
|
||||
PassManagerBase *PM = unwrap(PMR);
|
||||
#if LLVM_VERSION_MINOR >= 6
|
||||
#if LLVM_VERSION_MINOR >= 7
|
||||
PM->add(createTargetTransformInfoWrapperPass(
|
||||
unwrap(TM)->getTargetIRAnalysis()));
|
||||
#else
|
||||
#if LLVM_VERSION_MINOR == 6
|
||||
PM->add(new DataLayoutPass());
|
||||
#else
|
||||
PM->add(new DataLayoutPass(unwrap(M)));
|
||||
#endif
|
||||
unwrap(TM)->addAnalysisPasses(*PM);
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
LLVMRustConfigurePassManagerBuilder(LLVMPassManagerBuilderRef PMB,
|
||||
CodeGenOpt::Level OptLevel,
|
||||
bool MergeFunctions,
|
||||
bool SLPVectorize,
|
||||
bool LoopVectorize) {
|
||||
#if LLVM_VERSION_MINOR >= 6
|
||||
// Ignore mergefunc for now as enabling it causes crashes.
|
||||
//unwrap(PMB)->MergeFunctions = MergeFunctions;
|
||||
#endif
|
||||
unwrap(PMB)->SLPVectorize = SLPVectorize;
|
||||
unwrap(PMB)->OptLevel = OptLevel;
|
||||
unwrap(PMB)->LoopVectorize = LoopVectorize;
|
||||
}
|
||||
|
||||
// Unfortunately, the LLVM C API doesn't provide a way to set the `LibraryInfo`
|
||||
@ -138,7 +162,11 @@ LLVMRustAddBuilderLibraryInfo(LLVMPassManagerBuilderRef PMB,
|
||||
LLVMModuleRef M,
|
||||
bool DisableSimplifyLibCalls) {
|
||||
Triple TargetTriple(unwrap(M)->getTargetTriple());
|
||||
#if LLVM_VERSION_MINOR >= 7
|
||||
TargetLibraryInfoImpl *TLI = new TargetLibraryInfoImpl(TargetTriple);
|
||||
#else
|
||||
TargetLibraryInfo *TLI = new TargetLibraryInfo(TargetTriple);
|
||||
#endif
|
||||
if (DisableSimplifyLibCalls)
|
||||
TLI->disableAllFunctions();
|
||||
unwrap(PMB)->LibraryInfo = TLI;
|
||||
@ -151,10 +179,17 @@ LLVMRustAddLibraryInfo(LLVMPassManagerRef PMB,
|
||||
LLVMModuleRef M,
|
||||
bool DisableSimplifyLibCalls) {
|
||||
Triple TargetTriple(unwrap(M)->getTargetTriple());
|
||||
#if LLVM_VERSION_MINOR >= 7
|
||||
TargetLibraryInfoImpl TLII(TargetTriple);
|
||||
if (DisableSimplifyLibCalls)
|
||||
TLII.disableAllFunctions();
|
||||
unwrap(PMB)->add(new TargetLibraryInfoWrapperPass(TLII));
|
||||
#else
|
||||
TargetLibraryInfo *TLI = new TargetLibraryInfo(TargetTriple);
|
||||
if (DisableSimplifyLibCalls)
|
||||
TLI->disableAllFunctions();
|
||||
unwrap(PMB)->add(TLI);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Unfortunately, the LLVM C API doesn't provide an easy way of iterating over
|
||||
@ -204,10 +239,19 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target,
|
||||
LLVMRustSetLastError(ErrorInfo.c_str());
|
||||
return false;
|
||||
}
|
||||
formatted_raw_ostream FOS(OS);
|
||||
|
||||
#if LLVM_VERSION_MINOR >= 7
|
||||
unwrap(Target)->addPassesToEmitFile(*PM, OS, FileType, false);
|
||||
#else
|
||||
formatted_raw_ostream FOS(OS);
|
||||
unwrap(Target)->addPassesToEmitFile(*PM, FOS, FileType, false);
|
||||
#endif
|
||||
PM->run(*unwrap(M));
|
||||
|
||||
// Apparently `addPassesToEmitFile` adds an pointer to our on-the-stack output
|
||||
// stream (OS), so the only real safe place to delete this is here? Don't we
|
||||
// wish this was written in Rust?
|
||||
delete PM;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -141,6 +141,15 @@ extern "C" void LLVMAddFunctionAttrString(LLVMValueRef Fn, unsigned index, const
|
||||
F->addAttributes(index, AttributeSet::get(F->getContext(), index, B));
|
||||
}
|
||||
|
||||
extern "C" void LLVMAddFunctionAttrStringValue(LLVMValueRef Fn, unsigned index,
|
||||
const char *Name,
|
||||
const char *Value) {
|
||||
Function *F = unwrap<Function>(Fn);
|
||||
AttrBuilder B;
|
||||
B.addAttribute(Name, Value);
|
||||
F->addAttributes(index, AttributeSet::get(F->getContext(), index, B));
|
||||
}
|
||||
|
||||
extern "C" void LLVMRemoveFunctionAttrString(LLVMValueRef fn, unsigned index, const char *Name) {
|
||||
Function *f = unwrap<Function>(fn);
|
||||
LLVMContext &C = f->getContext();
|
||||
@ -228,10 +237,25 @@ inline Metadata **unwrap(LLVMMetadataRef *Vals) {
|
||||
typedef LLVMValueRef LLVMMetadataRef;
|
||||
#endif
|
||||
|
||||
template<typename DIT>
|
||||
DIT* unwrapDIptr(LLVMMetadataRef ref) {
|
||||
return (DIT*) (ref ? unwrap<MDNode>(ref) : NULL);
|
||||
}
|
||||
|
||||
#if LLVM_VERSION_MINOR <= 6
|
||||
template<typename DIT>
|
||||
DIT unwrapDI(LLVMMetadataRef ref) {
|
||||
return DIT(ref ? unwrap<MDNode>(ref) : NULL);
|
||||
}
|
||||
#else
|
||||
#define DIDescriptor DIScope
|
||||
#define DIArray DINodeArray
|
||||
#define unwrapDI unwrapDIptr
|
||||
#endif
|
||||
|
||||
#if LLVM_VERSION_MINOR <= 5
|
||||
#define DISubroutineType DICompositeType
|
||||
#endif
|
||||
|
||||
extern "C" uint32_t LLVMRustDebugMetadataVersion() {
|
||||
return DEBUG_METADATA_VERSION;
|
||||
@ -296,7 +320,9 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateSubroutineType(
|
||||
LLVMMetadataRef ParameterTypes) {
|
||||
return wrap(Builder->createSubroutineType(
|
||||
unwrapDI<DIFile>(File),
|
||||
#if LLVM_VERSION_MINOR >= 6
|
||||
#if LLVM_VERSION_MINOR >= 7
|
||||
DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
|
||||
#elif LLVM_VERSION_MINOR >= 6
|
||||
unwrapDI<DITypeArray>(ParameterTypes)));
|
||||
#else
|
||||
unwrapDI<DIArray>(ParameterTypes)));
|
||||
@ -322,11 +348,11 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateFunction(
|
||||
return wrap(Builder->createFunction(
|
||||
unwrapDI<DIScope>(Scope), Name, LinkageName,
|
||||
unwrapDI<DIFile>(File), LineNo,
|
||||
unwrapDI<DICompositeType>(Ty), isLocalToUnit, isDefinition, ScopeLine,
|
||||
unwrapDI<DISubroutineType>(Ty), isLocalToUnit, isDefinition, ScopeLine,
|
||||
Flags, isOptimized,
|
||||
unwrap<Function>(Fn),
|
||||
unwrapDI<MDNode*>(TParam),
|
||||
unwrapDI<MDNode*>(Decl)));
|
||||
unwrapDIptr<MDNode>(TParam),
|
||||
unwrapDIptr<MDNode>(Decl)));
|
||||
}
|
||||
|
||||
extern "C" LLVMMetadataRef LLVMDIBuilderCreateBasicType(
|
||||
@ -373,7 +399,11 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateStructType(
|
||||
AlignInBits,
|
||||
Flags,
|
||||
unwrapDI<DIType>(DerivedFrom),
|
||||
#if LLVM_VERSION_MINOR >= 7
|
||||
DINodeArray(unwrapDI<MDTuple>(Elements)),
|
||||
#else
|
||||
unwrapDI<DIArray>(Elements),
|
||||
#endif
|
||||
RunTimeLang,
|
||||
unwrapDI<DIType>(VTableHolder),
|
||||
UniqueId
|
||||
@ -436,7 +466,7 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateStaticVariable(
|
||||
unwrapDI<DIType>(Ty),
|
||||
isLocalToUnit,
|
||||
cast<Constant>(unwrap(Val)),
|
||||
unwrapDI<MDNode*>(Decl)));
|
||||
unwrapDIptr<MDNode>(Decl)));
|
||||
}
|
||||
|
||||
extern "C" LLVMMetadataRef LLVMDIBuilderCreateVariable(
|
||||
@ -486,7 +516,12 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateArrayType(
|
||||
LLVMMetadataRef Subscripts) {
|
||||
return wrap(Builder->createArrayType(Size, AlignInBits,
|
||||
unwrapDI<DIType>(Ty),
|
||||
unwrapDI<DIArray>(Subscripts)));
|
||||
#if LLVM_VERSION_MINOR >= 7
|
||||
DINodeArray(unwrapDI<MDTuple>(Subscripts))
|
||||
#else
|
||||
unwrapDI<DIArray>(Subscripts)
|
||||
#endif
|
||||
));
|
||||
}
|
||||
|
||||
extern "C" LLVMMetadataRef LLVMDIBuilderCreateVectorType(
|
||||
@ -497,7 +532,12 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateVectorType(
|
||||
LLVMMetadataRef Subscripts) {
|
||||
return wrap(Builder->createVectorType(Size, AlignInBits,
|
||||
unwrapDI<DIType>(Ty),
|
||||
unwrapDI<DIArray>(Subscripts)));
|
||||
#if LLVM_VERSION_MINOR >= 7
|
||||
DINodeArray(unwrapDI<MDTuple>(Subscripts))
|
||||
#else
|
||||
unwrapDI<DIArray>(Subscripts)
|
||||
#endif
|
||||
));
|
||||
}
|
||||
|
||||
extern "C" LLVMMetadataRef LLVMDIBuilderGetOrCreateSubrange(
|
||||
@ -511,12 +551,18 @@ extern "C" LLVMMetadataRef LLVMDIBuilderGetOrCreateArray(
|
||||
DIBuilderRef Builder,
|
||||
LLVMMetadataRef* Ptr,
|
||||
unsigned Count) {
|
||||
#if LLVM_VERSION_MINOR >= 7
|
||||
Metadata **DataValue = unwrap(Ptr);
|
||||
return wrap(Builder->getOrCreateArray(
|
||||
ArrayRef<Metadata*>(DataValue, Count)).get());
|
||||
#else
|
||||
return wrap(Builder->getOrCreateArray(
|
||||
#if LLVM_VERSION_MINOR >= 6
|
||||
ArrayRef<Metadata*>(unwrap(Ptr), Count)));
|
||||
#else
|
||||
ArrayRef<Value*>(reinterpret_cast<Value**>(Ptr), Count)));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(
|
||||
@ -525,21 +571,21 @@ extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(
|
||||
LLVMMetadataRef VarInfo,
|
||||
int64_t* AddrOps,
|
||||
unsigned AddrOpsCount,
|
||||
LLVMValueRef DL,
|
||||
LLVMBasicBlockRef InsertAtEnd) {
|
||||
#if LLVM_VERSION_MINOR >= 6
|
||||
DIExpression Expr;
|
||||
if (AddrOpsCount == 0) {
|
||||
Expr = Builder->createExpression();
|
||||
} else {
|
||||
llvm::ArrayRef<int64_t> addr_ops(AddrOps, AddrOpsCount);
|
||||
Expr = Builder->createExpression(addr_ops);
|
||||
}
|
||||
#endif
|
||||
return wrap(Builder->insertDeclare(
|
||||
unwrap(Val),
|
||||
#if LLVM_VERSION_MINOR >= 7
|
||||
unwrap<DILocalVariable>(VarInfo),
|
||||
#else
|
||||
unwrapDI<DIVariable>(VarInfo),
|
||||
#endif
|
||||
#if LLVM_VERSION_MINOR >= 6
|
||||
Expr,
|
||||
Builder->createExpression(
|
||||
llvm::ArrayRef<int64_t>(AddrOps, AddrOpsCount)),
|
||||
#endif
|
||||
#if LLVM_VERSION_MINOR >= 7
|
||||
DebugLoc(cast<MDNode>(unwrap<MetadataAsValue>(DL)->getMetadata())),
|
||||
#endif
|
||||
unwrap(InsertAtEnd)));
|
||||
}
|
||||
@ -550,21 +596,23 @@ extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareBefore(
|
||||
LLVMMetadataRef VarInfo,
|
||||
int64_t* AddrOps,
|
||||
unsigned AddrOpsCount,
|
||||
LLVMValueRef DL,
|
||||
LLVMValueRef InsertBefore) {
|
||||
#if LLVM_VERSION_MINOR >= 6
|
||||
DIExpression Expr;
|
||||
if (AddrOpsCount == 0) {
|
||||
Expr = Builder->createExpression();
|
||||
} else {
|
||||
llvm::ArrayRef<int64_t> addr_ops(AddrOps, AddrOpsCount);
|
||||
Expr = Builder->createExpression(addr_ops);
|
||||
}
|
||||
#endif
|
||||
return wrap(Builder->insertDeclare(
|
||||
unwrap(Val),
|
||||
#if LLVM_VERSION_MINOR >= 7
|
||||
unwrap<DILocalVariable>(VarInfo),
|
||||
#else
|
||||
unwrapDI<DIVariable>(VarInfo),
|
||||
#endif
|
||||
#if LLVM_VERSION_MINOR >= 6
|
||||
Expr,
|
||||
Builder->createExpression(
|
||||
llvm::ArrayRef<int64_t>(AddrOps, AddrOpsCount)),
|
||||
#endif
|
||||
#if LLVM_VERSION_MINOR >= 7
|
||||
DebugLoc(cast<MDNode>(unwrap<MetadataAsValue>(DL)->getMetadata())),
|
||||
#endif
|
||||
unwrap<Instruction>(InsertBefore)));
|
||||
}
|
||||
@ -595,7 +643,11 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateEnumerationType(
|
||||
LineNumber,
|
||||
SizeInBits,
|
||||
AlignInBits,
|
||||
#if LLVM_VERSION_MINOR >= 7
|
||||
DINodeArray(unwrapDI<MDTuple>(Elements)),
|
||||
#else
|
||||
unwrapDI<DIArray>(Elements),
|
||||
#endif
|
||||
unwrapDI<DIType>(ClassType)));
|
||||
}
|
||||
|
||||
@ -620,7 +672,11 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateUnionType(
|
||||
SizeInBits,
|
||||
AlignInBits,
|
||||
Flags,
|
||||
#if LLVM_VERSION_MINOR >= 7
|
||||
DINodeArray(unwrapDI<MDTuple>(Elements)),
|
||||
#else
|
||||
unwrapDI<DIArray>(Elements),
|
||||
#endif
|
||||
RunTimeLang,
|
||||
UniqueId
|
||||
));
|
||||
@ -638,10 +694,14 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateTemplateTypeParameter(
|
||||
return wrap(Builder->createTemplateTypeParameter(
|
||||
unwrapDI<DIDescriptor>(Scope),
|
||||
Name,
|
||||
unwrapDI<DIType>(Ty),
|
||||
unwrapDI<DIType>(Ty)
|
||||
#if LLVM_VERSION_MINOR <= 6
|
||||
,
|
||||
unwrapDI<MDNode*>(File),
|
||||
LineNo,
|
||||
ColumnNo));
|
||||
ColumnNo
|
||||
#endif
|
||||
));
|
||||
}
|
||||
|
||||
extern "C" int64_t LLVMDIBuilderCreateOpDeref()
|
||||
@ -673,7 +733,10 @@ extern "C" void LLVMDICompositeTypeSetTypeArray(
|
||||
LLVMMetadataRef CompositeType,
|
||||
LLVMMetadataRef TypeArray)
|
||||
{
|
||||
#if LLVM_VERSION_MINOR >= 6
|
||||
#if LLVM_VERSION_MINOR >= 7
|
||||
DICompositeType *tmp = unwrapDI<DICompositeType>(CompositeType);
|
||||
Builder->replaceArrays(tmp, DINodeArray(unwrap<MDTuple>(TypeArray)));
|
||||
#elif LLVM_VERSION_MINOR >= 6
|
||||
DICompositeType tmp = unwrapDI<DICompositeType>(CompositeType);
|
||||
Builder->replaceArrays(tmp, unwrapDI<DIArray>(TypeArray));
|
||||
#else
|
||||
@ -692,11 +755,15 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateDebugLocation(
|
||||
|
||||
DebugLoc debug_loc = DebugLoc::get(Line,
|
||||
Column,
|
||||
unwrapDI<MDNode*>(Scope),
|
||||
unwrapDI<MDNode*>(InlinedAt));
|
||||
unwrapDIptr<MDNode>(Scope),
|
||||
unwrapDIptr<MDNode>(InlinedAt));
|
||||
|
||||
#if LLVM_VERSION_MINOR >= 6
|
||||
return wrap(MetadataAsValue::get(context, debug_loc.getAsMDNode(context)));
|
||||
return wrap(MetadataAsValue::get(context, debug_loc.getAsMDNode(
|
||||
#if LLVM_VERSION_MINOR <= 6
|
||||
context
|
||||
#endif
|
||||
)));
|
||||
#else
|
||||
return wrap(debug_loc.getAsMDNode(context));
|
||||
#endif
|
||||
@ -721,7 +788,12 @@ LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) {
|
||||
Module *Dst = unwrap(dst);
|
||||
#if LLVM_VERSION_MINOR >= 6
|
||||
std::unique_ptr<MemoryBuffer> buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len));
|
||||
#if LLVM_VERSION_MINOR >= 7
|
||||
ErrorOr<std::unique_ptr<Module>> Src =
|
||||
llvm::getLazyBitcodeModule(std::move(buf), Dst->getContext());
|
||||
#else
|
||||
ErrorOr<Module *> Src = llvm::getLazyBitcodeModule(std::move(buf), Dst->getContext());
|
||||
#endif
|
||||
#else
|
||||
MemoryBuffer* buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len));
|
||||
ErrorOr<Module *> Src = llvm::getLazyBitcodeModule(buf, Dst->getContext());
|
||||
@ -739,7 +811,11 @@ LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) {
|
||||
#if LLVM_VERSION_MINOR >= 6
|
||||
raw_string_ostream Stream(Err);
|
||||
DiagnosticPrinterRawOStream DP(Stream);
|
||||
#if LLVM_VERSION_MINOR >= 7
|
||||
if (Linker::LinkModules(Dst, Src->get(), [&](const DiagnosticInfo &DI) { DI.print(DP); })) {
|
||||
#else
|
||||
if (Linker::LinkModules(Dst, *Src, [&](const DiagnosticInfo &DI) { DI.print(DP); })) {
|
||||
#endif
|
||||
#else
|
||||
if (Linker::LinkModules(Dst, *Src, Linker::DestroySource, &Err)) {
|
||||
#endif
|
||||
@ -813,8 +889,12 @@ extern "C" const Archive::Child*
|
||||
LLVMRustArchiveIteratorCurrent(RustArchiveIterator *rai) {
|
||||
if (rai->cur == rai->end)
|
||||
return NULL;
|
||||
#if LLVM_VERSION_MINOR >= 6
|
||||
const Archive::Child &ret = *rai->cur;
|
||||
return &ret;
|
||||
#else
|
||||
return rai->cur.operator->();
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
@ -942,7 +1022,11 @@ extern "C" void LLVMWriteDebugLocToString(
|
||||
RustStringRef str)
|
||||
{
|
||||
raw_rust_string_ostream os(str);
|
||||
#if LLVM_VERSION_MINOR >= 7
|
||||
unwrap(dl)->print(os);
|
||||
#else
|
||||
unwrap(dl)->print(*unwrap(C), os);
|
||||
#endif
|
||||
}
|
||||
|
||||
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
|
||||
|
@ -1,4 +1,4 @@
|
||||
# If this file is modified, then llvm will be forcibly cleaned and then rebuilt.
|
||||
# The actual contents of this file do not matter, but to trigger a change on the
|
||||
# build bots then the contents should be changed so git updates the mtime.
|
||||
2015-03-04
|
||||
2015-06-16
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include "llvm/IR/InlineAsm.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/PassManager.h"
|
||||
#include "llvm/IR/InlineAsm.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/Analysis/Passes.h"
|
||||
@ -46,6 +45,12 @@
|
||||
#include "llvm-c/ExecutionEngine.h"
|
||||
#include "llvm-c/Object.h"
|
||||
|
||||
#if LLVM_VERSION_MINOR >= 7
|
||||
#include "llvm/IR/LegacyPassManager.h"
|
||||
#else
|
||||
#include "llvm/PassManager.h"
|
||||
#endif
|
||||
|
||||
#include "llvm/IR/IRPrintingPasses.h"
|
||||
#include "llvm/IR/DebugInfo.h"
|
||||
#include "llvm/IR/DIBuilder.h"
|
||||
|
@ -24,5 +24,5 @@ pub fn plugin_registrar(reg: &mut Registry) {
|
||||
// Normally, we would name a pass that was registered through
|
||||
// C++ static object constructors in the same .so file as the
|
||||
// plugin registrar.
|
||||
reg.register_llvm_pass("inline");
|
||||
reg.register_llvm_pass("gvn");
|
||||
}
|
||||
|
@ -20,14 +20,14 @@ pub struct Bytes {
|
||||
// CHECK-LABEL: @borrow
|
||||
#[no_mangle]
|
||||
pub fn borrow(x: &i32) -> &i32 {
|
||||
// CHECK: load i32** %x{{.*}}, !nonnull
|
||||
// CHECK: load i32*, i32** %x{{.*}}, !nonnull
|
||||
x
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @_box
|
||||
#[no_mangle]
|
||||
pub fn _box(x: Box<i32>) -> i32 {
|
||||
// CHECK: load i32** %x{{.*}}, !nonnull
|
||||
// CHECK: load i32*, i32** %x{{.*}}, !nonnull
|
||||
*x
|
||||
}
|
||||
|
||||
@ -36,7 +36,7 @@ pub fn _box(x: Box<i32>) -> i32 {
|
||||
// dependent alignment
|
||||
#[no_mangle]
|
||||
pub fn small_array_alignment(x: [i8; 4]) -> [i8; 4] {
|
||||
// CHECK: [[VAR:%[0-9]+]] = load i32* %{{.*}}, align 1
|
||||
// CHECK: [[VAR:%[0-9]+]] = load i32, i32* %{{.*}}, align 1
|
||||
// CHECK: ret i32 [[VAR]]
|
||||
x
|
||||
}
|
||||
@ -46,7 +46,7 @@ pub fn small_array_alignment(x: [i8; 4]) -> [i8; 4] {
|
||||
// dependent alignment
|
||||
#[no_mangle]
|
||||
pub fn small_struct_alignment(x: Bytes) -> Bytes {
|
||||
// CHECK: [[VAR:%[0-9]+]] = load i32* %{{.*}}, align 1
|
||||
// CHECK: [[VAR:%[0-9]+]] = load i32, i32* %{{.*}}, align 1
|
||||
// CHECK: ret i32 [[VAR]]
|
||||
x
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ pub struct Bytes {
|
||||
// dependent alignment
|
||||
#[no_mangle]
|
||||
pub fn small_array_alignment(x: &mut [i8; 4]) {
|
||||
// CHECK: [[VAR:%[0-9]+]] = load [4 x i8]** %x
|
||||
// CHECK: [[VAR:%[0-9]+]] = load [4 x i8]*, [4 x i8]** %x
|
||||
// CHECK: [[VAR2:%[0-9]+]] = bitcast [4 x i8]* [[VAR]] to i32*
|
||||
// CHECK: store i32 %{{.*}}, i32* [[VAR2]], align 1
|
||||
*x = [0; 4];
|
||||
@ -33,7 +33,7 @@ pub fn small_array_alignment(x: &mut [i8; 4]) {
|
||||
// dependent alignment
|
||||
#[no_mangle]
|
||||
pub fn small_struct_alignment(x: &mut Bytes) {
|
||||
// CHECK: [[VAR:%[0-9]+]] = load %Bytes** %x
|
||||
// CHECK: [[VAR:%[0-9]+]] = load %Bytes*, %Bytes** %x
|
||||
// CHECK: [[VAR2:%[0-9]+]] = bitcast %Bytes* [[VAR]] to i32*
|
||||
// CHECK: store i32 %{{.*}}, i32* [[VAR2]], align 1
|
||||
*x = Bytes {
|
||||
|
@ -8,14 +8,13 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
|
||||
#![feature(asm)]
|
||||
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
unsafe fn next_power_of_2(n: u32) -> u32 {
|
||||
let mut tmp = n;
|
||||
asm!("dec $0" : "+rm"(tmp) :: "cc");
|
||||
let mut shift = 1_usize;
|
||||
let mut shift = 1_u32;
|
||||
while shift <= 16 {
|
||||
asm!(
|
||||
"shr %cl, $2
|
||||
|
Loading…
x
Reference in New Issue
Block a user