summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/BitCodeFormat.html7
-rw-r--r--docs/LangRef.html13
-rw-r--r--include/llvm/GlobalValue.h7
-rw-r--r--lib/AsmParser/LLLexer.cpp1
-rw-r--r--lib/AsmParser/LLParser.cpp16
-rw-r--r--lib/AsmParser/LLToken.h1
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.cpp14
-rw-r--r--lib/Bitcode/Writer/BitcodeWriter.cpp10
-rw-r--r--lib/VMCore/AsmWriter.cpp3
-rw-r--r--lib/VMCore/Verifier.cpp1
-rw-r--r--test/Assembler/unnamed-addr.ll18
-rw-r--r--unittests/VMCore/VerifierTest.cpp20
12 files changed, 98 insertions, 13 deletions
diff --git a/docs/BitCodeFormat.html b/docs/BitCodeFormat.html
index d8ddc2b6b2..0b8747c261 100644
--- a/docs/BitCodeFormat.html
+++ b/docs/BitCodeFormat.html
@@ -922,6 +922,9 @@ encoding of the visibility of this variable:
<li><i>threadlocal</i>: If present and non-zero, indicates that the variable
is <tt>thread_local</tt></li>
+<li><i>unnamed_addr</i>: If present and non-zero, indicates that the variable
+has <tt>unnamed_addr<tt></li>
+
</ul>
</div>
@@ -975,6 +978,10 @@ entries.</li>
<li><i>gc</i>: If present and nonzero, the 1-based garbage collector
index in the table of
<a href="#MODULE_CODE_GCNAME">MODULE_CODE_GCNAME</a> entries.</li>
+
+<li><i>unnamed_addr</i>: If present and non-zero, indicates that the function
+has <tt>unnamed_addr<tt></li>
+
</ul>
</div>
diff --git a/docs/LangRef.html b/docs/LangRef.html
index 21144125b0..2121fc6740 100644
--- a/docs/LangRef.html
+++ b/docs/LangRef.html
@@ -846,6 +846,10 @@ define i32 @main() { <i>; i32()* </i>&nbsp;
region of memory, and all memory objects in LLVM are accessed through
pointers.</p>
+<p>Global variables can be marked with <tt>unnamed_addr</tt> which indicates
+ that the address is not significant, only the content. Constants marked
+ like this can be merged if they have the same content.</p>
+
<p>A global variable may be declared to reside in a target-specific numbered
address space. For targets that support them, address spaces may affect how
optimizations are performed and/or what target instructions are used to
@@ -885,7 +889,8 @@ define i32 @main() { <i>; i32()* </i>&nbsp;
<p>LLVM function definitions consist of the "<tt>define</tt>" keyword, an
optional <a href="#linkage">linkage type</a>, an optional
<a href="#visibility">visibility style</a>, an optional
- <a href="#callingconv">calling convention</a>, a return type, an optional
+ <a href="#callingconv">calling convention</a>,
+ an optional <tt>unnamed_addr</tt> attribute, a return type, an optional
<a href="#paramattrs">parameter attribute</a> for the return type, a function
name, a (possibly empty) argument list (each with optional
<a href="#paramattrs">parameter attributes</a>), optional
@@ -896,7 +901,8 @@ define i32 @main() { <i>; i32()* </i>&nbsp;
<p>LLVM function declarations consist of the "<tt>declare</tt>" keyword, an
optional <a href="#linkage">linkage type</a>, an optional
<a href="#visibility">visibility style</a>, an optional
- <a href="#callingconv">calling convention</a>, a return type, an optional
+ <a href="#callingconv">calling convention</a>,
+ an optional <tt>unnamed_addr</tt> attribute, a return type, an optional
<a href="#paramattrs">parameter attribute</a> for the return type, a function
name, a possibly empty list of arguments, an optional alignment, and an
optional <a href="#gc">garbage collector name</a>.</p>
@@ -922,6 +928,9 @@ define i32 @main() { <i>; i32()* </i>&nbsp;
specified, the function is forced to have at least that much alignment. All
alignments must be a power of 2.</p>
+<p>If the <tt>unnamed_addr</tt> attribute is given, the address is know to not
+ be significant and two identical functions can be merged</p>.
+
<h5>Syntax:</h5>
<pre class="doc_code">
define [<a href="#linkage">linkage</a>] [<a href="#visibility">visibility</a>]
diff --git a/include/llvm/GlobalValue.h b/include/llvm/GlobalValue.h
index 68cb8e2604..ccadc1c603 100644
--- a/include/llvm/GlobalValue.h
+++ b/include/llvm/GlobalValue.h
@@ -60,7 +60,8 @@ protected:
GlobalValue(const Type *ty, ValueTy vty, Use *Ops, unsigned NumOps,
LinkageTypes linkage, const Twine &Name)
: Constant(ty, vty, Ops, NumOps), Parent(0),
- Linkage(linkage), Visibility(DefaultVisibility), Alignment(0) {
+ Linkage(linkage), Visibility(DefaultVisibility), Alignment(0),
+ UnnamedAddr(0) {
setName(Name);
}
@@ -70,6 +71,7 @@ protected:
LinkageTypes Linkage : 5; // The linkage of this global
unsigned Visibility : 2; // The visibility style of this global
unsigned Alignment : 16; // Alignment of this symbol, must be power of two
+ unsigned UnnamedAddr : 1; // This value's address is not significant
std::string Section; // Section to emit this into, empty mean default
public:
~GlobalValue() {
@@ -81,6 +83,9 @@ public:
}
void setAlignment(unsigned Align);
+ bool hasUnnamedAddr() const { return UnnamedAddr; }
+ void setUnnamedAddr(bool Val) { UnnamedAddr = Val; }
+
VisibilityTypes getVisibility() const { return VisibilityTypes(Visibility); }
bool hasDefaultVisibility() const { return Visibility == DefaultVisibility; }
bool hasHiddenVisibility() const { return Visibility == HiddenVisibility; }
diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp
index eb5b0f9c1d..857fa1ef62 100644
--- a/lib/AsmParser/LLLexer.cpp
+++ b/lib/AsmParser/LLLexer.cpp
@@ -509,6 +509,7 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(default);
KEYWORD(hidden);
KEYWORD(protected);
+ KEYWORD(unnamed_addr);
KEYWORD(extern_weak);
KEYWORD(external);
KEYWORD(thread_local);
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp
index 68f79465be..5c33d65c05 100644
--- a/lib/AsmParser/LLParser.cpp
+++ b/lib/AsmParser/LLParser.cpp
@@ -194,7 +194,8 @@ bool LLParser::ParseTopLevelEntities() {
// The Global variable production with no name can have many different
// optional leading prefixes, the production is:
// GlobalVar ::= OptionalLinkage OptionalVisibility OptionalThreadLocal
- // OptionalAddrSpace ('constant'|'global') ...
+ // OptionalAddrSpace OptionalUnNammedAddr
+ // ('constant'|'global') ...
case lltok::kw_private: // OptionalLinkage
case lltok::kw_linker_private: // OptionalLinkage
case lltok::kw_linker_private_weak: // OptionalLinkage
@@ -682,9 +683,9 @@ bool LLParser::ParseAlias(const std::string &Name, LocTy NameLoc,
/// ParseGlobal
/// ::= GlobalVar '=' OptionalLinkage OptionalVisibility OptionalThreadLocal
-/// OptionalAddrSpace GlobalType Type Const
+/// OptionalAddrSpace OptionalUnNammedAddr GlobalType Type Const
/// ::= OptionalLinkage OptionalVisibility OptionalThreadLocal
-/// OptionalAddrSpace GlobalType Type Const
+/// OptionalAddrSpace OptionalUnNammedAddr GlobalType Type Const
///
/// Everything through visibility has been parsed already.
///
@@ -692,12 +693,13 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc,
unsigned Linkage, bool HasLinkage,
unsigned Visibility) {
unsigned AddrSpace;
- bool ThreadLocal, IsConstant;
+ bool ThreadLocal, IsConstant, UnnamedAddr;
LocTy TyLoc;
PATypeHolder Ty(Type::getVoidTy(Context));
if (ParseOptionalToken(lltok::kw_thread_local, ThreadLocal) ||
ParseOptionalAddrSpace(AddrSpace) ||
+ ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr) ||
ParseGlobalType(IsConstant) ||
ParseType(Ty, TyLoc))
return true;
@@ -755,6 +757,7 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc,
GV->setLinkage((GlobalValue::LinkageTypes)Linkage);
GV->setVisibility((GlobalValue::VisibilityTypes)Visibility);
GV->setThreadLocal(ThreadLocal);
+ GV->setUnnamedAddr(UnnamedAddr);
// Parse attributes on the global.
while (Lex.getKind() == lltok::comma) {
@@ -2657,7 +2660,7 @@ bool LLParser::ParseTypeAndBasicBlock(BasicBlock *&BB, LocTy &Loc,
/// FunctionHeader
/// ::= OptionalLinkage OptionalVisibility OptionalCallingConv OptRetAttrs
-/// Type GlobalName '(' ArgList ')' OptFuncAttrs OptSection
+/// OptUnnamedAddr Type GlobalName '(' ArgList ')' OptFuncAttrs OptSection
/// OptionalAlign OptGC
bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
// Parse the linkage.
@@ -2665,6 +2668,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
unsigned Linkage;
unsigned Visibility, RetAttrs;
+ bool UnnamedAddr;
CallingConv::ID CC;
PATypeHolder RetType(Type::getVoidTy(Context));
LocTy RetTypeLoc = Lex.getLoc();
@@ -2672,6 +2676,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
ParseOptionalVisibility(Visibility) ||
ParseOptionalCallingConv(CC) ||
ParseOptionalAttrs(RetAttrs, 1) ||
+ ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr) ||
ParseType(RetType, RetTypeLoc, true /*void allowed*/))
return true;
@@ -2841,6 +2846,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
Fn->setVisibility((GlobalValue::VisibilityTypes)Visibility);
Fn->setCallingConv(CC);
Fn->setAttributes(PAL);
+ Fn->setUnnamedAddr(UnnamedAddr);
Fn->setAlignment(Alignment);
Fn->setSection(Section);
if (!GC.empty()) Fn->setGC(GC.c_str());
diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h
index 72128c9ae0..576da191ae 100644
--- a/lib/AsmParser/LLToken.h
+++ b/lib/AsmParser/LLToken.h
@@ -42,6 +42,7 @@ namespace lltok {
kw_linkonce, kw_linkonce_odr, kw_weak, kw_weak_odr, kw_appending,
kw_dllimport, kw_dllexport, kw_common, kw_available_externally,
kw_default, kw_hidden, kw_protected,
+ kw_unnamed_addr,
kw_extern_weak,
kw_external, kw_thread_local,
kw_zeroinitializer,
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index e8b998e2a6..7a71b267ea 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -1422,7 +1422,8 @@ bool BitcodeReader::ParseModule() {
break;
}
// GLOBALVAR: [pointer type, isconst, initid,
- // linkage, alignment, section, visibility, threadlocal]
+ // linkage, alignment, section, visibility, threadlocal,
+ // unnamed_addr]
case bitc::MODULE_CODE_GLOBALVAR: {
if (Record.size() < 6)
return Error("Invalid MODULE_CODE_GLOBALVAR record");
@@ -1449,6 +1450,10 @@ bool BitcodeReader::ParseModule() {
if (Record.size() > 7)
isThreadLocal = Record[7];
+ bool UnnamedAddr = false;
+ if (Record.size() > 8)
+ UnnamedAddr = Record[8];
+
GlobalVariable *NewGV =
new GlobalVariable(*TheModule, Ty, isConstant, Linkage, 0, "", 0,
isThreadLocal, AddressSpace);
@@ -1457,6 +1462,7 @@ bool BitcodeReader::ParseModule() {
NewGV->setSection(Section);
NewGV->setVisibility(Visibility);
NewGV->setThreadLocal(isThreadLocal);
+ NewGV->setUnnamedAddr(UnnamedAddr);
ValueList.push_back(NewGV);
@@ -1466,7 +1472,7 @@ bool BitcodeReader::ParseModule() {
break;
}
// FUNCTION: [type, callingconv, isproto, linkage, paramattr,
- // alignment, section, visibility, gc]
+ // alignment, section, visibility, gc, unnamed_addr]
case bitc::MODULE_CODE_FUNCTION: {
if (Record.size() < 8)
return Error("Invalid MODULE_CODE_FUNCTION record");
@@ -1499,6 +1505,10 @@ bool BitcodeReader::ParseModule() {
return Error("Invalid GC ID");
Func->setGC(GCTable[Record[8]-1].c_str());
}
+ bool UnnamedAddr = false;
+ if (Record.size() > 9)
+ UnnamedAddr = Record[9];
+ Func->setUnnamedAddr(UnnamedAddr);
ValueList.push_back(Func);
// If this is a function with a body, remember the prototype we are
diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp
index 7b6b8433a3..702a611cbe 100644
--- a/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -404,7 +404,8 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE,
unsigned AbbrevToUse = 0;
// GLOBALVAR: [type, isconst, initid,
- // linkage, alignment, section, visibility, threadlocal]
+ // linkage, alignment, section, visibility, threadlocal,
+ // unnamed_addr]
Vals.push_back(VE.getTypeID(GV->getType()));
Vals.push_back(GV->isConstant());
Vals.push_back(GV->isDeclaration() ? 0 :
@@ -413,9 +414,11 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE,
Vals.push_back(Log2_32(GV->getAlignment())+1);
Vals.push_back(GV->hasSection() ? SectionMap[GV->getSection()] : 0);
if (GV->isThreadLocal() ||
- GV->getVisibility() != GlobalValue::DefaultVisibility) {
+ GV->getVisibility() != GlobalValue::DefaultVisibility ||
+ GV->hasUnnamedAddr()) {
Vals.push_back(getEncodedVisibility(GV));
Vals.push_back(GV->isThreadLocal());
+ Vals.push_back(GV->hasUnnamedAddr());
} else {
AbbrevToUse = SimpleGVarAbbrev;
}
@@ -427,7 +430,7 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE,
// Emit the function proto information.
for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) {
// FUNCTION: [type, callingconv, isproto, paramattr,
- // linkage, alignment, section, visibility, gc]
+ // linkage, alignment, section, visibility, gc, unnamed_addr]
Vals.push_back(VE.getTypeID(F->getType()));
Vals.push_back(F->getCallingConv());
Vals.push_back(F->isDeclaration());
@@ -437,6 +440,7 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE,
Vals.push_back(F->hasSection() ? SectionMap[F->getSection()] : 0);
Vals.push_back(getEncodedVisibility(F));
Vals.push_back(F->hasGC() ? GCMap[F->getGC()] : 0);
+ Vals.push_back(F->hasUnnamedAddr());
unsigned AbbrevToUse = 0;
Stream.EmitRecord(bitc::MODULE_CODE_FUNCTION, Vals, AbbrevToUse);
diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp
index 7a1b7dd4e8..3fefbbcafb 100644
--- a/lib/VMCore/AsmWriter.cpp
+++ b/lib/VMCore/AsmWriter.cpp
@@ -1459,6 +1459,7 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
if (GV->isThreadLocal()) Out << "thread_local ";
if (unsigned AddressSpace = GV->getType()->getAddressSpace())
Out << "addrspace(" << AddressSpace << ") ";
+ if (GV->hasUnnamedAddr()) Out << "unnamed_addr ";
Out << (GV->isConstant() ? "constant " : "global ");
TypePrinter.print(GV->getType()->getElementType(), Out);
@@ -1589,6 +1590,8 @@ void AssemblyWriter::printFunction(const Function *F) {
Attributes RetAttrs = Attrs.getRetAttributes();
if (RetAttrs != Attribute::None)
Out << Attribute::getAsString(Attrs.getRetAttributes()) << ' ';
+ if (F->hasUnnamedAddr())
+ Out << "unnamed_addr ";
TypePrinter.print(F->getReturnType(), Out);
Out << ' ';
WriteAsOperandInternal(Out, F, &TypePrinter, &Machine, F->getParent());
diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp
index 2b87619038..58ec6fe88d 100644
--- a/lib/VMCore/Verifier.cpp
+++ b/lib/VMCore/Verifier.cpp
@@ -484,6 +484,7 @@ void Verifier::visitGlobalAlias(GlobalAlias &GA) {
"Aliasee cannot be NULL!", &GA);
Assert1(GA.getType() == GA.getAliasee()->getType(),
"Alias and aliasee types should match!", &GA);
+ Assert1(!GA.hasUnnamedAddr(), "Alias cannot have unnamed_addr!", &GA);
if (!isa<GlobalValue>(GA.getAliasee())) {
const ConstantExpr *CE = dyn_cast<ConstantExpr>(GA.getAliasee());
diff --git a/test/Assembler/unnamed-addr.ll b/test/Assembler/unnamed-addr.ll
new file mode 100644
index 0000000000..a4828c3c45
--- /dev/null
+++ b/test/Assembler/unnamed-addr.ll
@@ -0,0 +1,18 @@
+; RUN: llvm-as < %s | llvm-dis | FileCheck %s
+
+%struct.foobar = type { i32 }
+
+@bar.d = internal unnamed_addr constant %struct.foobar zeroinitializer, align 4
+@foo.d = internal constant %struct.foobar zeroinitializer, align 4
+
+define unnamed_addr i32 @main() nounwind ssp {
+entry:
+ %call2 = tail call i32 @zed(%struct.foobar* @foo.d, %struct.foobar* @bar.d) nounwind
+ ret i32 0
+}
+
+declare i32 @zed(%struct.foobar*, %struct.foobar*)
+
+; CHECK: @bar.d = internal unnamed_addr constant %struct.foobar zeroinitializer, align 4
+; CHECK: @foo.d = internal constant %struct.foobar zeroinitializer, align 4
+; CHECK: define unnamed_addr i32 @main() nounwind ssp {
diff --git a/unittests/VMCore/VerifierTest.cpp b/unittests/VMCore/VerifierTest.cpp
index 1173b2d18f..55ce1444ed 100644
--- a/unittests/VMCore/VerifierTest.cpp
+++ b/unittests/VMCore/VerifierTest.cpp
@@ -10,8 +10,11 @@
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
+#include "llvm/GlobalAlias.h"
+#include "llvm/GlobalVariable.h"
#include "llvm/Instructions.h"
#include "llvm/LLVMContext.h"
+#include "llvm/Module.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Analysis/Verifier.h"
#include "gtest/gtest.h"
@@ -41,5 +44,22 @@ TEST(VerifierTest, Branch_i1) {
EXPECT_TRUE(verifyFunction(*F, ReturnStatusAction));
}
+TEST(VerifierTest, AliasUnnamedAddr) {
+ LLVMContext &C = getGlobalContext();
+ Module M("M", C);
+ const Type *Ty = Type::getInt8Ty(C);
+ Constant *Init = Constant::getNullValue(Ty);
+ GlobalVariable *Aliasee = new GlobalVariable(M, Ty, true,
+ GlobalValue::ExternalLinkage,
+ Init, "foo");
+ GlobalAlias *GA = new GlobalAlias(Type::getInt8PtrTy(C),
+ GlobalValue::ExternalLinkage,
+ "bar", Aliasee, &M);
+ GA->setUnnamedAddr(true);
+ std::string Error;
+ EXPECT_TRUE(verifyModule(M, ReturnStatusAction, &Error));
+ EXPECT_TRUE(StringRef(Error).startswith("Alias cannot have unnamed_addr"));
+}
+
}
}