Skip to content

Commit 2146851

Browse files
committed
Auto merge of #26025 - alexcrichton:update-llvm, r=brson
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. * The `LoopVectorize` option of the LLVM optimization passes has been disabled as it causes a divide-by-zero exception to happen in LLVM for zero-sized types. This is reported as https://llvm.org/bugs/show_bug.cgi?id=23763 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`.
2 parents c78c099 + 0e0cc9e commit 2146851

File tree

15 files changed

+267
-104
lines changed

15 files changed

+267
-104
lines changed

src/librustc_llvm/lib.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -979,6 +979,9 @@ extern {
979979
pub fn LLVMAddDereferenceableAttr(Fn: ValueRef, index: c_uint, bytes: uint64_t);
980980
pub fn LLVMAddFunctionAttribute(Fn: ValueRef, index: c_uint, PA: uint64_t);
981981
pub fn LLVMAddFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *const c_char);
982+
pub fn LLVMAddFunctionAttrStringValue(Fn: ValueRef, index: c_uint,
983+
Name: *const c_char,
984+
Value: *const c_char);
982985
pub fn LLVMRemoveFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *const c_char);
983986
pub fn LLVMGetFunctionAttr(Fn: ValueRef) -> c_ulonglong;
984987
pub fn LLVMRemoveFunctionAttr(Fn: ValueRef, val: c_ulonglong);
@@ -1924,6 +1927,7 @@ extern {
19241927
VarInfo: DIVariable,
19251928
AddrOps: *const i64,
19261929
AddrOpsCount: c_uint,
1930+
DL: ValueRef,
19271931
InsertAtEnd: BasicBlockRef)
19281932
-> ValueRef;
19291933

@@ -1932,6 +1936,7 @@ extern {
19321936
VarInfo: DIVariable,
19331937
AddrOps: *const i64,
19341938
AddrOpsCount: c_uint,
1939+
DL: ValueRef,
19351940
InsertBefore: ValueRef)
19361941
-> ValueRef;
19371942

@@ -2039,7 +2044,6 @@ extern {
20392044
Level: CodeGenOptLevel,
20402045
EnableSegstk: bool,
20412046
UseSoftFP: bool,
2042-
NoFramePointerElim: bool,
20432047
PositionIndependentExecutable: bool,
20442048
FunctionSections: bool,
20452049
DataSections: bool) -> TargetMachineRef;
@@ -2050,6 +2054,11 @@ extern {
20502054
pub fn LLVMRustAddBuilderLibraryInfo(PMB: PassManagerBuilderRef,
20512055
M: ModuleRef,
20522056
DisableSimplifyLibCalls: bool);
2057+
pub fn LLVMRustConfigurePassManagerBuilder(PMB: PassManagerBuilderRef,
2058+
OptLevel: CodeGenOptLevel,
2059+
MergeFunctions: bool,
2060+
SLPVectorize: bool,
2061+
LoopVectorize: bool);
20532062
pub fn LLVMRustAddLibraryInfo(PM: PassManagerRef, M: ModuleRef,
20542063
DisableSimplifyLibCalls: bool);
20552064
pub fn LLVMRustRunFunctionPassManager(PM: PassManagerRef, M: ModuleRef);

src/librustc_trans/back/write.rs

+47-44
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use back::lto;
1212
use back::link::{get_cc_prog, remove};
13-
use session::config::{OutputFilenames, NoDebugInfo, Passes, SomePasses, AllPasses};
13+
use session::config::{OutputFilenames, Passes, SomePasses, AllPasses};
1414
use session::Session;
1515
use session::config;
1616
use llvm;
@@ -188,10 +188,6 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef {
188188
let opt_level = get_llvm_opt_level(sess.opts.optimize);
189189
let use_softfp = sess.opts.cg.soft_float;
190190

191-
// FIXME: #11906: Omitting frame pointers breaks retrieving the value of a parameter.
192-
let no_fp_elim = (sess.opts.debuginfo != NoDebugInfo) ||
193-
!sess.target.target.options.eliminate_frame_pointer;
194-
195191
let any_library = sess.crate_types.borrow().iter().any(|ty| {
196192
*ty != config::CrateTypeExecutable
197193
});
@@ -237,7 +233,6 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef {
237233
opt_level,
238234
true /* EnableSegstk */,
239235
use_softfp,
240-
no_fp_elim,
241236
!any_library && reloc_model == llvm::RelocPIC,
242237
ffunction_sections,
243238
fdata_sections,
@@ -279,6 +274,9 @@ struct ModuleConfig {
279274
no_prepopulate_passes: bool,
280275
no_builtins: bool,
281276
time_passes: bool,
277+
vectorize_loop: bool,
278+
vectorize_slp: bool,
279+
merge_functions: bool,
282280
}
283281

284282
unsafe impl Send for ModuleConfig { }
@@ -301,6 +299,9 @@ impl ModuleConfig {
301299
no_prepopulate_passes: false,
302300
no_builtins: false,
303301
time_passes: false,
302+
vectorize_loop: false,
303+
vectorize_slp: false,
304+
merge_functions: false,
304305
}
305306
}
306307

@@ -309,6 +310,18 @@ impl ModuleConfig {
309310
self.no_prepopulate_passes = sess.opts.cg.no_prepopulate_passes;
310311
self.no_builtins = trans.no_builtins;
311312
self.time_passes = sess.time_passes();
313+
314+
// Copy what clang does by turning on loop vectorization at O2 and
315+
// slp vectorization at O3. Otherwise configure other optimization aspects
316+
// of this pass manager builder.
317+
self.vectorize_loop = !sess.opts.cg.no_vectorize_loops &&
318+
(sess.opts.optimize == config::Default ||
319+
sess.opts.optimize == config::Aggressive);
320+
self.vectorize_slp = !sess.opts.cg.no_vectorize_slp &&
321+
sess.opts.optimize == config::Aggressive;
322+
323+
self.merge_functions = sess.opts.optimize == config::Default ||
324+
sess.opts.optimize == config::Aggressive;
312325
}
313326
}
314327

@@ -448,27 +461,26 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
448461
let pass = CString::new(pass).unwrap();
449462
llvm::LLVMRustAddPass(fpm, pass.as_ptr())
450463
};
451-
if !config.no_verify { assert!(addpass("verify")); }
452464

