1
Fork 0

Control LLVM's TrapUnreachable feature through rustc's TargetOptions.

This commit is contained in:
Dan Gohman 2017-11-11 07:08:00 -08:00
parent 365c159b80
commit 7b6b764917
4 changed files with 19 additions and 7 deletions

View file

@ -435,6 +435,10 @@ pub struct TargetOptions {
/// Default number of codegen units to use in debug mode /// Default number of codegen units to use in debug mode
pub default_codegen_units: Option<u64>, pub default_codegen_units: Option<u64>,
/// Whether to generate trap instructions in places where optimization would
/// otherwise produce control flow that falls through into unrelated memory.
pub trap_unreachable: bool,
} }
impl Default for TargetOptions { impl Default for TargetOptions {
@ -498,6 +502,7 @@ impl Default for TargetOptions {
stack_probes: false, stack_probes: false,
min_global_align: None, min_global_align: None,
default_codegen_units: None, default_codegen_units: None,
trap_unreachable: true,
} }
} }
} }
@ -739,6 +744,7 @@ impl Target {
key!(stack_probes, bool); key!(stack_probes, bool);
key!(min_global_align, Option<u64>); key!(min_global_align, Option<u64>);
key!(default_codegen_units, Option<u64>); key!(default_codegen_units, Option<u64>);
key!(trap_unreachable, bool);
if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) { if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) {
for name in array.iter().filter_map(|abi| abi.as_string()) { for name in array.iter().filter_map(|abi| abi.as_string()) {
@ -932,6 +938,7 @@ impl ToJson for Target {
target_option_val!(stack_probes); target_option_val!(stack_probes);
target_option_val!(min_global_align); target_option_val!(min_global_align);
target_option_val!(default_codegen_units); target_option_val!(default_codegen_units);
target_option_val!(trap_unreachable);
if default.abi_blacklist != self.options.abi_blacklist { if default.abi_blacklist != self.options.abi_blacklist {
d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter() d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter()

View file

@ -1605,7 +1605,8 @@ extern "C" {
UseSoftFP: bool, UseSoftFP: bool,
PositionIndependentExecutable: bool, PositionIndependentExecutable: bool,
FunctionSections: bool, FunctionSections: bool,
DataSections: bool) DataSections: bool,
TrapUnreachable: bool)
-> TargetMachineRef; -> TargetMachineRef;
pub fn LLVMRustDisposeTargetMachine(T: TargetMachineRef); pub fn LLVMRustDisposeTargetMachine(T: TargetMachineRef);
pub fn LLVMRustAddAnalysisPasses(T: TargetMachineRef, PM: PassManagerRef, M: ModuleRef); pub fn LLVMRustAddAnalysisPasses(T: TargetMachineRef, PM: PassManagerRef, M: ModuleRef);

View file

@ -196,6 +196,7 @@ pub fn target_machine_factory(sess: &Session)
let cpu = CString::new(cpu.as_bytes()).unwrap(); let cpu = CString::new(cpu.as_bytes()).unwrap();
let features = CString::new(target_feature(sess).as_bytes()).unwrap(); let features = CString::new(target_feature(sess).as_bytes()).unwrap();
let is_pie_binary = is_pie_binary(sess); let is_pie_binary = is_pie_binary(sess);
let trap_unreachable = sess.target.target.options.trap_unreachable;
Arc::new(move || { Arc::new(move || {
let tm = unsafe { let tm = unsafe {
@ -208,6 +209,7 @@ pub fn target_machine_factory(sess: &Session)
is_pie_binary, is_pie_binary,
ffunction_sections, ffunction_sections,
fdata_sections, fdata_sections,
trap_unreachable,
) )
}; };

View file

@ -366,7 +366,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
LLVMRustCodeModel RustCM, LLVMRustRelocMode RustReloc, LLVMRustCodeModel RustCM, LLVMRustRelocMode RustReloc,
LLVMRustCodeGenOptLevel RustOptLevel, bool UseSoftFloat, LLVMRustCodeGenOptLevel RustOptLevel, bool UseSoftFloat,
bool PositionIndependentExecutable, bool FunctionSections, bool PositionIndependentExecutable, bool FunctionSections,
bool DataSections) { bool DataSections, bool TrapUnreachable) {
auto CM = fromRust(RustCM); auto CM = fromRust(RustCM);
auto OptLevel = fromRust(RustOptLevel); auto OptLevel = fromRust(RustOptLevel);
@ -398,11 +398,13 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
Options.DataSections = DataSections; Options.DataSections = DataSections;
Options.FunctionSections = FunctionSections; Options.FunctionSections = FunctionSections;
if (TrapUnreachable) {
// Tell LLVM to translate `unreachable` into an explicit trap instruction. // Tell LLVM to translate `unreachable` into an explicit trap instruction.
// This limits the extent of possible undefined behavior in some cases, as it // This limits the extent of possible undefined behavior in some cases, as
// prevents control flow from "falling through" into whatever code happens to // it prevents control flow from "falling through" into whatever code
// be laid out next in memory. // happens to be laid out next in memory.
Options.TrapUnreachable = true; Options.TrapUnreachable = true;
}
TargetMachine *TM = TheTarget->createTargetMachine( TargetMachine *TM = TheTarget->createTargetMachine(
Trip.getTriple(), RealCPU, Feature, Options, RM, CM, OptLevel); Trip.getTriple(), RealCPU, Feature, Options, RM, CM, OptLevel);