[llvm] edd819c - [AIX] supporting the visibility attribute for aix assembly
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 9 13:15:33 PDT 2020
Author: diggerlin
Date: 2020-06-09T16:15:06-04:00
New Revision: edd819c7576b5183f0d9ef90c48bf903e22035d0
URL: https://github.com/llvm/llvm-project/commit/edd819c7576b5183f0d9ef90c48bf903e22035d0
DIFF: https://github.com/llvm/llvm-project/commit/edd819c7576b5183f0d9ef90c48bf903e22035d0.diff
LOG: [AIX] supporting the visibility attribute for aix assembly
SUMMARY:
in the aix assembly , it do not have .hidden and .protected directive.
in current llvm. if a function or a variable which has visibility attribute, it will generate something like the .hidden or .protected , it can not recognize by aix as.
in aix assembly, the visibility attribute are support in the pseudo-op like
.extern Name [ , Visibility ]
.globl Name [, Visibility ]
.weak Name [, Visibility ]
in this patch, we implement the visibility attribute for the global variable, function or extern function .
for example.
extern __attribute__ ((visibility ("hidden"))) int
bar(int* ip);
__attribute__ ((visibility ("hidden"))) int b = 0;
__attribute__ ((visibility ("hidden"))) int
foo(int* ip){
return (*ip)++;
}
the visibility of .comm linkage do not support , we will have a separate patch for it.
we have the unsupported cases ("default" and "internal") , we will implement them in a a separate patch for it.
Reviewers: Jason Liu ,hubert.reinterpretcast,James Henderson
Differential Revision: https://reviews.llvm.org/D75866
Added:
Modified:
llvm/include/llvm/BinaryFormat/XCOFF.h
llvm/include/llvm/CodeGen/AsmPrinter.h
llvm/include/llvm/MC/MCAsmInfo.h
llvm/include/llvm/MC/MCStreamer.h
llvm/include/llvm/MC/MCSymbolXCOFF.h
llvm/include/llvm/MC/MCXCOFFStreamer.h
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
llvm/lib/MC/MCAsmInfoXCOFF.cpp
llvm/lib/MC/MCAsmStreamer.cpp
llvm/lib/MC/MCStreamer.cpp
llvm/lib/MC/MCXCOFFStreamer.cpp
llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/BinaryFormat/XCOFF.h b/llvm/include/llvm/BinaryFormat/XCOFF.h
index 0b0040c418a8..5a7ce80a2f62 100644
--- a/llvm/include/llvm/BinaryFormat/XCOFF.h
+++ b/llvm/include/llvm/BinaryFormat/XCOFF.h
@@ -178,6 +178,17 @@ enum SymbolType : uint8_t {
XTY_CM = 3 ///< Common csect definition. For uninitialized storage.
};
+/// Values for visibility as they would appear when encoded in the high 4 bits
+/// of the 16-bit unsigned n_type field of symbol table entries. Valid for
+/// 32-bit XCOFF only when the vstamp in the auxiliary header is greater than 1.
+enum VisibilityType : uint16_t {
+ SYM_V_UNSPECIFIED = 0x0000,
+ SYM_V_INTERNAL = 0x1000,
+ SYM_V_HIDDEN = 0x2000,
+ SYM_V_PROTECTED = 0x3000,
+ SYM_V_EXPORTED = 0x4000
+};
+
// Relocation types, defined in `/usr/include/reloc.h`.
enum RelocationType : uint8_t {
R_POS = 0x00, ///< Positive relocation. Provides the address of the referenced
diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h
index ff9ec9cfa6b8..939a5cb08a37 100644
--- a/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -659,7 +659,7 @@ class AsmPrinter : public MachineFunctionPass {
/// This emits linkage information about \p GVSym based on \p GV, if this is
/// supported by the target.
- void emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const;
+ virtual void emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const;
/// Return the alignment for the specified \p GV.
static Align getGVAlignment(const GlobalValue *GV, const DataLayout &DL,
diff --git a/llvm/include/llvm/MC/MCAsmInfo.h b/llvm/include/llvm/MC/MCAsmInfo.h
index e7e48a318c8f..aac1e059302c 100644
--- a/llvm/include/llvm/MC/MCAsmInfo.h
+++ b/llvm/include/llvm/MC/MCAsmInfo.h
@@ -93,6 +93,10 @@ class MCAsmInfo {
/// constants into comdat sections.
bool HasCOFFComdatConstants = false;
+ /// True if this is an XCOFF target that supports visibility attributes as
+ /// part of .global, .weak, .extern, and .comm. Default is false.
+ bool HasVisibilityOnlyWithLinkage = false;
+
/// This is the maximum possible length of an instruction, which is needed to
/// compute the size of an inline asm. Defaults to 4.
unsigned MaxInstLength = 4;
@@ -506,6 +510,9 @@ class MCAsmInfo {
bool hasMachoTBSSDirective() const { return HasMachoTBSSDirective; }
bool hasCOFFAssociativeComdats() const { return HasCOFFAssociativeComdats; }
bool hasCOFFComdatConstants() const { return HasCOFFComdatConstants; }
+ bool hasVisibilityOnlyWithLinkage() const {
+ return HasVisibilityOnlyWithLinkage;
+ }
/// Returns the maximum possible encoded instruction size in bytes. If \p STI
/// is null, this should be the maximum size for any subtarget.
diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h
index d62fcf7c4fcf..f77ecb5af50c 100644
--- a/llvm/include/llvm/MC/MCStreamer.h
+++ b/llvm/include/llvm/MC/MCStreamer.h
@@ -565,6 +565,15 @@ class MCStreamer {
MCSymbol *CsectSym,
unsigned ByteAlignment);
+ /// Emit a symbol's linkage and visibilty with a linkage directive for XCOFF.
+ ///
+ /// \param Symbol - The symbol to emit.
+ /// \param Linkage - The linkage of the symbol to emit.
+ /// \param Visibility - The visibility of the symbol to emit or MCSA_Invalid
+ /// if the symbol does not have an explicit visibility.
+ virtual void emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol,
+ MCSymbolAttr Linkage,
+ MCSymbolAttr Visibility);
/// Emit an ELF .size directive.
///
/// This corresponds to an assembler statement such as:
diff --git a/llvm/include/llvm/MC/MCSymbolXCOFF.h b/llvm/include/llvm/MC/MCSymbolXCOFF.h
index 6815f421d598..e5bea10fd5d5 100644
--- a/llvm/include/llvm/MC/MCSymbolXCOFF.h
+++ b/llvm/include/llvm/MC/MCSymbolXCOFF.h
@@ -53,9 +53,14 @@ class MCSymbolXCOFF : public MCSymbol {
void setRepresentedCsect(MCSectionXCOFF *C);
+ void setVisibilityType(XCOFF::VisibilityType SVT) { VisibilityType = SVT; };
+
+ XCOFF::VisibilityType getVisibilityType() const { return VisibilityType; }
+
private:
Optional<XCOFF::StorageClass> StorageClass;
MCSectionXCOFF *RepresentedCsect = nullptr;
+ XCOFF::VisibilityType VisibilityType = XCOFF::SYM_V_UNSPECIFIED;
};
} // end namespace llvm
diff --git a/llvm/include/llvm/MC/MCXCOFFStreamer.h b/llvm/include/llvm/MC/MCXCOFFStreamer.h
index cd5abd2a226f..416a55f2c8fc 100644
--- a/llvm/include/llvm/MC/MCXCOFFStreamer.h
+++ b/llvm/include/llvm/MC/MCXCOFFStreamer.h
@@ -29,6 +29,9 @@ class MCXCOFFStreamer : public MCObjectStreamer {
void emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size,
MCSymbol *CsectSym,
unsigned ByteAlign) override;
+ void emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol,
+ MCSymbolAttr Linkage,
+ MCSymbolAttr Visibility) override;
};
} // end namespace llvm
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 0aaf5a487c15..45ac517f3c68 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -700,7 +700,8 @@ void AsmPrinter::emitFunctionHeader() {
MF->setSection(getObjFileLowering().SectionForGlobal(&F, TM));
OutStreamer->SwitchSection(MF->getSection());
- emitVisibility(CurrentFnSym, F.getVisibility());
+ if (!MAI->hasVisibilityOnlyWithLinkage())
+ emitVisibility(CurrentFnSym, F.getVisibility());
if (MAI->needsFunctionDescriptors() &&
F.getLinkage() != GlobalValue::InternalLinkage)
@@ -1517,23 +1518,29 @@ bool AsmPrinter::doFinalization(Module &M) {
MCSymbol *Name = getSymbol(&F);
// Function getSymbol gives us the function descriptor symbol for XCOFF.
- if (TM.getTargetTriple().isOSBinFormatXCOFF() && !F.isIntrinsic()) {
- // Get the function entry point symbol.
- MCSymbol *FnEntryPointSym = TLOF.getFunctionEntryPointSymbol(&F, TM);
- if (cast<MCSymbolXCOFF>(FnEntryPointSym)->hasRepresentedCsectSet())
- // Emit linkage for the function entry point.
- emitLinkage(&F, FnEntryPointSym);
+ if (!TM.getTargetTriple().isOSBinFormatXCOFF()) {
+ GlobalValue::VisibilityTypes V = F.getVisibility();
+ if (V == GlobalValue::DefaultVisibility)
+ continue;
- // Emit linkage for the function descriptor.
- emitLinkage(&F, Name);
+ emitVisibility(Name, V, false);
+ continue;
}
- GlobalValue::VisibilityTypes V = F.getVisibility();
- if (V == GlobalValue::DefaultVisibility)
+ if (F.isIntrinsic())
continue;
- emitVisibility(Name, V, false);
+ // Handle the XCOFF case.
+ // Variable `Name` is the function descriptor symbol (see above). Get the
+ // function entry point symbol.
+ MCSymbol *FnEntryPointSym = TLOF.getFunctionEntryPointSymbol(&F, TM);
+ if (cast<MCSymbolXCOFF>(FnEntryPointSym)->hasRepresentedCsectSet())
+ // Emit linkage for the function entry point.
+ emitLinkage(&F, FnEntryPointSym);
+
+ // Emit linkage for the function descriptor.
+ emitLinkage(&F, Name);
}
// Emit the remarks section contents.
diff --git a/llvm/lib/MC/MCAsmInfoXCOFF.cpp b/llvm/lib/MC/MCAsmInfoXCOFF.cpp
index bf28dac6746e..4a848426c196 100644
--- a/llvm/lib/MC/MCAsmInfoXCOFF.cpp
+++ b/llvm/lib/MC/MCAsmInfoXCOFF.cpp
@@ -14,6 +14,7 @@ void MCAsmInfoXCOFF::anchor() {}
MCAsmInfoXCOFF::MCAsmInfoXCOFF() {
IsLittleEndian = false;
+ HasVisibilityOnlyWithLinkage = true;
PrivateGlobalPrefix = "L..";
PrivateLabelPrefix = "L..";
SupportsQuotedNames = false;
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index df688f43fe0e..9a86895a2fe1 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -171,6 +171,10 @@ class MCAsmStreamer final : public MCStreamer {
void emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size,
MCSymbol *CsectSym,
unsigned ByteAlign) override;
+ void emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol,
+ MCSymbolAttr Linakge,
+ MCSymbolAttr Visibility) override;
+
void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) override;
@@ -791,6 +795,41 @@ void MCAsmStreamer::emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym,
EmitEOL();
}
+void MCAsmStreamer::emitXCOFFSymbolLinkageWithVisibility(
+ MCSymbol *Symbol, MCSymbolAttr Linkage, MCSymbolAttr Visibility) {
+
+ switch (Linkage) {
+ case MCSA_Global:
+ OS << MAI->getGlobalDirective();
+ break;
+ case MCSA_Weak:
+ OS << MAI->getWeakDirective();
+ break;
+ case MCSA_Extern:
+ OS << "\t.extern\t";
+ break;
+ default:
+ report_fatal_error("unhandled linkage type");
+ }
+
+ Symbol->print(OS, MAI);
+
+ switch (Visibility) {
+ case MCSA_Invalid:
+ // Nothing to do.
+ break;
+ case MCSA_Hidden:
+ OS << ",hidden";
+ break;
+ case MCSA_Protected:
+ OS << ",protected";
+ break;
+ default:
+ report_fatal_error("unexpected value for Visibility type");
+ }
+ EmitEOL();
+}
+
void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
assert(MAI->hasDotTypeDotSizeDirective());
OS << "\t.size\t";
diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp
index be5d588140ba..0b650ef936bf 100644
--- a/llvm/lib/MC/MCStreamer.cpp
+++ b/llvm/lib/MC/MCStreamer.cpp
@@ -1063,6 +1063,14 @@ void MCStreamer::emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size,
unsigned ByteAlign) {
llvm_unreachable("this directive only supported on XCOFF targets");
}
+
+void MCStreamer::emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol,
+ MCSymbolAttr Linkage,
+ MCSymbolAttr Visibility) {
+ llvm_unreachable("emitXCOFFSymbolLinkageWithVisibility is only supported on "
+ "XCOFF targets");
+}
+
void MCStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {}
void MCStreamer::emitELFSymverDirective(StringRef AliasName,
const MCSymbol *Aliasee) {}
diff --git a/llvm/lib/MC/MCXCOFFStreamer.cpp b/llvm/lib/MC/MCXCOFFStreamer.cpp
index ad0c2c76b4a2..ec9e89fac416 100644
--- a/llvm/lib/MC/MCXCOFFStreamer.cpp
+++ b/llvm/lib/MC/MCXCOFFStreamer.cpp
@@ -48,12 +48,30 @@ bool MCXCOFFStreamer::emitSymbolAttribute(MCSymbol *Sym,
Symbol->setStorageClass(XCOFF::C_WEAKEXT);
Symbol->setExternal(true);
break;
+ case llvm::MCSA_Hidden:
+ Symbol->setVisibilityType(XCOFF::SYM_V_HIDDEN);
+ break;
+ case llvm::MCSA_Protected:
+ Symbol->setVisibilityType(XCOFF::SYM_V_PROTECTED);
+ break;
default:
report_fatal_error("Not implemented yet.");
}
return true;
}
+void MCXCOFFStreamer::emitXCOFFSymbolLinkageWithVisibility(
+ MCSymbol *Symbol, MCSymbolAttr Linkage, MCSymbolAttr Visibility) {
+
+ emitSymbolAttribute(Symbol, Linkage);
+
+ // When the caller passes `MCSA_Invalid` for the visibility, do not emit one.
+ if (Visibility == MCSA_Invalid)
+ return;
+
+ emitSymbolAttribute(Symbol, Visibility);
+}
+
void MCXCOFFStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) {
getAssembler().registerSymbol(*Symbol);
diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index 051c800600c5..d86aa576ef85 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -168,6 +168,8 @@ class PPCAIXAsmPrinter : public PPCAsmPrinter {
void emitFunctionDescriptor() override;
void emitEndOfAsmFile(Module &) override;
+
+ void emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const override;
};
} // end anonymous namespace
@@ -1577,6 +1579,61 @@ void PPCLinuxAsmPrinter::emitFunctionBodyEnd() {
}
}
+void PPCAIXAsmPrinter::emitLinkage(const GlobalValue *GV,
+ MCSymbol *GVSym) const {
+
+ assert(MAI->hasVisibilityOnlyWithLinkage() &&
+ "AIX's linkage directives take a visibility setting.");
+
+ MCSymbolAttr LinkageAttr = MCSA_Invalid;
+ switch (GV->getLinkage()) {
+ case GlobalValue::ExternalLinkage:
+ LinkageAttr = GV->isDeclaration() ? MCSA_Extern : MCSA_Global;
+ break;
+ case GlobalValue::LinkOnceAnyLinkage:
+ case GlobalValue::LinkOnceODRLinkage:
+ case GlobalValue::WeakAnyLinkage:
+ case GlobalValue::WeakODRLinkage:
+ case GlobalValue::ExternalWeakLinkage:
+ LinkageAttr = MCSA_Weak;
+ break;
+ case GlobalValue::AvailableExternallyLinkage:
+ LinkageAttr = MCSA_Extern;
+ break;
+ case GlobalValue::PrivateLinkage:
+ return;
+ case GlobalValue::InternalLinkage:
+ assert(MAI->hasDotLGloblDirective() &&
+ "Expecting .lglobl to be supported for AIX.");
+ OutStreamer->emitSymbolAttribute(GVSym, MCSA_LGlobal);
+ return;
+ case GlobalValue::AppendingLinkage:
+ llvm_unreachable("Should never emit this");
+ case GlobalValue::CommonLinkage:
+ llvm_unreachable("CommonLinkage of XCOFF should not come to this path");
+ }
+
+ assert(LinkageAttr != MCSA_Invalid && "LinkageAttr should not MCSA_Invalid.");
+
+ MCSymbolAttr VisibilityAttr = MCSA_Invalid;
+ switch (GV->getVisibility()) {
+
+ // TODO: "exported" and "internal" Visibility needs to go here.
+
+ case GlobalValue::DefaultVisibility:
+ break;
+ case GlobalValue::HiddenVisibility:
+ VisibilityAttr = MAI->getHiddenVisibilityAttr();
+ break;
+ case GlobalValue::ProtectedVisibility:
+ VisibilityAttr = MAI->getProtectedVisibilityAttr();
+ break;
+ }
+
+ OutStreamer->emitXCOFFSymbolLinkageWithVisibility(GVSym, LinkageAttr,
+ VisibilityAttr);
+}
+
void PPCAIXAsmPrinter::SetupMachineFunction(MachineFunction &MF) {
// Setup CurrentFnDescSym and its containing csect.
MCSectionXCOFF *FnDescSec =
More information about the llvm-commits
mailing list