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:
bors 2013-08-11 07:29:07 -07:00
commit f08851e31a
5 changed files with 46 additions and 15 deletions

View File

@ -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)

View File

@ -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
}

View File

@ -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) => {

View File

@ -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);
}

View File

@ -613,3 +613,4 @@ LLVMDIBuilderInsertDeclareBefore
LLVMDIBuilderCreateEnumerator
LLVMDIBuilderCreateEnumerationType
LLVMDIBuilderCreateUnionType
LLVMSetUnnamedAddr