[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
This commit is contained in:
diggerlin 2020-06-09 16:15:06 -04:00
parent bdf48658a5
commit d98ed2e336
12 changed files with 178 additions and 13 deletions

View File

@ -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

View File

@ -659,7 +659,7 @@ public:
/// 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,

View File

@ -93,6 +93,10 @@ protected:
/// 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 @@ public:
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.

View File

@ -565,6 +565,15 @@ public:
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:

View File

@ -53,9 +53,14 @@ public:
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

View File

@ -29,6 +29,9 @@ public:
void emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size,
MCSymbol *CsectSym,
unsigned ByteAlign) override;
void emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol,
MCSymbolAttr Linkage,
MCSymbolAttr Visibility) override;
};
} // end namespace llvm

View File

@ -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.

View File

@ -14,6 +14,7 @@ void MCAsmInfoXCOFF::anchor() {}
MCAsmInfoXCOFF::MCAsmInfoXCOFF() {
IsLittleEndian = false;
HasVisibilityOnlyWithLinkage = true;
PrivateGlobalPrefix = "L..";
PrivateLabelPrefix = "L..";
SupportsQuotedNames = false;

View File

@ -171,6 +171,10 @@ public:
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";

View File

@ -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) {}

View File

@ -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);

View File

@ -168,6 +168,8 @@ public:
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 =