forked from OSchip/llvm-project
[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
This commit is contained in:
parent
2a6c871596
commit
b98b1700ef
|
@ -246,7 +246,7 @@ public:
|
|||
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 @@ public:
|
|||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -247,7 +247,8 @@ public:
|
|||
|
||||
/// 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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -154,6 +154,10 @@ private:
|
|||
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 @@ public:
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
@bar = global i32 42
|
||||
@test = alias i32, inttoptr(i32 42 to i32*)
|
|
@ -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
|
||||
@b = internal alias i32 (), i32 ()* @a
|
||||
@var = global i32 42
|
||||
@var1 = alias i32, i32* @var
|
||||
@var2 = alias i32, i32* @var1
|
||||
@var_l = linkonce_odr alias i32, i32* @var
|
||||
@var_i = internal alias i32, i32* @var
|
||||
@var_h = hidden alias i32, i32* @var
|
||||
@var_p = protected alias i32, i32* @var
|
||||
|
||||
@array = global [2 x i32] [i32 1, i32 2], align 4
|
||||
@x = global i32* bitcast (i8* getelementptr (i8, i8* bitcast ([2 x i32]* @array to i8*), i64 4) to i32*), align 4
|
||||
@bitcast_alias = alias i32*, i32** @x
|
||||
|
||||
define i32 @fun() {
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
%FunTy = type i32()
|
||||
@fun_weak = weak alias %FunTy, %FunTy* @fun
|
||||
@fun_hidden = hidden alias %FunTy, %FunTy* @fun
|
||||
@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
|
||||
|
|
Loading…
Reference in New Issue