Skip to content

Commit f08851e

Browse files
committed
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!
2 parents 45da2a5 + 2f3fde6 commit f08851e

File tree

5 files changed

+46
-15
lines changed

5 files changed

+46
-15
lines changed

src/librustc/lib/llvm.rs

+9
Original file line numberDiff line numberDiff line change
@@ -2082,6 +2082,9 @@ pub mod llvm {
20822082
Elements: ValueRef,
20832083
RunTimeLang: c_uint)
20842084
-> ValueRef;
2085+
2086+
#[fast_ffi]
2087+
pub fn LLVMSetUnnamedAddr(GlobalVar: ValueRef, UnnamedAddr: Bool);
20852088
}
20862089
}
20872090

@@ -2101,6 +2104,12 @@ pub fn SetLinkage(Global: ValueRef, Link: Linkage) {
21012104
}
21022105
}
21032106

2107+
pub fn SetUnnamedAddr(Global: ValueRef, Unnamed: bool) {
2108+
unsafe {
2109+
llvm::LLVMSetUnnamedAddr(Global, Unnamed as Bool);
2110+
}
2111+
}
2112+
21042113
pub fn ConstICmp(Pred: IntPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef {
21052114
unsafe {
21062115
llvm::LLVMConstICmp(Pred as c_ushort, V1, V2)

src/librustc/middle/trans/base.rs

+21-13
Original file line numberDiff line numberDiff line change
@@ -2180,19 +2180,18 @@ pub fn trans_item(ccx: @mut CrateContext, item: &ast::item) {
21802180
}
21812181
ast::item_static(_, m, expr) => {
21822182
consts::trans_const(ccx, m, item.id);
2183-
// Do static_assert checking. It can't really be done much earlier because we need to get
2184-
// the value of the bool out of LLVM
2185-
for attr in item.attrs.iter() {
2186-
if "static_assert" == attr.name() {
2187-
if m == ast::m_mutbl {
2188-
ccx.sess.span_fatal(expr.span,
2189-
"cannot have static_assert on a mutable static");
2190-
}
2191-
let v = ccx.const_values.get_copy(&item.id);
2192-
unsafe {
2193-
if !(llvm::LLVMConstIntGetZExtValue(v) as bool) {
2194-
ccx.sess.span_fatal(expr.span, "static assertion failed");
2195-
}
2183+
// Do static_assert checking. It can't really be done much earlier
2184+
// because we need to get the value of the bool out of LLVM
2185+
if attr::contains_name(item.attrs, "static_assert") {
2186+
if m == ast::m_mutbl {
2187+
ccx.sess.span_fatal(expr.span,
2188+
"cannot have static_assert on a mutable \
2189+
static");
2190+
}
2191+
let v = ccx.const_values.get_copy(&item.id);
2192+
unsafe {
2193+
if !(llvm::LLVMConstIntGetZExtValue(v) as bool) {
2194+
ccx.sess.span_fatal(expr.span, "static assertion failed");
21962195
}
21972196
}
21982197
}
@@ -2452,6 +2451,15 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::NodeId) -> ValueRef {
24522451
llvm::LLVMAddGlobal(ccx.llmod, llty, buf)
24532452
};
24542453

2454+
// Apply the `unnamed_addr` attribute if
2455+
// requested
2456+
if attr::contains_name(i.attrs,
2457+
"address_insignificant"){
2458+
lib::llvm::SetUnnamedAddr(g, true);
2459+
lib::llvm::SetLinkage(g,
2460+
lib::llvm::InternalLinkage);
2461+
}
2462+
24552463
ccx.item_symbols.insert(i.id, sym);
24562464
g
24572465
}

src/libsyntax/ext/ifmt.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,12 @@ impl Context {
429429
let st = ast::item_static(ty, ast::m_imm, method);
430430
let static_name = self.ecx.ident_of(fmt!("__static_method_%u",
431431
self.method_statics.len()));
432-
let item = self.ecx.item(sp, static_name, ~[], st);
432+
// Flag these statics as `address_insignificant` so LLVM can
433+
// merge duplicate globals as much as possible (which we're
434+
// generating a whole lot of).
435+
let unnamed = self.ecx.meta_word(self.fmtsp, @"address_insignificant");
436+
let unnamed = self.ecx.attribute(self.fmtsp, unnamed);
437+
let item = self.ecx.item(sp, static_name, ~[unnamed], st);
433438
self.method_statics.push(item);
434439
self.ecx.expr_ident(sp, static_name)
435440
};
@@ -550,7 +555,10 @@ impl Context {
550555
let ty = self.ecx.ty(self.fmtsp, ty);
551556
let st = ast::item_static(ty, ast::m_imm, fmt);
552557
let static_name = self.ecx.ident_of("__static_fmtstr");
553-
let item = self.ecx.item(self.fmtsp, static_name, ~[], st);
558+
// see above comment for `address_insignificant` and why we do it
559+
let unnamed = self.ecx.meta_word(self.fmtsp, @"address_insignificant");
560+
let unnamed = self.ecx.attribute(self.fmtsp, unnamed);
561+
let item = self.ecx.item(self.fmtsp, static_name, ~[unnamed], st);
554562
let decl = respan(self.fmtsp, ast::decl_item(item));
555563
lets.push(@respan(self.fmtsp, ast::stmt_decl(@decl, self.ecx.next_id())));
556564

@@ -613,6 +621,7 @@ impl Context {
613621
if ty == Unknown {
614622
ty = Known(@"?");
615623
}
624+
616625
let argptr = self.ecx.expr_addr_of(sp, self.ecx.expr_ident(sp, ident));
617626
match ty {
618627
Known(tyname) => {

src/rustllvm/RustWrapper.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -833,3 +833,7 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateUnionType(
833833
unwrapDI<DIArray>(Elements),
834834
RunTimeLang));
835835
}
836+
837+
extern "C" void LLVMSetUnnamedAddr(LLVMValueRef Value, LLVMBool Unnamed) {
838+
unwrap<GlobalValue>(Value)->setUnnamedAddr(Unnamed);
839+
}

src/rustllvm/rustllvm.def.in

+1
Original file line numberDiff line numberDiff line change
@@ -613,3 +613,4 @@ LLVMDIBuilderInsertDeclareBefore
613613
LLVMDIBuilderCreateEnumerator
614614
LLVMDIBuilderCreateEnumerationType
615615
LLVMDIBuilderCreateUnionType
616+
LLVMSetUnnamedAddr

0 commit comments

Comments
 (0)