[llvm] b98b170 - [XCOFF] Enable symbol alias for AIX
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 22 07:04:12 PDT 2020
Author: jasonliu
Date: 2020-07-22T14:03:55Z
New Revision: b98b1700efe7709e7bf7eaec25cfbfd9fb490357
URL: https://github.com/llvm/llvm-project/commit/b98b1700efe7709e7bf7eaec25cfbfd9fb490357
DIFF: https://github.com/llvm/llvm-project/commit/b98b1700efe7709e7bf7eaec25cfbfd9fb490357.diff
LOG: [XCOFF] Enable symbol alias for AIX
Summary:
AIX assembly's .set directive is not usable for aliasing purpose.
We need to use extra-label-at-defintion strategy to generate symbol
aliasing on AIX.
Reviewed By: DiggerLin, Xiangling_L
Differential Revision: https://reviews.llvm.org/D83252
Added:
llvm/test/CodeGen/PowerPC/aix-alias-unsupported.ll
Modified:
llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
llvm/include/llvm/Target/TargetLoweringObjectFile.h
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
llvm/lib/Target/PowerPC/PPCISelLowering.cpp
llvm/test/CodeGen/PowerPC/aix-alias.ll
Removed:
################################################################################
diff --git a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
index 6e2c0973e354..a333d971bbcb 100644
--- a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
+++ b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
@@ -246,7 +246,7 @@ class TargetLoweringObjectFileXCOFF : public TargetLoweringObjectFile {
const Constant *C,
Align &Alignment) const override;
- static XCOFF::StorageClass getStorageClassForGlobal(const GlobalObject *GO);
+ static XCOFF::StorageClass getStorageClassForGlobal(const GlobalValue *GV);
MCSection *
getSectionForFunctionDescriptor(const Function *F,
@@ -263,7 +263,7 @@ class TargetLoweringObjectFileXCOFF : public TargetLoweringObjectFile {
MCSymbol *getTargetSymbol(const GlobalValue *GV,
const TargetMachine &TM) const override;
- MCSymbol *getFunctionEntryPointSymbol(const Function *F,
+ MCSymbol *getFunctionEntryPointSymbol(const GlobalValue *Func,
const TargetMachine &TM) const override;
};
diff --git a/llvm/include/llvm/Target/TargetLoweringObjectFile.h b/llvm/include/llvm/Target/TargetLoweringObjectFile.h
index cc6c93b6ee2b..0cb888e75078 100644
--- a/llvm/include/llvm/Target/TargetLoweringObjectFile.h
+++ b/llvm/include/llvm/Target/TargetLoweringObjectFile.h
@@ -247,7 +247,8 @@ class TargetLoweringObjectFile : public MCObjectFileInfo {
/// If supported, return the function entry point symbol.
/// Otherwise, returns nulltpr.
- virtual MCSymbol *getFunctionEntryPointSymbol(const Function *F,
+ /// Func must be a function or an alias which has a function as base object.
+ virtual MCSymbol *getFunctionEntryPointSymbol(const GlobalValue *Func,
const TargetMachine &TM) const {
return nullptr;
}
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index f8f7b74baf91..b50cae89b349 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -1390,16 +1390,7 @@ void AsmPrinter::emitGlobalGOTEquivs() {
void AsmPrinter::emitGlobalIndirectSymbol(Module &M,
const GlobalIndirectSymbol& GIS) {
MCSymbol *Name = getSymbol(&GIS);
-
- if (GIS.hasExternalLinkage() || !MAI->getWeakRefDirective())
- OutStreamer->emitSymbolAttribute(Name, MCSA_Global);
- else if (GIS.hasWeakLinkage() || GIS.hasLinkOnceLinkage())
- OutStreamer->emitSymbolAttribute(Name, MCSA_WeakReference);
- else
- assert(GIS.hasLocalLinkage() && "Invalid alias or ifunc linkage");
-
bool IsFunction = GIS.getValueType()->isFunctionTy();
-
// Treat bitcasts of functions as functions also. This is important at least
// on WebAssembly where object and function addresses can't alias each other.
if (!IsFunction)
@@ -1408,6 +1399,30 @@ void AsmPrinter::emitGlobalIndirectSymbol(Module &M,
IsFunction =
CE->getOperand(0)->getType()->getPointerElementType()->isFunctionTy();
+ // AIX's assembly directive `.set` is not usable for aliasing purpose,
+ // so AIX has to use the extra-label-at-definition strategy. At this
+ // point, all the extra label is emitted, we just have to emit linkage for
+ // those labels.
+ if (TM.getTargetTriple().isOSBinFormatXCOFF()) {
+ assert(!isa<GlobalIFunc>(GIS) && "IFunc is not supported on AIX.");
+ assert(MAI->hasVisibilityOnlyWithLinkage() &&
+ "Visibility should be handled with emitLinkage() on AIX.");
+ emitLinkage(&GIS, Name);
+ // If it's a function, also emit linkage for aliases of function entry
+ // point.
+ if (IsFunction)
+ emitLinkage(&GIS,
+ getObjFileLowering().getFunctionEntryPointSymbol(&GIS, TM));
+ return;
+ }
+
+ if (GIS.hasExternalLinkage() || !MAI->getWeakRefDirective())
+ OutStreamer->emitSymbolAttribute(Name, MCSA_Global);
+ else if (GIS.hasWeakLinkage() || GIS.hasLinkOnceLinkage())
+ OutStreamer->emitSymbolAttribute(Name, MCSA_WeakReference);
+ else
+ assert(GIS.hasLocalLinkage() && "Invalid alias or ifunc linkage");
+
// Set the symbol type to function if the alias has a function type.
// This affects codegen when the aliasee is not a function.
if (IsFunction)
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index 27bebe503ce6..653127782595 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -2125,9 +2125,11 @@ const MCExpr *TargetLoweringObjectFileXCOFF::lowerRelativeReference(
report_fatal_error("XCOFF not yet implemented.");
}
-XCOFF::StorageClass TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(
- const GlobalObject *GO) {
- switch (GO->getLinkage()) {
+XCOFF::StorageClass
+TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(const GlobalValue *GV) {
+ assert(!isa<GlobalIFunc>(GV) && "GlobalIFunc is not supported on AIX.");
+
+ switch (GV->getLinkage()) {
case GlobalValue::InternalLinkage:
case GlobalValue::PrivateLinkage:
return XCOFF::C_HIDEXT;
@@ -2149,10 +2151,16 @@ XCOFF::StorageClass TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(
}
MCSymbol *TargetLoweringObjectFileXCOFF::getFunctionEntryPointSymbol(
- const Function *F, const TargetMachine &TM) const {
+ const GlobalValue *Func, const TargetMachine &TM) const {
+ assert(
+ isa<Function>(Func) ||
+ (isa<GlobalAlias>(Func) &&
+ isa_and_nonnull<Function>(cast<GlobalAlias>(Func)->getBaseObject())) &&
+ "Func must be a function or an alias which has a function as base "
+ "object.");
SmallString<128> NameStr;
NameStr.push_back('.');
- getNameWithPrefix(NameStr, F, TM);
+ getNameWithPrefix(NameStr, Func, TM);
return getContext().getOrCreateSymbol(NameStr);
}
diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index d26df9a6c7f7..bc869c39e393 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -154,6 +154,10 @@ class PPCAIXAsmPrinter : public PPCAsmPrinter {
SmallPtrSet<MCSymbol *, 8> ExtSymSDNodeSymbols;
static void ValidateGV(const GlobalVariable *GV);
+ // Record a list of GlobalAlias associated with a GlobalObject.
+ // This is used for AIX's extra-label-at-definition aliasing strategy.
+ DenseMap<const GlobalObject *, SmallVector<const GlobalAlias *, 1>>
+ GOAliasMap;
public:
PPCAIXAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
@@ -173,6 +177,8 @@ class PPCAIXAsmPrinter : public PPCAsmPrinter {
void emitFunctionDescriptor() override;
+ void emitFunctionEntryLabel() override;
+
void emitEndOfAsmFile(Module &) override;
void emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const override;
@@ -1729,6 +1735,10 @@ void PPCAIXAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
emitLinkage(GV, EmittedInitSym);
emitAlignment(getGVAlignment(GV, DL), GV);
OutStreamer->emitLabel(EmittedInitSym);
+ // Emit aliasing label for global variable.
+ llvm::for_each(GOAliasMap[GV], [this](const GlobalAlias *Alias) {
+ OutStreamer->emitLabel(getSymbol(Alias));
+ });
emitGlobalConstant(GV->getParent()->getDataLayout(), GV->getInitializer());
}
@@ -1740,6 +1750,13 @@ void PPCAIXAsmPrinter::emitFunctionDescriptor() {
// Emit function descriptor.
OutStreamer->SwitchSection(
cast<MCSymbolXCOFF>(CurrentFnDescSym)->getRepresentedCsect());
+
+ // Emit aliasing label for function descriptor csect.
+ llvm::for_each(GOAliasMap[&MF->getFunction()],
+ [this](const GlobalAlias *Alias) {
+ OutStreamer->emitLabel(getSymbol(Alias));
+ });
+
// Emit function entry point address.
OutStreamer->emitValue(MCSymbolRefExpr::create(CurrentFnSym, OutContext),
PointerSize);
@@ -1755,6 +1772,16 @@ void PPCAIXAsmPrinter::emitFunctionDescriptor() {
OutStreamer->SwitchSection(Current.first, Current.second);
}
+void PPCAIXAsmPrinter::emitFunctionEntryLabel() {
+ PPCAsmPrinter::emitFunctionEntryLabel();
+ // Emit aliasing label for function entry point label.
+ llvm::for_each(
+ GOAliasMap[&MF->getFunction()], [this](const GlobalAlias *Alias) {
+ OutStreamer->emitLabel(
+ getObjFileLowering().getFunctionEntryPointSymbol(Alias, TM));
+ });
+}
+
void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) {
// If there are no functions in this module, we will never need to reference
// the TOC base.
@@ -1790,10 +1817,6 @@ void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) {
}
bool PPCAIXAsmPrinter::doInitialization(Module &M) {
- if (M.alias_size() > 0u)
- report_fatal_error(
- "module has aliases, which LLVM does not yet support for AIX");
-
const bool Result = PPCAsmPrinter::doInitialization(M);
auto setCsectAlignment = [this](const GlobalObject *GO) {
@@ -1819,6 +1842,15 @@ bool PPCAIXAsmPrinter::doInitialization(Module &M) {
for (const auto &F : M)
setCsectAlignment(&F);
+ // Construct an aliasing list for each GlobalObject.
+ for (const auto &Alias : M.aliases()) {
+ const GlobalObject *Base = Alias.getBaseObject();
+ if (!Base)
+ report_fatal_error(
+ "alias without a base object is not yet supported on AIX");
+ GOAliasMap[Base].push_back(&Alias);
+ }
+
return Result;
}
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index fe9ab604ec2f..5db829f8d470 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -5372,10 +5372,9 @@ static SDValue transformCallee(const SDValue &Callee, SelectionDAG &DAG,
UsePlt ? PPCII::MO_PLT : 0);
assert(!isa<GlobalIFunc>(GV) && "IFunc is not supported on AIX.");
- const GlobalObject *GO = cast<GlobalObject>(GV);
const XCOFF::StorageClass SC =
- TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GO);
- return getAIXFuncEntryPointSymbolSDNode(GO->getName(), GO->isDeclaration(),
+ TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GV);
+ return getAIXFuncEntryPointSymbolSDNode(GV->getName(), GV->isDeclaration(),
SC);
}
diff --git a/llvm/test/CodeGen/PowerPC/aix-alias-unsupported.ll b/llvm/test/CodeGen/PowerPC/aix-alias-unsupported.ll
new file mode 100644
index 000000000000..342f7d419f33
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/aix-alias-unsupported.ll
@@ -0,0 +1,6 @@
+; RUN: not --crash llc < %s -mtriple powerpc-ibm-aix-xcoff 2>&1 | FileCheck %s
+; RUN: not --crash llc < %s -mtriple powerpc64-ibm-aix-xcoff 2>&1 | FileCheck %s
+; CHECK: ERROR: alias without a base object is not yet supported on AIX
+
+ at bar = global i32 42
+ at test = alias i32, inttoptr(i32 42 to i32*)
diff --git a/llvm/test/CodeGen/PowerPC/aix-alias.ll b/llvm/test/CodeGen/PowerPC/aix-alias.ll
index 2183c2e8c557..1fdd7c90f5ad 100644
--- a/llvm/test/CodeGen/PowerPC/aix-alias.ll
+++ b/llvm/test/CodeGen/PowerPC/aix-alias.ll
@@ -1,10 +1,116 @@
-; RUN: not --crash llc < %s -mtriple powerpc-ibm-aix-xcoff 2>&1 | FileCheck %s
-; RUN: not --crash llc < %s -mtriple powerpc64-ibm-aix-xcoff 2>&1 | FileCheck %s
+; TODO: Add object generation test when visibility for object generation
+; is implemnted.
-; Check that, while generation of aliases on AIX remains unimplemented, llc dies
-; with an appropriate message instead of generating incorrect output when an
-; alias is encountered.
+; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr4 \
+; RUN: -mattr=-altivec < %s | \
+; RUN: FileCheck --check-prefix=ASM %s
+; RUN: llc -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff -mcpu=pwr4 \
+; RUN: -mattr=-altivec < %s | \
+; RUN: FileCheck --check-prefix=ASM %s
-define i32 @a() { ret i32 0 }
-; CHECK: ERROR: module has aliases
- at b = internal alias i32 (), i32 ()* @a
+ at var = global i32 42
+ at var1 = alias i32, i32* @var
+ at var2 = alias i32, i32* @var1
+ at var_l = linkonce_odr alias i32, i32* @var
+ at var_i = internal alias i32, i32* @var
+ at var_h = hidden alias i32, i32* @var
+ at var_p = protected alias i32, i32* @var
+
+ at array = global [2 x i32] [i32 1, i32 2], align 4
+ at x = global i32* bitcast (i8* getelementptr (i8, i8* bitcast ([2 x i32]* @array to i8*), i64 4) to i32*), align 4
+ at bitcast_alias = alias i32*, i32** @x
+
+define i32 @fun() {
+ ret i32 0
+}
+
+%FunTy = type i32()
+ at fun_weak = weak alias %FunTy, %FunTy* @fun
+ at fun_hidden = hidden alias %FunTy, %FunTy* @fun
+ at fun_ptr = global i32()* @fun_weak
+
+define i32 @test() {
+entry:
+ %tmp = load i32, i32* @var1
+ %tmp1 = load i32, i32* @var2
+ %tmp0 = load i32, i32* @var_i
+ %tmp2 = call i32 @fun()
+ %tmp3 = add i32 %tmp, %tmp2
+ %tmp4 = call i32 @fun_weak()
+ %tmp5 = add i32 %tmp3, %tmp4
+ %tmp6 = add i32 %tmp1, %tmp5
+ %tmp7 = add i32 %tmp6, %tmp0
+ %fun_ptr1 = alloca i32 ()*
+ store i32 ()* @fun_weak, i32 ()** %fun_ptr1
+ %callee.knr.cast = bitcast i32 ()** %fun_ptr1 to i32 ()*
+ %tmp8 = call i32 %callee.knr.cast()
+ %tmp9 = call i32 @fun_hidden()
+ %tmp10 = add i32 %tmp7, %tmp8
+ %tmp11 = add i32 %tmp10, %tmp9
+ ret i32 %tmp11
+}
+
+; ASM: .globl fun[DS]
+; ASM-NEXT: .globl .fun
+; ASM-NEXT: .align 4
+; ASM-NEXT: .csect fun[DS]
+; ASM-NEXT: fun_weak: # @fun
+; ASM-NEXT: fun_hidden:
+; ASM: .csect .text[PR],2
+; ASM-NEXT: .fun:
+; ASM-NEXT: .fun_weak:
+; ASM-NEXT: .fun_hidden:
+; ASM-NEXT: # %bb.0:
+; ASM-NEXT: li 3, 0
+; ASM-NEXT: blr
+; ASM-NEXT: # -- End function
+; ASM: .csect .text[PR],2
+; ASM-NEXT: .test:
+; ASM-NEXT: # %bb.0: # %entry
+; ASM: bl .fun
+; ASM-NEXT: nop
+; ASM: bl .fun_weak
+; ASM-NEXT: nop
+; ASM: bl .fun_hidden
+; ASM: # -- End function
+; ASM-NEXT: .csect .data[RW]
+; ASM-NEXT: .globl var
+; ASM: var:
+; ASM-NEXT: var1:
+; ASM-NEXT: var2:
+; ASM-NEXT: var_l:
+; ASM-NEXT: var_i:
+; ASM-NEXT: var_h:
+; ASM-NEXT: var_p:
+; ASM-NEXT: .vbyte 4, 42
+; ASM-NEXT: .globl array
+; ASM: array:
+; ASM-NEXT: .vbyte 4, 1 # 0x1
+; ASM-NEXT: .vbyte 4, 2 # 0x2
+; ASM-NEXT: .globl x
+; ASM: x:
+; ASM-NEXT: bitcast_alias:
+; ASM-NEXT: .vbyte {{[0-9]+}}, array+4
+; ASM-NEXT: .globl fun_ptr
+; ASM: fun_ptr:
+; ASM-NEXT: .vbyte {{[0-9]+}}, fun_weak
+; ASM-NEXT: .globl var1
+; ASM-NEXT: .globl var2
+; ASM-NEXT: .weak var_l
+; ASM-NEXT: .lglobl var_i
+; ASM-NEXT: .globl var_h,hidden
+; ASM-NEXT: .globl var_p,protected
+; ASM-NEXT: .globl bitcast_alias
+; ASM-NEXT: .weak fun_weak
+; ASM-NEXT: .weak .fun_weak
+; ASM-NEXT: .globl fun_hidden,hidden
+; ASM-NEXT: .globl .fun_hidden,hidden
+; ASM-NEXT: .toc
+; ASM-NEXT: L..C0:
+; ASM-NEXT: .tc var1[TC],var1
+; ASM-NEXT: L..C1:
+; ASM-NEXT: .tc var2[TC],var2
+; ASM-NEXT: L..C2:
+; ASM-NEXT: .tc var_i[TC],var_i
+; ASM-NEXT: L..C3:
+; ASM-NEXT: .tc fun_weak[TC],fun_weak
More information about the llvm-commits
mailing list