465+
if !config.no_verify { assert!(addpass("verify")); }
453466
if !config.no_prepopulate_passes {
454467
llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
455468
llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
456-
populate_llvm_passes(fpm, mpm, llmod, opt_level,
457-
config.no_builtins);
469+
populate_llvm_passes(fpm, mpm, llmod, opt_level, &config);
458470
}
459471

460472
for pass in &config.passes {
461-
let pass = CString::new(pass.clone()).unwrap();
462-
if !llvm::LLVMRustAddPass(mpm, pass.as_ptr()) {
463-
cgcx.handler.warn(&format!("unknown pass {:?}, ignoring", pass));
473+
if !addpass(pass) {
474+
cgcx.handler.warn(&format!("unknown pass `{}`, ignoring",
475+
pass));
464476
}
465477
}
466478

467479
for pass in &cgcx.plugin_passes {
468-
let pass = CString::new(pass.clone()).unwrap();
469-
if !llvm::LLVMRustAddPass(mpm, pass.as_ptr()) {
470-
cgcx.handler.err(&format!("a plugin asked for LLVM pass {:?} but LLVM \
471-
does not recognize it", pass));
480+
if !addpass(pass) {
481+
cgcx.handler.err(&format!("a plugin asked for LLVM pass \
482+
`{}` but LLVM does not \
483+
recognize it", pass));
472484
}
473485
}
474486

@@ -520,7 +532,6 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
520532
llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod);
521533
llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
522534
f(cpm);
523-
llvm::LLVMDisposePassManager(cpm);
524535
}
525536

526537
if config.emit_bc {
@@ -537,13 +548,15 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
537548
let out = path2cstr(&out);
538549
with_codegen(tm, llmod, config.no_builtins, |cpm| {
539550
llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr());
551+
llvm::LLVMDisposePassManager(cpm);
540552
})
541553
}
542554

543555
if config.emit_asm {
544556
let path = output_names.with_extension(&format!("{}.s", name_extra));
545557
with_codegen(tm, llmod, config.no_builtins, |cpm| {
546-
write_output_file(cgcx.handler, tm, cpm, llmod, &path, llvm::AssemblyFileType);
558+
write_output_file(cgcx.handler, tm, cpm, llmod, &path,
559+
llvm::AssemblyFileType);
547560
});
548561
}
549562

@@ -1008,25 +1021,16 @@ unsafe fn configure_llvm(sess: &Session) {
10081021
use std::sync::Once;
10091022
static INIT: Once = Once::new();
10101023

1011-
// Copy what clang does by turning on loop vectorization at O2 and
1012-
// slp vectorization at O3
1013-
let vectorize_loop = !sess.opts.cg.no_vectorize_loops &&
1014-
(sess.opts.optimize == config::Default ||
1015-
sess.opts.optimize == config::Aggressive);
1016-
let vectorize_slp = !sess.opts.cg.no_vectorize_slp &&
1017-
sess.opts.optimize == config::Aggressive;
1018-
10191024
let mut llvm_c_strs = Vec::new();
10201025
let mut llvm_args = Vec::new();
1026+
10211027
{
10221028
let mut add = |arg: &str| {
10231029
let s = CString::new(arg).unwrap();
10241030
llvm_args.push(s.as_ptr());
10251031
llvm_c_strs.push(s);
10261032
};
10271033
add("rustc"); // fake program name
1028-
if vectorize_loop { add("-vectorize-loops"); }
1029-
if vectorize_slp { add("-vectorize-slp"); }
10301034
if sess.time_llvm_passes() { add("-time-passes"); }
10311035
if sess.print_llvm_passes() { add("-debug-pass=Structure"); }
10321036

@@ -1084,41 +1088,40 @@ unsafe fn populate_llvm_passes(fpm: llvm::PassManagerRef,
10841088
mpm: llvm::PassManagerRef,
10851089
llmod: ModuleRef,
10861090
opt: llvm::CodeGenOptLevel,
1087-
no_builtins: bool) {
1091+
config: &ModuleConfig) {
10881092
// Create the PassManagerBuilder for LLVM. We configure it with
10891093
// reasonable defaults and prepare it to actually populate the pass
10901094
// manager.
10911095
let builder = llvm::LLVMPassManagerBuilderCreate();
1096+
1097+
llvm::LLVMRustConfigurePassManagerBuilder(builder, opt,
1098+
config.merge_functions,
1099+
config.vectorize_slp,
1100+
config.vectorize_loop);
1101+
1102+
llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod, config.no_builtins);
1103+
1104+
// Here we match what clang does (kinda). For O0 we only inline
1105+
// always-inline functions (but don't add lifetime intrinsics), at O1 we
1106+
// inline with lifetime intrinsics, and O2+ we add an inliner with a
1107+
// thresholds copied from clang.
10921108
match opt {
10931109
llvm::CodeGenLevelNone => {
1094-
// Don't add lifetime intrinsics at O0
10951110
llvm::LLVMRustAddAlwaysInlinePass(builder, false);
10961111
}
10971112
llvm::CodeGenLevelLess => {
10981113
llvm::LLVMRustAddAlwaysInlinePass(builder, true);
10991114
}
1100-
// numeric values copied from clang
11011115
llvm::CodeGenLevelDefault => {
1102-
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder,
1103-
225);
1116+
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 225);
11041117
}
11051118
llvm::CodeGenLevelAggressive => {
1106-
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder,
1107-
275);
1119+
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 275);
11081120
}
11091121
}
1110-
llvm::LLVMPassManagerBuilderSetOptLevel(builder, opt as c_uint);
1111-
llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod, no_builtins);
11121122

