Skip to content

New codegen option "no-split-stack" #14394

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 23 additions & 21 deletions src/librustc/driver/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ pub fn debugging_opts_map() -> Vec<(&'static str, &'static str, u64)> {
/// its respective field in the struct. There are a few hand-written parsers for
/// parsing specific types of values in this module.
macro_rules! cgoptions(
($($opt:ident : $t:ty = ($init:expr, $parse:ident, $desc:expr)),* ,) =>
($($opt:ident : $t:ty = ($init:expr, $parse:ident, $desc:expr, $is_public:expr)),* ,) =>
(
#[deriving(Clone)]
pub struct CodegenOptions { $(pub $opt: $t),* }
Expand All @@ -231,8 +231,8 @@ macro_rules! cgoptions(

pub type CodegenSetter = fn(&mut CodegenOptions, v: Option<&str>) -> bool;
pub static CG_OPTIONS: &'static [(&'static str, CodegenSetter,
&'static str)] =
&[ $( (stringify!($opt), cgsetters::$opt, $desc) ),* ];
&'static str, bool)] =
&[ $( (stringify!($opt), cgsetters::$opt, $desc, $is_public) ),* ];

mod cgsetters {
use super::CodegenOptions;
Expand Down Expand Up @@ -282,37 +282,39 @@ macro_rules! cgoptions(

cgoptions!(
ar: Option<StrBuf> = (None, parse_opt_string,
"tool to assemble archives with"),
"tool to assemble archives with", true),
linker: Option<StrBuf> = (None, parse_opt_string,
"system linker to link outputs with"),
"system linker to link outputs with", true),
link_args: Vec<StrBuf> = (Vec::new(), parse_list,
"extra arguments to pass to the linker (space separated)"),
"extra arguments to pass to the linker (space separated)", true),
target_cpu: StrBuf = ("generic".to_strbuf(), parse_string,
"select target processor (llc -mcpu=help for details)"),
"select target processor (llc -mcpu=help for details)", true),
target_feature: StrBuf = ("".to_strbuf(), parse_string,
"target specific attributes (llc -mattr=help for details)"),
"target specific attributes (llc -mattr=help for details)", true),
passes: Vec<StrBuf> = (Vec::new(), parse_list,
"a list of extra LLVM passes to run (space separated)"),
"a list of extra LLVM passes to run (space separated)", true),
llvm_args: Vec<StrBuf> = (Vec::new(), parse_list,
"a list of arguments to pass to llvm (space separated)"),
"a list of arguments to pass to llvm (space separated)", true),
save_temps: bool = (false, parse_bool,
"save all temporary output files during compilation"),
"save all temporary output files during compilation", true),
no_rpath: bool = (false, parse_bool,
"disables setting the rpath in libs/exes"),
"disables setting the rpath in libs/exes", true),
no_prepopulate_passes: bool = (false, parse_bool,
"don't pre-populate the pass manager with a list of passes"),
"don't pre-populate the pass manager with a list of passes", true),
no_vectorize_loops: bool = (false, parse_bool,
"don't run the loop vectorization optimization passes"),
"don't run the loop vectorization optimization passes", true),
no_vectorize_slp: bool = (false, parse_bool,
"don't run LLVM's SLP vectorization pass"),
"don't run LLVM's SLP vectorization pass", true),
soft_float: bool = (false, parse_bool,
"generate software floating point library calls"),
"generate software floating point library calls", true),
prefer_dynamic: bool = (false, parse_bool,
"prefer dynamic linking to static linking"),
"prefer dynamic linking to static linking", true),
no_integrated_as: bool = (false, parse_bool,
"use an external assembler rather than LLVM's integrated one"),
"use an external assembler rather than LLVM's integrated one", true),
relocation_model: StrBuf = ("pic".to_strbuf(), parse_string,
"choose the relocation model to use (llc -relocation-model for details)"),
"choose the relocation model to use (llc -relocation-model for details)", true),
no_split_stack: bool = (false, parse_bool,
"disable segmented stack support", false),
)

