[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