auto merge of #8421 : alexcrichton/rust/unnamed-addr, r=thestinger
This can be applied to statics and it will indicate that LLVM will attempt to merge the constant in .data with other statics. I have preliminarily applied this to all of the statics generated by the new `ifmt!` syntax extension. I compiled a file with 1000 calls to `ifmt!` and a separate file with 1000 calls to `fmt!` to compare the sizes, and the results were: ``` fmt 310k ifmt (before) 529k ifmt (after) 202k ``` This now means that ifmt! is both faster and smaller than fmt!, yay!
This commit is contained in:
commit
f08851e31a
@ -2082,6 +2082,9 @@ pub mod llvm {
|
||||
Elements: ValueRef,
|
||||
RunTimeLang: c_uint)
|
||||
-> ValueRef;
|
||||
|
||||
#[fast_ffi]
|
||||
pub fn LLVMSetUnnamedAddr(GlobalVar: ValueRef, UnnamedAddr: Bool);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2101,6 +2104,12 @@ pub fn SetLinkage(Global: ValueRef, Link: Linkage) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn SetUnnamedAddr(Global: ValueRef, Unnamed: bool) {
|
||||
unsafe {
|
||||
llvm::LLVMSetUnnamedAddr(Global, Unnamed as Bool);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ConstICmp(Pred: IntPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef {
|
||||
unsafe {
|
||||
llvm::LLVMConstICmp(Pred as c_ushort, V1, V2)
|
||||
|
@ -2180,19 +2180,18 @@ pub fn trans_item(ccx: @mut CrateContext, item: &ast::item) {
|
||||
}
|
||||
ast::item_static(_, m, expr) => {
|
||||
consts::trans_const(ccx, m, item.id);
|
||||
// Do static_assert checking. It can't really be done much earlier because we need to get
|
||||
// the value of the bool out of LLVM
|
||||
for attr in item.attrs.iter() {
|
||||
if "static_assert" == attr.name() {
|
||||
if m == ast::m_mutbl {
|
||||
ccx.sess.span_fatal(expr.span,
|
||||
"cannot have static_assert on a mutable static");
|
||||
}
|
||||
let v = ccx.const_values.get_copy(&item.id);
|
||||
unsafe {
|
||||
if !(llvm::LLVMConstIntGetZExtValue(v) as bool) {
|
||||
ccx.sess.span_fatal(expr.span, "static assertion failed");
|
||||
}
|
||||
// Do static_assert checking. It can't really be done much earlier
|
||||
// because we need to get the value of the bool out of LLVM
|
||||
if attr::contains_name(item.attrs, "static_assert") {
|
||||
if m == ast::m_mutbl {
|
||||
ccx.sess.span_fatal(expr.span,
|
||||
"cannot have static_assert on a mutable \
|
||||
static");
|
||||
}
|
||||
let v = ccx.const_values.get_copy(&item.id);
|
||||
unsafe {
|
||||
if !(llvm::LLVMConstIntGetZExtValue(v) as bool) {
|
||||
ccx.sess.span_fatal(expr.span, "static assertion failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2452,6 +2451,15 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::NodeId) -> ValueRef {
|
||||
llvm::LLVMAddGlobal(ccx.llmod, llty, buf)
|
||||
};
|
||||
|
||||
// Apply the `unnamed_addr` attribute if
|
||||
// requested
|
||||
if attr::contains_name(i.attrs,
|
||||
"address_insignificant"){
|
||||
lib::llvm::SetUnnamedAddr(g, true);
|
||||
lib::llvm::SetLinkage(g,
|
||||
lib::llvm::InternalLinkage);
|
||||
}
|
||||
|
||||
ccx.item_symbols.insert(i.id, sym);
|
||||
g
|
||||
}
|
||||
|
@ -429,7 +429,12 @@ impl Context {
|
||||
let st = ast::item_static(ty, ast::m_imm, method);
|
||||
let static_name = self.ecx.ident_of(fmt!("__static_method_%u",
|
||||
self.method_statics.len()));
|
||||
let item = self.ecx.item(sp, static_name, ~[], st);
|
||||
// Flag these statics as `address_insignificant` so LLVM can
|
||||
// merge duplicate globals as much as possible (which we're
|
||||
// generating a whole lot of).
|
||||
let unnamed = self.ecx.meta_word(self.fmtsp, @"address_insignificant");
|
||||
let unnamed = self.ecx.attribute(self.fmtsp, unnamed);
|
||||
let item = self.ecx.item(sp, static_name, ~[unnamed], st);
|
||||
self.method_statics.push(item);
|
||||
self.ecx.expr_ident(sp, static_name)
|
||||
};
|
||||
@ -550,7 +555,10 @@ impl Context {
|
||||
let ty = self.ecx.ty(self.fmtsp, ty);
|
||||
let st = ast::item_static(ty, ast::m_imm, fmt);
|
||||
let static_name = self.ecx.ident_of("__static_fmtstr");
|
||||
let item = self.ecx.item(self.fmtsp, static_name, ~[], st);
|
||||
// see above comment for `address_insignificant` and why we do it
|
||||
let unnamed = self.ecx.meta_word(self.fmtsp, @"address_insignificant");
|
||||
let unnamed = self.ecx.attribute(self.fmtsp, unnamed);
|
||||
let item = self.ecx.item(self.fmtsp, static_name, ~[unnamed], st);
|
||||
let decl = respan(self.fmtsp, ast::decl_item(item));
|
||||
lets.push(@respan(self.fmtsp, ast::stmt_decl(@decl, self.ecx.next_id())));
|
||||
|
||||
@ -613,6 +621,7 @@ impl Context {
|
||||
if ty == Unknown {
|
||||
ty = Known(@"?");
|
||||
}
|
||||
|
||||
let argptr = self.ecx.expr_addr_of(sp, self.ecx.expr_ident(sp, ident));
|
||||
match ty {
|
||||
Known(tyname) => {
|
||||
|
@ -833,3 +833,7 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateUnionType(
|
||||
unwrapDI<DIArray>(Elements),
|
||||
RunTimeLang));
|
||||
}
|
||||
|
||||
extern "C" void LLVMSetUnnamedAddr(LLVMValueRef Value, LLVMBool Unnamed) {
|
||||
unwrap<GlobalValue>(Value)->setUnnamedAddr(Unnamed);
|
||||
}
|
||||
|
@ -613,3 +613,4 @@ LLVMDIBuilderInsertDeclareBefore
|
||||
LLVMDIBuilderCreateEnumerator
|
||||
LLVMDIBuilderCreateEnumerationType
|
||||
LLVMDIBuilderCreateUnionType
|
||||
LLVMSetUnnamedAddr
|
||||
|
Loading…
x
Reference in New Issue
Block a user