might not correctly handle dropping a weak symbol that is aliased.
Alias that are not ``unnamed_addr`` are guaranteed to have the same address as
-the aliasee.
+the aliasee expression. ``unnamed_addr`` ones are only guaranteed to point
+to the same content.
Since aliases are only a second name, some restrictions apply, of which
some can only be checked when producing an object file:
case lltok::kw_constant: // GlobalType
case lltok::kw_global: { // GlobalType
unsigned Linkage, Visibility, DLLStorageClass;
+ bool UnnamedAddr;
GlobalVariable::ThreadLocalMode TLM;
bool HasLinkage;
if (ParseOptionalLinkage(Linkage, HasLinkage) ||
ParseOptionalVisibility(Visibility) ||
ParseOptionalDLLStorageClass(DLLStorageClass) ||
ParseOptionalThreadLocal(TLM) ||
+ parseOptionalUnnamedAddr(UnnamedAddr) ||
ParseGlobal("", SMLoc(), Linkage, HasLinkage, Visibility,
- DLLStorageClass, TLM))
+ DLLStorageClass, TLM, UnnamedAddr))
return true;
break;
}
bool HasLinkage;
unsigned Linkage, Visibility, DLLStorageClass;
GlobalVariable::ThreadLocalMode TLM;
+ bool UnnamedAddr;
if (ParseOptionalLinkage(Linkage, HasLinkage) ||
ParseOptionalVisibility(Visibility) ||
ParseOptionalDLLStorageClass(DLLStorageClass) ||
- ParseOptionalThreadLocal(TLM))
+ ParseOptionalThreadLocal(TLM) ||
+ parseOptionalUnnamedAddr(UnnamedAddr))
return true;
if (HasLinkage || Lex.getKind() != lltok::kw_alias)
return ParseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility,
- DLLStorageClass, TLM);
- return ParseAlias(Name, NameLoc, Visibility, DLLStorageClass, TLM);
+ DLLStorageClass, TLM, UnnamedAddr);
+ return ParseAlias(Name, NameLoc, Visibility, DLLStorageClass, TLM,
+ UnnamedAddr);
}
/// ParseNamedGlobal:
bool HasLinkage;
unsigned Linkage, Visibility, DLLStorageClass;
GlobalVariable::ThreadLocalMode TLM;
+ bool UnnamedAddr;
if (ParseToken(lltok::equal, "expected '=' in global variable") ||
ParseOptionalLinkage(Linkage, HasLinkage) ||
ParseOptionalVisibility(Visibility) ||
ParseOptionalDLLStorageClass(DLLStorageClass) ||
- ParseOptionalThreadLocal(TLM))
+ ParseOptionalThreadLocal(TLM) ||
+ parseOptionalUnnamedAddr(UnnamedAddr))
return true;
if (HasLinkage || Lex.getKind() != lltok::kw_alias)
return ParseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility,
- DLLStorageClass, TLM);
- return ParseAlias(Name, NameLoc, Visibility, DLLStorageClass, TLM);
+ DLLStorageClass, TLM, UnnamedAddr);
+ return ParseAlias(Name, NameLoc, Visibility, DLLStorageClass, TLM,
+ UnnamedAddr);
}
// MDString:
/// ParseAlias:
/// ::= GlobalVar '=' OptionalVisibility OptionalDLLStorageClass
-/// OptionalThreadLocal 'alias' OptionalLinkage Aliasee
+/// OptionalThreadLocal OptionalUnNammedAddr 'alias'
+/// OptionalLinkage Aliasee
///
/// Aliasee
/// ::= TypeAndValue
///
-/// Everything through OptionalThreadLocal has already been parsed.
+/// Everything through OptionalUnNammedAddr has already been parsed.
///
bool LLParser::ParseAlias(const std::string &Name, LocTy NameLoc,
unsigned Visibility, unsigned DLLStorageClass,
- GlobalVariable::ThreadLocalMode TLM) {
+ GlobalVariable::ThreadLocalMode TLM,
+ bool UnnamedAddr) {
assert(Lex.getKind() == lltok::kw_alias);
Lex.Lex();
LocTy LinkageLoc = Lex.getLoc();
GA->setThreadLocalMode(TLM);
GA->setVisibility((GlobalValue::VisibilityTypes)Visibility);
GA->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass);
+ GA->setUnnamedAddr(UnnamedAddr);
// See if this value already exists in the symbol table. If so, it is either
// a redefinition or a definition of a forward reference.
/// ParseGlobal
/// ::= GlobalVar '=' OptionalLinkage OptionalVisibility OptionalDLLStorageClass
-/// OptionalThreadLocal OptionalAddrSpace OptionalUnNammedAddr
+/// OptionalThreadLocal OptionalUnNammedAddr OptionalAddrSpace
/// OptionalExternallyInitialized GlobalType Type Const
/// ::= OptionalLinkage OptionalVisibility OptionalDLLStorageClass
-/// OptionalThreadLocal OptionalAddrSpace OptionalUnNammedAddr
+/// OptionalThreadLocal OptionalUnNammedAddr OptionalAddrSpace
/// OptionalExternallyInitialized GlobalType Type Const
///
-/// Everything up to and including OptionalThreadLocal has been parsed
+/// Everything up to and including OptionalUnNammedAddr has been parsed
/// already.
///
bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc,
unsigned Linkage, bool HasLinkage,
unsigned Visibility, unsigned DLLStorageClass,
- GlobalVariable::ThreadLocalMode TLM) {
+ GlobalVariable::ThreadLocalMode TLM,
+ bool UnnamedAddr) {
if (!isValidVisibilityForLinkage(Visibility, Linkage))
return Error(NameLoc,
"symbol with local linkage must have default visibility");
unsigned AddrSpace;
- bool IsConstant, UnnamedAddr, IsExternallyInitialized;
- LocTy UnnamedAddrLoc;
+ bool IsConstant, IsExternallyInitialized;
LocTy IsExternallyInitializedLoc;
LocTy TyLoc;
Type *Ty = nullptr;
if (ParseOptionalAddrSpace(AddrSpace) ||
- ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr,
- &UnnamedAddrLoc) ||
ParseOptionalToken(lltok::kw_externally_initialized,
IsExternallyInitialized,
&IsExternallyInitializedLoc) ||
bool ParseTLSModel(GlobalVariable::ThreadLocalMode &TLM);
bool ParseOptionalThreadLocal(GlobalVariable::ThreadLocalMode &TLM);
+ bool parseOptionalUnnamedAddr(bool &UnnamedAddr) {
+ return ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr);
+ }
bool ParseOptionalAddrSpace(unsigned &AddrSpace);
bool ParseOptionalParamAttrs(AttrBuilder &B);
bool ParseOptionalReturnAttrs(AttrBuilder &B);
bool ParseGlobal(const std::string &Name, LocTy Loc, unsigned Linkage,
bool HasLinkage, unsigned Visibility,
unsigned DLLStorageClass,
- GlobalVariable::ThreadLocalMode TLM);
+ GlobalVariable::ThreadLocalMode TLM, bool UnnamedAddr);
bool ParseAlias(const std::string &Name, LocTy Loc, unsigned Visibility,
unsigned DLLStorageClass,
- GlobalVariable::ThreadLocalMode TLM);
+ GlobalVariable::ThreadLocalMode TLM, bool UnnamedAddr);
bool ParseStandaloneMetadata();
bool ParseNamedMetadata();
bool ParseMDString(MDString *&Result);
UpgradeDLLImportExportLinkage(NewGA, Record[2]);
if (Record.size() > 5)
NewGA->setThreadLocalMode(GetDecodedThreadLocalMode(Record[5]));
+ if (Record.size() > 6)
+ NewGA->setUnnamedAddr(Record[6]);
ValueList.push_back(NewGA);
AliasInits.push_back(std::make_pair(NewGA, Record[1]));
break;
Vals.push_back(getEncodedLinkage(A));
Vals.push_back(getEncodedVisibility(A));
Vals.push_back(getEncodedDLLStorageClass(A));
- if (A.isThreadLocal())
- Vals.push_back(getEncodedThreadLocalMode(A));
+ Vals.push_back(getEncodedThreadLocalMode(A));
+ Vals.push_back(A.hasUnnamedAddr());
unsigned AbbrevToUse = 0;
Stream.EmitRecord(bitc::MODULE_CODE_ALIAS, Vals, AbbrevToUse);
Vals.clear();
PrintVisibility(GV->getVisibility(), Out);
PrintDLLStorageClass(GV->getDLLStorageClass(), Out);
PrintThreadLocalModel(GV->getThreadLocalMode(), Out);
+ if (GV->hasUnnamedAddr())
+ Out << "unnamed_addr ";
if (unsigned AddressSpace = GV->getType()->getAddressSpace())
Out << "addrspace(" << AddressSpace << ") ";
- if (GV->hasUnnamedAddr()) Out << "unnamed_addr ";
if (GV->isExternallyInitialized()) Out << "externally_initialized ";
Out << (GV->isConstant() ? "constant " : "global ");
TypePrinter.print(GV->getType()->getElementType(), Out);
PrintVisibility(GA->getVisibility(), Out);
PrintDLLStorageClass(GA->getDLLStorageClass(), Out);
PrintThreadLocalModel(GA->getThreadLocalMode(), Out);
+ if (GA->hasUnnamedAddr())
+ Out << "unnamed_addr ";
Out << "alias ";
Assert1(Aliasee, "Aliasee cannot be NULL!", &GA);
Assert1(GA.getType() == Aliasee->getType(),
"Alias and aliasee types should match!", &GA);
- Assert1(!GA.hasUnnamedAddr(), "Alias cannot have unnamed_addr!", &GA);
Assert1(isa<GlobalValue>(Aliasee) || isa<ConstantExpr>(Aliasee),
"Aliasee should be either GlobalValue or ConstantExpr", &GA);
bool ModuleLinker::linkAliasProto(GlobalAlias *SGA) {
GlobalValue *DGV = getLinkedToGlobal(SGA);
llvm::Optional<GlobalValue::VisibilityTypes> NewVisibility;
+ bool HasUnnamedAddr = SGA->hasUnnamedAddr();
if (DGV) {
GlobalValue::LinkageTypes NewLinkage = GlobalValue::InternalLinkage;
if (getLinkageResult(DGV, SGA, NewLinkage, NV, LinkFromSrc))
return true;
NewVisibility = NV;
+ HasUnnamedAddr = HasUnnamedAddr && DGV->hasUnnamedAddr();
if (!LinkFromSrc) {
// Set calculated linkage.
DGV->setLinkage(NewLinkage);
DGV->setVisibility(*NewVisibility);
+ DGV->setUnnamedAddr(HasUnnamedAddr);
// Make sure to remember this mapping.
ValueMap[SGA] = ConstantExpr::getBitCast(DGV,TypeMap.get(SGA->getType()));
copyGVAttributes(NewDA, SGA);
if (NewVisibility)
NewDA->setVisibility(*NewVisibility);
+ NewDA->setUnnamedAddr(HasUnnamedAddr);
if (DGV) {
// Any uses of DGV need to change to NewDA, with cast.
; RUN: opt < %s -S -nvvm-reflect -nvvm-reflect-list USE_MUL=0 -O2 | FileCheck %s --check-prefix=USE_MUL_0
; RUN: opt < %s -S -nvvm-reflect -nvvm-reflect-list USE_MUL=1 -O2 | FileCheck %s --check-prefix=USE_MUL_1
-@str = private addrspace(4) unnamed_addr constant [8 x i8] c"USE_MUL\00"
+@str = private unnamed_addr addrspace(4) constant [8 x i8] c"USE_MUL\00"
declare i32 @__nvvm_reflect(i8*)
declare i8* @llvm.nvvm.ptr.constant.to.gen.p0i8.p4i8(i8 addrspace(4)*)
; XXX: Test on SI once 64-bit adds are supportes.
-@float_gv = internal addrspace(2) unnamed_addr constant [5 x float] [float 0.0, float 1.0, float 2.0, float 3.0, float 4.0], align 4
+@float_gv = internal unnamed_addr addrspace(2) constant [5 x float] [float 0.0, float 1.0, float 2.0, float 3.0, float 4.0], align 4
; FUNC-LABEL: @float
ret void
}
-@i32_gv = internal addrspace(2) unnamed_addr constant [5 x i32] [i32 0, i32 1, i32 2, i32 3, i32 4], align 4
+@i32_gv = internal unnamed_addr addrspace(2) constant [5 x i32] [i32 0, i32 1, i32 2, i32 3, i32 4], align 4
; FUNC-LABEL: @i32
%struct.foo = type { float, [5 x i32] }
-@struct_foo_gv = internal addrspace(2) unnamed_addr constant [1 x %struct.foo] [ %struct.foo { float 16.0, [5 x i32] [i32 0, i32 1, i32 2, i32 3, i32 4] } ]
+@struct_foo_gv = internal unnamed_addr addrspace(2) constant [1 x %struct.foo] [ %struct.foo { float 16.0, [5 x i32] [i32 0, i32 1, i32 2, i32 3, i32 4] } ]
; FUNC-LABEL: @struct_foo_gv_load
; CHECK-NOT: ALU clause
; CHECK: MOV * T{{[0-9]\.[XYZW]}}, OQAP
-@local_mem = internal addrspace(3) unnamed_addr global [2 x i32] [i32 1, i32 2], align 4
+@local_mem = internal unnamed_addr addrspace(3) global [2 x i32] [i32 1, i32 2], align 4
define void @lds_input_queue(i32 addrspace(1)* %out, i32 addrspace(1)* %in, i32 %index) {
entry:
; CHECK-LABEL: @test
; CHECK: .long 166120
; CHECK-NEXT: .long 1
-@lds = internal addrspace(3) unnamed_addr global i32 zeroinitializer, align 4
+@lds = internal unnamed_addr addrspace(3) global i32 zeroinitializer, align 4
define void @test(i32 addrspace(1)* %out, i32 %cond) {
entry:
; RUN: llc < %s -march=r600 -mcpu=redwood | FileCheck --check-prefix=EG-CHECK %s
; RUN: llc < %s -march=r600 -mcpu=verde -verify-machineinstrs | FileCheck --check-prefix=SI-CHECK %s
-@local_memory_two_objects.local_mem0 = internal addrspace(3) unnamed_addr global [4 x i32] zeroinitializer, align 4
-@local_memory_two_objects.local_mem1 = internal addrspace(3) unnamed_addr global [4 x i32] zeroinitializer, align 4
+@local_memory_two_objects.local_mem0 = internal unnamed_addr addrspace(3) global [4 x i32] zeroinitializer, align 4
+@local_memory_two_objects.local_mem1 = internal unnamed_addr addrspace(3) global [4 x i32] zeroinitializer, align 4
; EG-CHECK: @local_memory_two_objects
; RUN: llc < %s -march=r600 -mcpu=verde -verify-machineinstrs | FileCheck --check-prefix=SI-CHECK %s
; RUN: llc < %s -march=r600 -mcpu=bonaire -verify-machineinstrs | FileCheck --check-prefix=CI-CHECK %s
-@local_memory.local_mem = internal addrspace(3) unnamed_addr global [128 x i32] zeroinitializer, align 4
+@local_memory.local_mem = internal unnamed_addr addrspace(3) global [128 x i32] zeroinitializer, align 4
; EG-CHECK-LABEL: @local_memory
; SI-CHECK-LABEL: @local_memory
@foo1 = alias i32* @bar
@foo2 = alias i32* @bar
@foo3 = alias i32* @foo2
+@foo4 = unnamed_addr alias i32* @foo2
%FunTy = type i32()
}
-@global_as1 = private addrspace(1) unnamed_addr constant [10 x i8] c"ola\00mundo\00", align 1
+@global_as1 = private unnamed_addr addrspace(1) constant [10 x i8] c"ola\00mundo\00", align 1
define void @f1_as1(i8 addrspace(1)* nocapture %c) {
; CHECK: @f1_as1
@global-f = weak global i32 42
; CHECK-DAG: @global-f = global i32 42
+@alias-a = weak global i32 42
+; CHECK-DAG: @alias-a = alias i32* @global-f
+@alias-b = weak unnamed_addr global i32 42
+; CHECK-DAG: @alias-b = unnamed_addr alias i32* @global-f
+
declare void @func-c()
; CHECK-DAG: define weak void @func-c() {
define weak void @func-d() { ret void }
@global-j = weak global i32 42
; CHECK-DAG: @global-j = global i32 42
+@alias-c = weak global i32 42
+; CHECK-DAG: @alias-c = alias i32* @global-f
+@alias-d = weak unnamed_addr global i32 42
+; CHECK-DAG: @alias-d = alias i32* @global-f
+
+
declare void @func-g()
; CHECK-DAG: define weak void @func-g() {
define weak void @func-h() { ret void }
@global-e = unnamed_addr global i32 42
@global-f = unnamed_addr global i32 42
+@alias-a = unnamed_addr alias i32* @global-f
+@alias-b = unnamed_addr alias i32* @global-f
+
define weak void @func-c() unnamed_addr { ret void }
define weak void @func-d() unnamed_addr { ret void }
define weak void @func-e() unnamed_addr { ret void }
@global-i = global i32 42
@global-j = global i32 42
+@alias-c = alias i32* @global-f
+@alias-d = alias i32* @global-f
+
define weak void @func-g() { ret void }
define weak void @func-h() { ret void }
define weak void @func-i() { ret void }
; RUN: opt < %s -instcombine -S | FileCheck %s
; CHECK: addrspacecast
-@base = internal addrspace(3) unnamed_addr global [16 x i32] zeroinitializer, align 16
+@base = internal unnamed_addr addrspace(3) global [16 x i32] zeroinitializer, align 16
declare void @foo(i32*)
define void @test() nounwind {
EXPECT_TRUE(verifyFunction(*F));
}
-TEST(VerifierTest, AliasUnnamedAddr) {
- LLVMContext &C = getGlobalContext();
- Module M("M", C);
- Type *Ty = Type::getInt8Ty(C);
- Constant *Init = Constant::getNullValue(Ty);
- GlobalVariable *Aliasee = new GlobalVariable(M, Ty, true,
- GlobalValue::ExternalLinkage,
- Init, "foo");
- auto *GA = GlobalAlias::create(GlobalValue::ExternalLinkage, "bar", Aliasee);
- GA->setUnnamedAddr(true);
- std::string Error;
- raw_string_ostream ErrorOS(Error);
- EXPECT_TRUE(verifyModule(M, &ErrorOS));
- EXPECT_TRUE(
- StringRef(ErrorOS.str()).startswith("Alias cannot have unnamed_addr"));
-}
-
TEST(VerifierTest, InvalidRetAttribute) {
LLVMContext &C = getGlobalContext();
Module M("M", C);