11131123
// Use the builder to populate the function/module pass managers.
11141124
llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(builder, fpm);
11151125
llvm::LLVMPassManagerBuilderPopulateModulePassManager(builder, mpm);
11161126
llvm::LLVMPassManagerBuilderDispose(builder);
1117-
1118-
match opt {
1119-
llvm::CodeGenLevelDefault | llvm::CodeGenLevelAggressive => {
1120-
llvm::LLVMRustAddPass(mpm, "mergefunc\0".as_ptr() as *const _);
1121-
}
1122-
_ => {}
1123-
};
11241127
}

src/librustc_trans/trans/attributes.rs

+15
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use libc::{c_uint, c_ulonglong};
1313
use llvm::{self, ValueRef, AttrHelper};
1414
use middle::ty::{self, ClosureTyper};
15+
use session::config::NoDebugInfo;
1516
use syntax::abi;
1617
use syntax::ast;
1718
pub use syntax::attr::InlineAttr;
@@ -106,6 +107,20 @@ pub fn from_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRe
106107
use syntax::attr::*;
107108
inline(llfn, find_inline_attr(Some(ccx.sess().diagnostic()), attrs));
108109

110+
// FIXME: #11906: Omitting frame pointers breaks retrieving the value of a
111+
// parameter.
112+
let no_fp_elim = (ccx.sess().opts.debuginfo != NoDebugInfo) ||
113+
!ccx.sess().target.target.options.eliminate_frame_pointer;
114+
if no_fp_elim {
115+
unsafe {
116+
let attr = "no-frame-pointer-elim\0".as_ptr() as *const _;
117+
let val = "true\0".as_ptr() as *const _;
118+
llvm::LLVMAddFunctionAttrStringValue(llfn,
119+
llvm::FunctionIndex as c_uint,
120+
attr, val);
121+
}
122+
}
123+
109124
for attr in attrs {
110125
if attr.check_name("no_stack_check") {
111126
split_stack(llfn, false);

src/librustc_trans/trans/base.rs

+17-3
Original file line numberDiff line numberDiff line change
@@ -480,9 +480,23 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
480480
}
481481
(_match::Switch, Some(lldiscrim_a)) => {
482482
cx = f(cx, lldiscrim_a, cx.tcx().types.isize);
483-
let unr_cx = fcx.new_temp_block("enum-iter-unr");
484-
Unreachable(unr_cx);
485-
let llswitch = Switch(cx, lldiscrim_a, unr_cx.llbb,
483+
484+
// Create a fall-through basic block for the "else" case of
485+
// the switch instruction we're about to generate. Note that
486+
// we do **not** use an Unreachable instruction here, even
487+
// though most of the time this basic block will never be hit.
488+
//
489+
// When an enum is dropped it's contents are currently
490+
// overwritten to DTOR_DONE, which means the discriminant
491+
// could have changed value to something not within the actual
492+
// range of the discriminant. Currently this function is only
493+
// used for drop glue so in this case we just return quickly
494+
// from the outer function, and any other use case will only
495+
// call this for an already-valid enum in which case the `ret
496+
// void` will never be hit.
497+
let ret_void_cx = fcx.new_temp_block("enum-iter-ret-void");
498+
RetVoid(ret_void_cx, DebugLoc::None);
499+
let llswitch = Switch(cx, lldiscrim_a, ret_void_cx.llbb,
486500
n_variants);
487501
let next_cx = fcx.new_temp_block("enum-iter-next");
488502

src/librustc_trans/trans/debuginfo/metadata.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1673,7 +1673,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
16731673
DIB(cx),
16741674
containing_scope,
16751675
enum_name.as_ptr(),
1676-
UNKNOWN_FILE_METADATA,
1676+
file_metadata,
16771677
UNKNOWN_LINE_NUMBER,
16781678
bytes_to_bits(enum_type_size),
16791679
bytes_to_bits(enum_type_align),

src/librustc_trans/trans/debuginfo/mod.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -484,10 +484,10 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
484484
let param_metadata = unsafe {
485485
llvm::LLVMDIBuilderCreateTemplateTypeParameter(
486486
DIB(cx),
487-
file_metadata,
487+
ptr::null_mut(),
488488
name.as_ptr(),
489489
actual_self_type_metadata,
490-
ptr::null_mut(),
490+
file_metadata,
491491
0,
492492
0)
493493
};
@@ -518,10 +518,10 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
518518
let param_metadata = unsafe {
519519
llvm::LLVMDIBuilderCreateTemplateTypeParameter(
520520
DIB(cx),
521-
file_metadata,
521+
ptr::null_mut(),
522522
name.as_ptr(),
523523
actual_type_metadata,
524-
ptr::null_mut(),
524+
file_metadata,
525525
0,
526526
0)
527527
};
@@ -580,12 +580,14 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
580580
loc.line,
581581
loc.col.to_usize()));
582582
unsafe {
583+
let debug_loc = llvm::LLVMGetCurrentDebugLocation(cx.raw_builder());
583584
let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
584585
DIB(cx),
585586
alloca,
586587
metadata,
587588
address_operations.as_ptr(),
588589
address_operations.len() as c_uint,
590+
debug_loc,
589591
bcx.llbb);
590592

591593
llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr);

src/llvm

Submodule llvm updated 10121 files

src/rustllvm/ExecutionEngineWrapper.cpp

-3
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,6 @@ extern "C" LLVMExecutionEngineRef LLVMBuildExecutionEngine(
8585
std::string error_str;
8686
TargetOptions options;
8787

88-
options.JITEmitDebugInfo = true;
89-
options.NoFramePointerElim = true;
90-
9188
ExecutionEngine *ee =
9289
#if LLVM_VERSION_MINOR >= 6
9390
EngineBuilder(std::unique_ptr<Module>(unwrap(mod)))

0 commit comments

Comments
 (0)