summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorPeter Collingbourne <peter@pcc.me.uk>2016-06-14 21:01:22 +0000
committerPeter Collingbourne <peter@pcc.me.uk>2016-06-14 21:01:22 +0000
commit96efdd6107a06e762e2cd25eb41b053f946ac87a (patch)
tree784c39f51cb5c4ec15071c7db559fb0b31e2f484 /llvm/lib
parent1dc9fd3c4a260883b1559f7b92ad9156ecc2418c (diff)
downloadbcm5719-llvm-96efdd6107a06e762e2cd25eb41b053f946ac87a.tar.gz
bcm5719-llvm-96efdd6107a06e762e2cd25eb41b053f946ac87a.zip
IR: Introduce local_unnamed_addr attribute.
If a local_unnamed_addr attribute is attached to a global, the address is known to be insignificant within the module. It is distinct from the existing unnamed_addr attribute in that it only describes a local property of the module rather than a global property of the symbol. This attribute is intended to be used by the code generator and LTO to allow the linker to decide whether the global needs to be in the symbol table. It is possible to exclude a global from the symbol table if three things are true: - This attribute is present on every instance of the global (which means that the normal rule that the global must have a unique address can be broken without being observable by the program by performing comparisons against the global's address) - The global has linkonce_odr linkage (which means that each linkage unit must have its own copy of the global if it requires one, and the copy in each linkage unit must be the same) - It is a constant or a function (which means that the program cannot observe that the unique-address rule has been broken by writing to the global) Although this attribute could in principle be computed from the module contents, LTO clients (i.e. linkers) will normally need to be able to compute this property as part of symbol resolution, and it would be inefficient to materialize every module just to compute it. See: http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20160509/356401.html http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20160516/356738.html for earlier discussion. Part of the fix for PR27553. Differential Revision: http://reviews.llvm.org/D20348 llvm-svn: 272709
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Analysis/InstructionSimplify.cpp2
-rw-r--r--llvm/lib/AsmParser/LLLexer.cpp1
-rw-r--r--llvm/lib/AsmParser/LLParser.cpp35
-rw-r--r--llvm/lib/AsmParser/LLParser.h9
-rw-r--r--llvm/lib/AsmParser/LLToken.h1
-rw-r--r--llvm/lib/Bitcode/Reader/BitcodeReader.cpp20
-rw-r--r--llvm/lib/Bitcode/Writer/BitcodeWriter.cpp21
-rw-r--r--llvm/lib/CodeGen/Analysis.cpp20
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp2
-rw-r--r--llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp2
-rw-r--r--llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp2
-rw-r--r--llvm/lib/IR/AsmWriter.cpp26
-rw-r--r--llvm/lib/IR/Core.cpp6
-rw-r--r--llvm/lib/IR/Globals.cpp2
-rw-r--r--llvm/lib/IR/IRBuilder.cpp2
-rw-r--r--llvm/lib/IR/Verifier.cpp2
-rw-r--r--llvm/lib/Linker/IRMover.cpp2
-rw-r--r--llvm/lib/Linker/LinkModules.cpp7
-rw-r--r--llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp2
-rw-r--r--llvm/lib/Target/TargetLoweringObjectFile.cpp2
-rw-r--r--llvm/lib/Transforms/IPO/ConstantMerge.cpp8
-rw-r--r--llvm/lib/Transforms/IPO/GlobalOpt.cpp19
-rw-r--r--llvm/lib/Transforms/IPO/MergeFunctions.cpp2
-rw-r--r--llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp4
-rw-r--r--llvm/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp2
-rw-r--r--llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp12
-rw-r--r--llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp4
-rw-r--r--llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp2
-rw-r--r--llvm/lib/Transforms/Utils/FunctionImportUtils.cpp2
-rw-r--r--llvm/lib/Transforms/Utils/GlobalStatus.cpp2
-rw-r--r--llvm/lib/Transforms/Utils/SimplifyCFG.cpp2
31 files changed, 134 insertions, 91 deletions
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 43dcaec1373..a9fed16f8aa 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -2086,7 +2086,7 @@ computePointerICmp(const DataLayout &DL, const TargetLibraryInfo *TLI,
return AI->getParent() && AI->getFunction() && AI->isStaticAlloca();
if (const GlobalValue *GV = dyn_cast<GlobalValue>(V))
return (GV->hasLocalLinkage() || GV->hasHiddenVisibility() ||
- GV->hasProtectedVisibility() || GV->hasUnnamedAddr()) &&
+ GV->hasProtectedVisibility() || GV->hasGlobalUnnamedAddr()) &&
!GV->isThreadLocal();
if (const Argument *A = dyn_cast<Argument>(V))
return A->hasByValAttr();
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp
index 1ba698ebd61..a3d1346e7d2 100644
--- a/llvm/lib/AsmParser/LLLexer.cpp
+++ b/llvm/lib/AsmParser/LLLexer.cpp
@@ -513,6 +513,7 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(hidden);
KEYWORD(protected);
KEYWORD(unnamed_addr);
+ KEYWORD(local_unnamed_addr);
KEYWORD(externally_initialized);
KEYWORD(extern_weak);
KEYWORD(external);
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index cc7b98fa56d..2725386f8da 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -429,6 +429,17 @@ bool LLParser::ParseGlobalType(bool &IsConstant) {
return false;
}
+bool LLParser::ParseOptionalUnnamedAddr(
+ GlobalVariable::UnnamedAddr &UnnamedAddr) {
+ if (EatIfPresent(lltok::kw_unnamed_addr))
+ UnnamedAddr = GlobalValue::UnnamedAddr::Global;
+ else if (EatIfPresent(lltok::kw_local_unnamed_addr))
+ UnnamedAddr = GlobalValue::UnnamedAddr::Local;
+ else
+ UnnamedAddr = GlobalValue::UnnamedAddr::None;
+ return false;
+}
+
/// ParseUnnamedGlobal:
/// OptionalVisibility (ALIAS | IFUNC) ...
/// OptionalLinkage OptionalVisibility OptionalDLLStorageClass
@@ -455,9 +466,9 @@ bool LLParser::ParseUnnamedGlobal() {
bool HasLinkage;
unsigned Linkage, Visibility, DLLStorageClass;
GlobalVariable::ThreadLocalMode TLM;
- bool UnnamedAddr;
+ GlobalVariable::UnnamedAddr UnnamedAddr;
if (ParseOptionalLinkage(Linkage, HasLinkage, Visibility, DLLStorageClass) ||
- ParseOptionalThreadLocal(TLM) || parseOptionalUnnamedAddr(UnnamedAddr))
+ ParseOptionalThreadLocal(TLM) || ParseOptionalUnnamedAddr(UnnamedAddr))
return true;
if (Lex.getKind() != lltok::kw_alias && Lex.getKind() != lltok::kw_ifunc)
@@ -481,10 +492,10 @@ bool LLParser::ParseNamedGlobal() {
bool HasLinkage;
unsigned Linkage, Visibility, DLLStorageClass;
GlobalVariable::ThreadLocalMode TLM;
- bool UnnamedAddr;
+ GlobalVariable::UnnamedAddr UnnamedAddr;
if (ParseToken(lltok::equal, "expected '=' in global variable") ||
ParseOptionalLinkage(Linkage, HasLinkage, Visibility, DLLStorageClass) ||
- ParseOptionalThreadLocal(TLM) || parseOptionalUnnamedAddr(UnnamedAddr))
+ ParseOptionalThreadLocal(TLM) || ParseOptionalUnnamedAddr(UnnamedAddr))
return true;
if (Lex.getKind() != lltok::kw_alias && Lex.getKind() != lltok::kw_ifunc)
@@ -659,11 +670,10 @@ static bool isValidVisibilityForLinkage(unsigned V, unsigned L) {
///
/// Everything through OptionalUnnamedAddr has already been parsed.
///
-bool LLParser::parseIndirectSymbol(const std::string &Name, LocTy NameLoc,
- unsigned L, unsigned Visibility,
- unsigned DLLStorageClass,
- GlobalVariable::ThreadLocalMode TLM,
- bool UnnamedAddr) {
+bool LLParser::parseIndirectSymbol(
+ const std::string &Name, LocTy NameLoc, unsigned L, unsigned Visibility,
+ unsigned DLLStorageClass, GlobalVariable::ThreadLocalMode TLM,
+ GlobalVariable::UnnamedAddr UnnamedAddr) {
bool IsAlias;
if (Lex.getKind() == lltok::kw_alias)
IsAlias = true;
@@ -799,7 +809,7 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc,
unsigned Linkage, bool HasLinkage,
unsigned Visibility, unsigned DLLStorageClass,
GlobalVariable::ThreadLocalMode TLM,
- bool UnnamedAddr) {
+ GlobalVariable::UnnamedAddr UnnamedAddr) {
if (!isValidVisibilityForLinkage(Visibility, Linkage))
return Error(NameLoc,
"symbol with local linkage must have default visibility");
@@ -4580,7 +4590,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
std::string Section;
unsigned Alignment;
std::string GC;
- bool UnnamedAddr;
+ GlobalValue::UnnamedAddr UnnamedAddr = GlobalValue::UnnamedAddr::None;
LocTy UnnamedAddrLoc;
Constant *Prefix = nullptr;
Constant *Prologue = nullptr;
@@ -4588,8 +4598,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
Comdat *C;
if (ParseArgumentList(ArgList, isVarArg) ||
- ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr,
- &UnnamedAddrLoc) ||
+ ParseOptionalUnnamedAddr(UnnamedAddr) ||
ParseFnAttributeValuePairs(FuncAttrs, FwdRefAttrGrps, false,
BuiltinLoc) ||
(EatIfPresent(lltok::kw_section) &&
diff --git a/llvm/lib/AsmParser/LLParser.h b/llvm/lib/AsmParser/LLParser.h
index 7c32f2c7fac..479ff96bc8a 100644
--- a/llvm/lib/AsmParser/LLParser.h
+++ b/llvm/lib/AsmParser/LLParser.h
@@ -226,9 +226,7 @@ namespace llvm {
bool ParseTLSModel(GlobalVariable::ThreadLocalMode &TLM);
bool ParseOptionalThreadLocal(GlobalVariable::ThreadLocalMode &TLM);
- bool parseOptionalUnnamedAddr(bool &UnnamedAddr) {
- return ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr);
- }
+ bool ParseOptionalUnnamedAddr(GlobalVariable::UnnamedAddr &UnnamedAddr);
bool ParseOptionalAddrSpace(unsigned &AddrSpace);
bool ParseOptionalParamAttrs(AttrBuilder &B);
bool ParseOptionalReturnAttrs(AttrBuilder &B);
@@ -275,12 +273,13 @@ namespace llvm {
bool ParseGlobal(const std::string &Name, LocTy Loc, unsigned Linkage,
bool HasLinkage, unsigned Visibility,
unsigned DLLStorageClass,
- GlobalVariable::ThreadLocalMode TLM, bool UnnamedAddr);
+ GlobalVariable::ThreadLocalMode TLM,
+ GlobalVariable::UnnamedAddr UnnamedAddr);
bool parseIndirectSymbol(const std::string &Name, LocTy Loc,
unsigned Linkage, unsigned Visibility,
unsigned DLLStorageClass,
GlobalVariable::ThreadLocalMode TLM,
- bool UnnamedAddr);
+ GlobalVariable::UnnamedAddr UnnamedAddr);
bool parseComdat();
bool ParseStandaloneMetadata();
bool ParseNamedMetadata();
diff --git a/llvm/lib/AsmParser/LLToken.h b/llvm/lib/AsmParser/LLToken.h
index 85881d6f11b..be3697aefdd 100644
--- a/llvm/lib/AsmParser/LLToken.h
+++ b/llvm/lib/AsmParser/LLToken.h
@@ -60,6 +60,7 @@ enum Kind {
kw_hidden,
kw_protected,
kw_unnamed_addr,
+ kw_local_unnamed_addr,
kw_externally_initialized,
kw_extern_weak,
kw_external,
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 3bba0250af5..ac72f69c76e 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -773,6 +773,15 @@ static GlobalVariable::ThreadLocalMode getDecodedThreadLocalMode(unsigned Val) {
}
}
+static GlobalVariable::UnnamedAddr getDecodedUnnamedAddrType(unsigned Val) {
+ switch (Val) {
+ default: // Map unknown to UnnamedAddr::None.
+ case 0: return GlobalVariable::UnnamedAddr::None;
+ case 1: return GlobalVariable::UnnamedAddr::Global;
+ case 2: return GlobalVariable::UnnamedAddr::Local;
+ }
+}
+
static int getDecodedCastOpcode(unsigned Val) {
switch (Val) {
default: return -1;
@@ -3791,9 +3800,9 @@ std::error_code BitcodeReader::parseModule(uint64_t ResumeBit,
if (Record.size() > 7)
TLM = getDecodedThreadLocalMode(Record[7]);
- bool UnnamedAddr = false;
+ GlobalValue::UnnamedAddr UnnamedAddr = GlobalValue::UnnamedAddr::None;
if (Record.size() > 8)
- UnnamedAddr = Record[8];
+ UnnamedAddr = getDecodedUnnamedAddrType(Record[8]);
bool ExternallyInitialized = false;
if (Record.size() > 9)
@@ -3828,6 +3837,7 @@ std::error_code BitcodeReader::parseModule(uint64_t ResumeBit,
} else if (hasImplicitComdat(RawLinkage)) {
NewGV->setComdat(reinterpret_cast<Comdat *>(1));
}
+
break;
}
case bitc::MODULE_CODE_GLOBALVAR_ATTACHMENT: {
@@ -3885,9 +3895,9 @@ std::error_code BitcodeReader::parseModule(uint64_t ResumeBit,
return error("Invalid ID");
Func->setGC(GCTable[Record[8] - 1]);
}
- bool UnnamedAddr = false;
+ GlobalValue::UnnamedAddr UnnamedAddr = GlobalValue::UnnamedAddr::None;
if (Record.size() > 9)
- UnnamedAddr = Record[9];
+ UnnamedAddr = getDecodedUnnamedAddrType(Record[9]);
Func->setUnnamedAddr(UnnamedAddr);
if (Record.size() > 10 && Record[10] != 0)
FunctionPrologues.push_back(std::make_pair(Func, Record[10]-1));
@@ -3974,7 +3984,7 @@ std::error_code BitcodeReader::parseModule(uint64_t ResumeBit,
if (OpNum != Record.size())
NewGA->setThreadLocalMode(getDecodedThreadLocalMode(Record[OpNum++]));
if (OpNum != Record.size())
- NewGA->setUnnamedAddr(Record[OpNum++]);
+ NewGA->setUnnamedAddr(getDecodedUnnamedAddrType(Record[OpNum++]));
ValueList.push_back(NewGA);
IndirectSymbolInits.push_back(std::make_pair(NewGA, Val));
break;
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 06a4ef1892d..4699e7dac77 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -996,6 +996,15 @@ static unsigned getEncodedComdatSelectionKind(const Comdat &C) {
llvm_unreachable("Invalid selection kind");
}
+static unsigned getEncodedUnnamedAddr(const GlobalValue &GV) {
+ switch (GV.getUnnamedAddr()) {
+ case GlobalValue::UnnamedAddr::None: return 0;
+ case GlobalValue::UnnamedAddr::Local: return 2;
+ case GlobalValue::UnnamedAddr::Global: return 1;
+ }
+ llvm_unreachable("Invalid unnamed_addr");
+}
+
void ModuleBitcodeWriter::writeComdats() {
SmallVector<unsigned, 64> Vals;
for (const Comdat *C : VE.getComdats()) {
@@ -1157,12 +1166,13 @@ void ModuleBitcodeWriter::writeModuleInfo() {
Vals.push_back(GV.hasSection() ? SectionMap[GV.getSection()] : 0);
if (GV.isThreadLocal() ||
GV.getVisibility() != GlobalValue::DefaultVisibility ||
- GV.hasUnnamedAddr() || GV.isExternallyInitialized() ||
+ GV.getUnnamedAddr() != GlobalValue::UnnamedAddr::None ||
+ GV.isExternallyInitialized() ||
GV.getDLLStorageClass() != GlobalValue::DefaultStorageClass ||
GV.hasComdat()) {
Vals.push_back(getEncodedVisibility(GV));
Vals.push_back(getEncodedThreadLocalMode(GV));
- Vals.push_back(GV.hasUnnamedAddr());
+ Vals.push_back(getEncodedUnnamedAddr(GV));
Vals.push_back(GV.isExternallyInitialized());
Vals.push_back(getEncodedDLLStorageClass(GV));
Vals.push_back(GV.hasComdat() ? VE.getComdatID(GV.getComdat()) : 0);
@@ -1188,7 +1198,7 @@ void ModuleBitcodeWriter::writeModuleInfo() {
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());
+ Vals.push_back(getEncodedUnnamedAddr(F));
Vals.push_back(F.hasPrologueData() ? (VE.getValueID(F.getPrologueData()) + 1)
: 0);
Vals.push_back(getEncodedDLLStorageClass(F));
@@ -1205,7 +1215,8 @@ void ModuleBitcodeWriter::writeModuleInfo() {
// Emit the alias information.
for (const GlobalAlias &A : M.aliases()) {
- // ALIAS: [alias type, aliasee val#, linkage, visibility]
+ // ALIAS: [alias type, aliasee val#, linkage, visibility, dllstorageclass,
+ // threadlocal, unnamed_addr]
Vals.push_back(VE.getTypeID(A.getValueType()));
Vals.push_back(A.getType()->getAddressSpace());
Vals.push_back(VE.getValueID(A.getAliasee()));
@@ -1213,7 +1224,7 @@ void ModuleBitcodeWriter::writeModuleInfo() {
Vals.push_back(getEncodedVisibility(A));
Vals.push_back(getEncodedDLLStorageClass(A));
Vals.push_back(getEncodedThreadLocalMode(A));
- Vals.push_back(A.hasUnnamedAddr());
+ Vals.push_back(getEncodedUnnamedAddr(A));
unsigned AbbrevToUse = 0;
Stream.EmitRecord(bitc::MODULE_CODE_ALIAS, Vals, AbbrevToUse);
Vals.clear();
diff --git a/llvm/lib/CodeGen/Analysis.cpp b/llvm/lib/CodeGen/Analysis.cpp
index ef405484e84..73bd3d29eae 100644
--- a/llvm/lib/CodeGen/Analysis.cpp
+++ b/llvm/lib/CodeGen/Analysis.cpp
@@ -623,7 +623,9 @@ bool llvm::canBeOmittedFromSymbolTable(const GlobalValue *GV) {
if (!GV->hasLinkOnceODRLinkage())
return false;
- if (GV->hasUnnamedAddr())
+ // We assume that anyone who sets global unnamed_addr on a non-constant knows
+ // what they're doing.
+ if (GV->hasGlobalUnnamedAddr())
return true;
// If it is a non constant variable, it needs to be uniqued across shared
@@ -633,21 +635,7 @@ bool llvm::canBeOmittedFromSymbolTable(const GlobalValue *GV) {
return false;
}
- // An alias can point to a variable. We could try to resolve the alias to
- // decide, but for now just don't hide them.
- if (isa<GlobalAlias>(GV))
- return false;
-
- // If we don't see every use, we have to be conservative and assume the value
- // address is significant.
- if (GV->getParent()->getMaterializer())
- return false;
-
- GlobalStatus GS;
- if (GlobalStatus::analyzeGlobal(GV, GS))
- return false;
-
- return !GS.IsCompared;
+ return GV->hasAtLeastLocalUnnamedAddr();
}
// FIXME: make this a proper option
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index d39881d9ce3..02640f55fa2 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -1001,7 +1001,7 @@ static bool isGOTEquivalentCandidate(const GlobalVariable *GV,
// Global GOT equivalents are unnamed private globals with a constant
// pointer initializer to another global symbol. They must point to a
// GlobalVariable or Function, i.e., as GlobalValue.
- if (!GV->hasUnnamedAddr() || !GV->hasInitializer() || !GV->isConstant() ||
+ if (!GV->hasGlobalUnnamedAddr() || !GV->hasInitializer() || !GV->isConstant() ||
!GV->isDiscardableIfUnused() || !dyn_cast<GlobalValue>(GV->getOperand(0)))
return false;
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index f7ba62ff231..6d5dd5fa4d5 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -429,7 +429,7 @@ const MCExpr *TargetLoweringObjectFileELF::lowerRelativeReference(
const TargetMachine &TM) const {
// We may only use a PLT-relative relocation to refer to unnamed_addr
// functions.
- if (!LHS->hasUnnamedAddr() || !LHS->getValueType()->isFunctionTy())
+ if (!LHS->hasGlobalUnnamedAddr() || !LHS->getValueType()->isFunctionTy())
return nullptr;
// Basic sanity checks.
diff --git a/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp
index c7b97865ab7..6f7c29feef0 100644
--- a/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp
@@ -144,7 +144,7 @@ static void raiseVisibilityOnValue(GlobalValue &V, GlobalRenamer &R) {
V.setLinkage(GlobalValue::ExternalLinkage);
V.setVisibility(GlobalValue::HiddenVisibility);
}
- V.setUnnamedAddr(false);
+ V.setUnnamedAddr(GlobalValue::UnnamedAddr::None);
assert(!R.needsRenaming(V) && "Invalid global name.");
}
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 24b92b8eb3c..0d488c27aa8 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -2426,6 +2426,17 @@ static void PrintThreadLocalModel(GlobalVariable::ThreadLocalMode TLM,
}
}
+static StringRef getUnnamedAddrEncoding(GlobalVariable::UnnamedAddr UA) {
+ switch (UA) {
+ case GlobalVariable::UnnamedAddr::None:
+ return "";
+ case GlobalVariable::UnnamedAddr::Local:
+ return "local_unnamed_addr";
+ case GlobalVariable::UnnamedAddr::Global:
+ return "unnamed_addr";
+ }
+}
+
static void maybePrintComdat(formatted_raw_ostream &Out,
const GlobalObject &GO) {
const Comdat *C = GO.getComdat();
@@ -2458,8 +2469,9 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
PrintVisibility(GV->getVisibility(), Out);
PrintDLLStorageClass(GV->getDLLStorageClass(), Out);
PrintThreadLocalModel(GV->getThreadLocalMode(), Out);
- if (GV->hasUnnamedAddr())
- Out << "unnamed_addr ";
+ StringRef UA = getUnnamedAddrEncoding(GV->getUnnamedAddr());
+ if (!UA.empty())
+ Out << UA << ' ';
if (unsigned AddressSpace = GV->getType()->getAddressSpace())
Out << "addrspace(" << AddressSpace << ") ";
@@ -2499,8 +2511,9 @@ void AssemblyWriter::printIndirectSymbol(const GlobalIndirectSymbol *GIS) {
PrintVisibility(GIS->getVisibility(), Out);
PrintDLLStorageClass(GIS->getDLLStorageClass(), Out);
PrintThreadLocalModel(GIS->getThreadLocalMode(), Out);
- if (GIS->hasUnnamedAddr())
- Out << "unnamed_addr ";
+ StringRef UA = getUnnamedAddrEncoding(GIS->getUnnamedAddr());
+ if (!UA.empty())
+ Out << UA << ' ';
if (isa<GlobalAlias>(GIS))
Out << "alias ";
@@ -2656,8 +2669,9 @@ void AssemblyWriter::printFunction(const Function *F) {
Out << "..."; // Output varargs portion of signature!
}
Out << ')';
- if (F->hasUnnamedAddr())
- Out << " unnamed_addr";
+ StringRef UA = getUnnamedAddrEncoding(F->getUnnamedAddr());
+ if (!UA.empty())
+ Out << ' ' << UA;
if (Attrs.hasAttributes(AttributeSet::FunctionIndex))
Out << " #" << Machine.getAttributeGroupSlot(Attrs.getFnAttributes());
if (F->hasSection()) {
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index 380fca8c10f..b044781302c 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -1560,11 +1560,13 @@ void LLVMSetDLLStorageClass(LLVMValueRef Global, LLVMDLLStorageClass Class) {
}
LLVMBool LLVMHasUnnamedAddr(LLVMValueRef Global) {
- return unwrap<GlobalValue>(Global)->hasUnnamedAddr();
+ return unwrap<GlobalValue>(Global)->hasGlobalUnnamedAddr();
}
void LLVMSetUnnamedAddr(LLVMValueRef Global, LLVMBool HasUnnamedAddr) {
- unwrap<GlobalValue>(Global)->setUnnamedAddr(HasUnnamedAddr);
+ unwrap<GlobalValue>(Global)->setUnnamedAddr(
+ HasUnnamedAddr ? GlobalValue::UnnamedAddr::Global
+ : GlobalValue::UnnamedAddr::None);
}
/*--.. Operations on global variables, load and store instructions .........--*/
diff --git a/llvm/lib/IR/Globals.cpp b/llvm/lib/IR/Globals.cpp
index d151b9c5dc2..c5e1b9b9fa0 100644
--- a/llvm/lib/IR/Globals.cpp
+++ b/llvm/lib/IR/Globals.cpp
@@ -51,7 +51,7 @@ Value *GlobalValue::handleOperandChangeImpl(Value *From, Value *To) {
/// create a GlobalValue) from the GlobalValue Src to this one.
void GlobalValue::copyAttributesFrom(const GlobalValue *Src) {
setVisibility(Src->getVisibility());
- setUnnamedAddr(Src->hasUnnamedAddr());
+ setUnnamedAddr(Src->getUnnamedAddr());
setDLLStorageClass(Src->getDLLStorageClass());
}
diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp
index bc75de2693b..480e5e5d426 100644
--- a/llvm/lib/IR/IRBuilder.cpp
+++ b/llvm/lib/IR/IRBuilder.cpp
@@ -34,7 +34,7 @@ GlobalVariable *IRBuilderBase::CreateGlobalString(StringRef Str,
StrConstant, Name, nullptr,
GlobalVariable::NotThreadLocal,
AddressSpace);
- GV->setUnnamedAddr(true);
+ GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
return GV;
}
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 79c9f4d3a13..0395f5b36fe 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -1535,7 +1535,7 @@ void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs,
if (Attrs.hasAttribute(AttributeSet::FunctionIndex,
Attribute::JumpTable)) {
const GlobalValue *GV = cast<GlobalValue>(V);
- Assert(GV->hasUnnamedAddr(),
+ Assert(GV->hasGlobalUnnamedAddr(),
"Attribute 'jumptable' requires 'unnamed_addr'", V);
}
diff --git a/llvm/lib/Linker/IRMover.cpp b/llvm/lib/Linker/IRMover.cpp
index d2c6d78abe2..14b0a43030d 100644
--- a/llvm/lib/Linker/IRMover.cpp
+++ b/llvm/lib/Linker/IRMover.cpp
@@ -791,7 +791,7 @@ IRLinker::linkAppendingVarProto(GlobalVariable *DstGV,
return stringErr(
"Appending variables with different visibility need to be linked!");
- if (DstGV->hasUnnamedAddr() != SrcGV->hasUnnamedAddr())
+ if (DstGV->hasGlobalUnnamedAddr() != SrcGV->hasGlobalUnnamedAddr())
return stringErr(
"Appending variables with different unnamed_addr need to be linked!");
diff --git a/llvm/lib/Linker/LinkModules.cpp b/llvm/lib/Linker/LinkModules.cpp
index ff36f90b53f..fae9c95ebe8 100644
--- a/llvm/lib/Linker/LinkModules.cpp
+++ b/llvm/lib/Linker/LinkModules.cpp
@@ -377,9 +377,10 @@ bool ModuleLinker::linkIfNeeded(GlobalValue &GV) {
DGV->setVisibility(Visibility);
GV.setVisibility(Visibility);
- bool HasUnnamedAddr = GV.hasUnnamedAddr() && DGV->hasUnnamedAddr();
- DGV->setUnnamedAddr(HasUnnamedAddr);
- GV.setUnnamedAddr(HasUnnamedAddr);
+ GlobalValue::UnnamedAddr UnnamedAddr = GlobalValue::getMinUnnamedAddr(
+ DGV->getUnnamedAddr(), GV.getUnnamedAddr());
+ DGV->setUnnamedAddr(UnnamedAddr);
+ GV.setUnnamedAddr(UnnamedAddr);
}
// Don't want to append to global_ctors list, for example, when we
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp b/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
index 5222bed0d25..17b45fa65f1 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
@@ -694,7 +694,7 @@ void AMDGPUPromoteAlloca::handleAlloca(AllocaInst &I) {
nullptr,
GlobalVariable::NotThreadLocal,
AMDGPUAS::LOCAL_ADDRESS);
- GV->setUnnamedAddr(true);
+ GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
GV->setAlignment(I.getAlignment());
Value *TCntY, *TCntZ;
diff --git a/llvm/lib/Target/TargetLoweringObjectFile.cpp b/llvm/lib/Target/TargetLoweringObjectFile.cpp
index b2b69025851..fd4936e1904 100644
--- a/llvm/lib/Target/TargetLoweringObjectFile.cpp
+++ b/llvm/lib/Target/TargetLoweringObjectFile.cpp
@@ -174,7 +174,7 @@ SectionKind TargetLoweringObjectFile::getKindForGlobal(const GlobalValue *GV,
// If the global is required to have a unique address, it can't be put
// into a mergable section: just drop it into the general read-only
// section instead.
- if (!GVar->hasUnnamedAddr())
+ if (!GVar->hasGlobalUnnamedAddr())
return SectionKind::getReadOnly();
// If initializer is a null-terminated string, put it in a "cstring"
diff --git a/llvm/lib/Transforms/IPO/ConstantMerge.cpp b/llvm/lib/Transforms/IPO/ConstantMerge.cpp
index 11f40e86460..65b042534f3 100644
--- a/llvm/lib/Transforms/IPO/ConstantMerge.cpp
+++ b/llvm/lib/Transforms/IPO/ConstantMerge.cpp
@@ -57,7 +57,7 @@ static bool IsBetterCanonical(const GlobalVariable &A,
if (A.hasLocalLinkage() && !B.hasLocalLinkage())
return false;
- return A.hasUnnamedAddr();
+ return A.hasGlobalUnnamedAddr();
}
static unsigned getAlignment(GlobalVariable *GV) {
@@ -152,11 +152,11 @@ static bool mergeConstants(Module &M) {
if (!Slot || Slot == GV)
continue;
- if (!Slot->hasUnnamedAddr() && !GV->hasUnnamedAddr())
+ if (!Slot->hasGlobalUnnamedAddr() && !GV->hasGlobalUnnamedAddr())
continue;
- if (!GV->hasUnnamedAddr())
- Slot->setUnnamedAddr(false);
+ if (!GV->hasGlobalUnnamedAddr())
+ Slot->setUnnamedAddr(GlobalValue::UnnamedAddr::None);
// Make all uses of the duplicate constant use the canonical version.
Replacements.push_back(std::make_pair(GV, Slot));
diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp
index e66ed8359ff..ded55dbb443 100644
--- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp
+++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp
@@ -1942,8 +1942,7 @@ static bool processInternalGlobal(
static bool
processGlobal(GlobalValue &GV, TargetLibraryInfo *TLI,
function_ref<DominatorTree &(Function &)> LookupDomTree) {
- // Do more involved optimizations if the global is internal.
- if (!GV.hasLocalLinkage())
+ if (GV.getName().startswith("llvm."))
return false;
GlobalStatus GS;
@@ -1952,12 +1951,20 @@ processGlobal(GlobalValue &GV, TargetLibraryInfo *TLI,
return false;
bool Changed = false;
- if (!GS.IsCompared && !GV.hasUnnamedAddr()) {
- GV.setUnnamedAddr(true);
- NumUnnamed++;
- Changed = true;
+ if (!GS.IsCompared && !GV.hasGlobalUnnamedAddr()) {
+ auto NewUnnamedAddr = GV.hasLocalLinkage() ? GlobalValue::UnnamedAddr::Global
+ : GlobalValue::UnnamedAddr::Local;
+ if (NewUnnamedAddr != GV.getUnnamedAddr()) {
+ GV.setUnnamedAddr(NewUnnamedAddr);
+ NumUnnamed++;
+ Changed = true;
+ }
}
+ // Do more involved optimizations if the global is internal.
+ if (!GV.hasLocalLinkage())
+ return Changed;
+
auto *GVar = dyn_cast<GlobalVariable>(&GV);
if (!GVar)
return Changed;
diff --git a/llvm/lib/Transforms/IPO/MergeFunctions.cpp b/llvm/lib/Transforms/IPO/MergeFunctions.cpp
index 27caa07c165..adf0d3f680b 100644
--- a/llvm/lib/Transforms/IPO/MergeFunctions.cpp
+++ b/llvm/lib/Transforms/IPO/MergeFunctions.cpp
@@ -1637,7 +1637,7 @@ void MergeFunctions::replaceDirectCallers(Function *Old, Function *New) {
// Replace G with an alias to F if possible, or else a thunk to F. Deletes G.
void MergeFunctions::writeThunkOrAlias(Function *F, Function *G) {
- if (HasGlobalAliases && G->hasUnnamedAddr()) {
+ if (HasGlobalAliases && G->hasGlobalUnnamedAddr()) {
if (G->hasExternalLinkage() || G->hasLocalLinkage() ||
G->hasWeakLinkage()) {
writeAlias(F, G);
diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index 08f148139a2..16a55527c20 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -832,7 +832,7 @@ static GlobalVariable *createPrivateGlobalForString(Module &M, StringRef Str,
GlobalVariable *GV =
new GlobalVariable(M, StrConst->getType(), true,
GlobalValue::PrivateLinkage, StrConst, kAsanGenPrefix);
- if (AllowMerging) GV->setUnnamedAddr(true);
+ if (AllowMerging) GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
GV->setAlignment(1); // Strings may not be merged w/o setting align 1.
return GV;
}
@@ -849,7 +849,7 @@ static GlobalVariable *createPrivateGlobalForSourceLoc(Module &M,
auto GV = new GlobalVariable(M, LocStruct->getType(), true,
GlobalValue::PrivateLinkage, LocStruct,
kAsanGenPrefix);
- GV->setUnnamedAddr(true);
+ GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
return GV;
}
diff --git a/llvm/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp
index 40a9fce7b0b..eafab784e57 100644
--- a/llvm/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp
@@ -137,7 +137,7 @@ static GlobalVariable *createPrivateGlobalForString(Module &M, StringRef Str,
new GlobalVariable(M, StrConst->getType(), true,
GlobalValue::PrivateLinkage, StrConst, "");
if (AllowMerging)
- GV->setUnnamedAddr(true);
+ GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
GV->setAlignment(1); // Strings may not be merged w/o setting align 1.
return GV;
}
diff --git a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp
index 9b19833cb75..6b2df2a1d9d 100644
--- a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp
+++ b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp
@@ -691,7 +691,7 @@ bool GCOVProfiler::emitProfileArcs() {
FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
Function *F = Function::Create(FTy, GlobalValue::InternalLinkage,
"__llvm_gcov_init", M);
- F->setUnnamedAddr(true);
+ F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
F->setLinkage(GlobalValue::InternalLinkage);
F->addFnAttr(Attribute::NoInline);
if (Options.NoRedZone)
@@ -766,7 +766,7 @@ GlobalVariable *GCOVProfiler::buildEdgeLookupTable(
ConstantArray::get(EdgeTableTy,
makeArrayRef(&EdgeTable[0],TableSize)),
"__llvm_gcda_edge_table");
- EdgeTableGV->setUnnamedAddr(true);
+ EdgeTableGV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
return EdgeTableGV;
}
@@ -840,7 +840,7 @@ GlobalVariable *GCOVProfiler::getEdgeStateValue() {
ConstantInt::get(Type::getInt32Ty(*Ctx),
0xffffffff),
"__llvm_gcov_global_state_pred");
- GV->setUnnamedAddr(true);
+ GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
}
return GV;
}
@@ -852,7 +852,7 @@ Function *GCOVProfiler::insertCounterWriteout(
if (!WriteoutF)
WriteoutF = Function::Create(WriteoutFTy, GlobalValue::InternalLinkage,
"__llvm_gcov_writeout", M);
- WriteoutF->setUnnamedAddr(true);
+ WriteoutF->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
WriteoutF->addFnAttr(Attribute::NoInline);
if (Options.NoRedZone)
WriteoutF->addFnAttr(Attribute::NoRedZone);
@@ -912,7 +912,7 @@ Function *GCOVProfiler::insertCounterWriteout(
void GCOVProfiler::insertIndirectCounterIncrement() {
Function *Fn =
cast<Function>(GCOVProfiler::getIncrementIndirectCounterFunc());
- Fn->setUnnamedAddr(true);
+ Fn->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
Fn->setLinkage(GlobalValue::InternalLinkage);
Fn->addFnAttr(Attribute::NoInline);
if (Options.NoRedZone)
@@ -969,7 +969,7 @@ insertFlush(ArrayRef<std::pair<GlobalVariable*, MDNode*> > CountersBySP) {
"__llvm_gcov_flush", M);
else
FlushF->setLinkage(GlobalValue::InternalLinkage);
- FlushF->setUnnamedAddr(true);
+ FlushF->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
FlushF->addFnAttr(Attribute::NoInline);
if (Options.NoRedZone)
FlushF->addFnAttr(Attribute::NoRedZone);
diff --git a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
index 7bb3bdc1137..a3fc16c9a9f 100644
--- a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
+++ b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
@@ -506,7 +506,7 @@ void InstrProfiling::emitRegistration() {
auto *RegisterFTy = FunctionType::get(VoidTy, false);
auto *RegisterF = Function::Create(RegisterFTy, GlobalValue::InternalLinkage,
getInstrProfRegFuncsName(), M);
- RegisterF->setUnnamedAddr(true);
+ RegisterF->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
if (Options.NoRedZone) RegisterF->addFnAttr(Attribute::NoRedZone);
auto *RuntimeRegisterTy = FunctionType::get(VoidTy, VoidPtrTy, false);
@@ -606,7 +606,7 @@ void InstrProfiling::emitInitialization() {
auto *F = Function::Create(FunctionType::get(VoidTy, false),
GlobalValue::InternalLinkage,
getInstrProfInitFuncName(), M);
- F->setUnnamedAddr(true);
+ F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
F->addFnAttr(Attribute::NoInline);
if (Options.NoRedZone) F->addFnAttr(Attribute::NoRedZone);
diff --git a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
index d99d4b6e596..f923673484f 100644
--- a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
@@ -777,7 +777,7 @@ bool LoopIdiomRecognize::processLoopStridedStore(
GlobalVariable *GV = new GlobalVariable(*M, PatternValue->getType(), true,
GlobalValue::PrivateLinkage,
PatternValue, ".memset_pattern");
- GV->setUnnamedAddr(true); // Ok to merge these.
+ GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); // Ok to merge these.
GV->setAlignment(16);
Value *PatternPtr = ConstantExpr::getBitCast(GV, Int8PtrTy);
NewCall = Builder.CreateCall(MSP, {BasePtr, PatternPtr, NumBytes});
diff --git a/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp b/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp
index 92e7fbc7e69..fcb25baf321 100644
--- a/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp
+++ b/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp
@@ -64,7 +64,7 @@ bool FunctionImportGlobalProcessing::doPromoteLocalToGlobal(
// of the module and recorded in the summary index for use when importing
// from that module.
auto *GVar = dyn_cast<GlobalVariable>(SGV);
- if (GVar && GVar->isConstant() && GVar->hasUnnamedAddr())
+ if (GVar && GVar->isConstant() && GVar->hasGlobalUnnamedAddr())
return false;
if (GVar && GVar->hasSection())
diff --git a/llvm/lib/Transforms/Utils/GlobalStatus.cpp b/llvm/lib/Transforms/Utils/GlobalStatus.cpp
index 8be42aed972..266be41fbea 100644
--- a/llvm/lib/Transforms/Utils/GlobalStatus.cpp
+++ b/llvm/lib/Transforms/Utils/GlobalStatus.cpp
@@ -105,7 +105,7 @@ static bool analyzeGlobalAux(const Value *V, GlobalStatus &GS,
}
}
- if (StoredVal == GV->getInitializer()) {
+ if (GV->hasInitializer() && StoredVal == GV->getInitializer()) {
if (GS.StoredType < GlobalStatus::InitializerStored)
GS.StoredType = GlobalStatus::InitializerStored;
} else if (isa<LoadInst>(StoredVal) &&
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index ec2c1af97ea..8f35f887c0b 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -4540,7 +4540,7 @@ SwitchLookupTable::SwitchLookupTable(
Array = new GlobalVariable(M, ArrayTy, /*constant=*/true,
GlobalVariable::PrivateLinkage, Initializer,
"switch.table");
- Array->setUnnamedAddr(true);
+ Array->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
Kind = ArrayKind;
}
OpenPOWER on IntegriCloud