pub fn build_codegen_options(matches: &getopts::Matches) -> CodegenOptions
Expand All @@ -324,8 +326,8 @@ pub fn build_codegen_options(matches: &getopts::Matches) -> CodegenOptions
let value = iter.next();
let option_to_lookup = key.replace("-", "_");
let mut found = false;
for &(candidate, setter, _) in CG_OPTIONS.iter() {
if option_to_lookup.as_slice() != candidate { continue }
for &(candidate, setter, _, is_public) in CG_OPTIONS.iter() {
if option_to_lookup.as_slice() != candidate || !is_public { continue }
if !setter(&mut cg, value) {
match value {
Some(..) => {
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/driver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,8 @@ fn describe_debug_flags() {
fn describe_codegen_flags() {
println!("\nAvailable codegen options:\n");
let mut cg = config::basic_codegen_options();
for &(name, parser, desc) in config::CG_OPTIONS.iter() {
for &(name, parser, desc, is_public) in config::CG_OPTIONS.iter() {
if !is_public { continue }
// we invoke the parser function on `None` to see if this option needs
// an argument or not.
let (width, extra) = if parser(&mut cg, None) {
Expand Down
25 changes: 14 additions & 11 deletions src/librustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,11 +165,11 @@ impl<'a> Drop for StatRecorder<'a> {
}

// only use this for foreign function ABIs and glue, use `decl_rust_fn` for Rust functions
fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv,
fn decl_fn(ccx: &CrateContext, name: &str, cc: lib::llvm::CallConv,
ty: Type, output: ty::t) -> ValueRef {
let llfn: ValueRef = name.with_c_str(|buf| {
unsafe {
llvm::LLVMGetOrInsertFunction(llmod, buf, ty.to_ref())
llvm::LLVMGetOrInsertFunction(ccx.llmod, buf, ty.to_ref())
}
});

Expand All @@ -193,22 +193,25 @@ fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv,
lib::llvm::SetFunctionCallConv(llfn, cc);
// Function addresses in Rust are never significant, allowing functions to be merged.
lib::llvm::SetUnnamedAddr(llfn, true);
set_split_stack(llfn);

if !ccx.sess().opts.cg.no_split_stack {
set_split_stack(llfn);
}

llfn
}

// only use this for foreign function ABIs and glue, use `decl_rust_fn` for Rust functions
pub fn decl_cdecl_fn(llmod: ModuleRef,
pub fn decl_cdecl_fn(ccx: &CrateContext,
name: &str,
ty: Type,
output: ty::t) -> ValueRef {
decl_fn(llmod, name, lib::llvm::CCallConv, ty, output)
decl_fn(ccx, name, lib::llvm::CCallConv, ty, output)
}

// only use this for foreign function ABIs and glue, use `get_extern_rust_fn` for Rust functions
pub fn get_extern_fn(externs: &mut ExternMap,
llmod: ModuleRef,
ccx: &CrateContext,
name: &str,
cc: lib::llvm::CallConv,
ty: Type,
Expand All @@ -218,7 +221,7 @@ pub fn get_extern_fn(externs: &mut ExternMap,
Some(n) => return *n,
None => {}
}
let f = decl_fn(llmod, name, cc, ty, output);
let f = decl_fn(ccx, name, cc, ty, output);
externs.insert(name.to_strbuf(), f);
f
}
Expand Down Expand Up @@ -246,7 +249,7 @@ pub fn decl_rust_fn(ccx: &CrateContext, has_env: bool,
use middle::ty::{BrAnon, ReLateBound};

let llfty = type_of_rust_fn(ccx, has_env, inputs, output);
let llfn = decl_cdecl_fn(ccx.llmod, name, llfty, output);
let llfn = decl_cdecl_fn(ccx, name, llfty, output);

let uses_outptr = type_of::return_uses_outptr(ccx, output);
let offset = if uses_outptr { 1 } else { 0 };
Expand Down Expand Up @@ -512,7 +515,7 @@ pub fn get_res_dtor(ccx: &CrateContext,
let llty = type_of_dtor(ccx, class_ty);

get_extern_fn(&mut *ccx.externs.borrow_mut(),
ccx.llmod,
ccx,
name.as_slice(),
lib::llvm::CCallConv,
llty,
Expand Down Expand Up @@ -1735,7 +1738,7 @@ pub fn register_fn_llvmty(ccx: &CrateContext,
output: ty::t) -> ValueRef {
debug!("register_fn_llvmty id={} sym={}", node_id, sym);

let llfn = decl_fn(ccx.llmod, sym.as_slice(), cc, fn_ty, output);
let llfn = decl_fn(ccx, sym.as_slice(), cc, fn_ty, output);
finish_register_fn(ccx, sp, sym, node_id, llfn);
llfn
}
Expand Down Expand Up @@ -1767,7 +1770,7 @@ pub fn create_entry_wrapper(ccx: &CrateContext,
let llfty = Type::func([ccx.int_type, Type::i8p(ccx).ptr_to()],
&ccx.int_type);

let llfn = decl_cdecl_fn(ccx.llmod, "main", llfty, ty::mk_nil());
let llfn = decl_cdecl_fn(ccx, "main", llfty, ty::mk_nil());
let llbb = "top".with_c_str(|buf| {
unsafe {
llvm::LLVMAppendBasicBlockInContext(ccx.llcx, llfn, buf)
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/cleanup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,7 @@ impl<'a> CleanupHelperMethods<'a> for FunctionContext<'a> {
Some(llpersonality) => llpersonality,
None => {
let fty = Type::variadic_func(&[], &Type::i32(self.ccx));
let f = base::decl_cdecl_fn(self.ccx.llmod,
let f = base::decl_cdecl_fn(self.ccx,
"rust_eh_personality",
fty,
ty::mk_i32());
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/middle/trans/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,14 +279,14 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
macro_rules! ifn (
($name:expr fn() -> $ret:expr) => (
if *key == $name {
let f = base::decl_cdecl_fn(ccx.llmod, $name, Type::func([], &$ret), ty::mk_nil());
let f = base::decl_cdecl_fn(ccx, $name, Type::func([], &$ret), ty::mk_nil());
ccx.intrinsics.borrow_mut().insert($name, f.clone());
return Some(f);
}
);
($name:expr fn($($arg:expr),*) -> $ret:expr) => (
if *key == $name {
let f = base::decl_cdecl_fn(ccx.llmod, $name,
let f = base::decl_cdecl_fn(ccx, $name,
Type::func([$($arg),*], &$ret), ty::mk_nil());
ccx.intrinsics.borrow_mut().insert($name, f.clone());
return Some(f);
Expand Down Expand Up @@ -418,7 +418,7 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
// The `if key == $name` is already in ifn!
ifn!($name fn($($arg),*) -> $ret);
} else if *key == $name {
let f = base::decl_cdecl_fn(ccx.llmod, stringify!($cname),
let f = base::decl_cdecl_fn(ccx, stringify!($cname),
Type::func([$($arg),*], &$ret),
ty::mk_nil());
ccx.intrinsics.borrow_mut().insert($name, f.clone());
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/foreign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ pub fn register_foreign_item_fn(ccx: &CrateContext, abi: Abi, fty: ty::t,
let llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys);

let llfn = base::get_extern_fn(&mut *ccx.externs.borrow_mut(),
ccx.llmod,
ccx,
name,
cc,
llfn_ty,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/glue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ fn declare_generic_glue(ccx: &CrateContext, t: ty::t, llfnty: Type,
t,
format!("glue_{}", name).as_slice());
debug!("{} is for type {}", fn_nm, ppaux::ty_to_str(ccx.tcx(), t));
let llfn = decl_cdecl_fn(ccx.llmod,
let llfn = decl_cdecl_fn(ccx,
fn_nm.as_slice(),
llfnty,
ty::mk_nil());
Expand Down