Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions llvm/include/llvm/MC/MCDirectives.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ enum MCSymbolAttr {
MCSA_WeakDefAutoPrivate, ///< .weak_def_can_be_hidden (MachO)
MCSA_WeakAntiDep, ///< .weak_anti_dep (COFF)
MCSA_Memtag, ///< .memtag (ELF)
MCSA_OSLinkage, ///< symbol uses OS linkage (GOFF)
MCSA_XPLinkage, ///< symbol uses XP linkage (GOFF)
};

enum MCDataRegionType {
Expand Down
9 changes: 9 additions & 0 deletions llvm/include/llvm/MC/MCGOFFAttributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,15 @@ struct PRAttr {
uint32_t SortKey = 0;
};

// Attributes for ER symbols.
struct ERAttr {
GOFF::ESDExecutable Executable = GOFF::ESD_EXE_Unspecified;
GOFF::ESDBindingStrength BindingStrength = GOFF::ESD_BST_Strong;
GOFF::ESDLinkageType Linkage = GOFF::ESD_LT_XPLink;
GOFF::ESDAmode Amode;
GOFF::ESDBindingScope BindingScope = GOFF::ESD_BSC_Unspecified;
};

// Predefined GOFF class names.
constexpr StringLiteral CLASS_CODE = "C_CODE64";
constexpr StringLiteral CLASS_WSA = "C_WSA64";
Expand Down
6 changes: 6 additions & 0 deletions llvm/include/llvm/MC/MCGOFFObjectWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

namespace llvm {
class MCObjectWriter;
class MCSectionGOFF;
class raw_pwrite_stream;

class MCGOFFObjectTargetWriter : public MCObjectTargetWriter {
Expand All @@ -37,11 +38,16 @@ class GOFFObjectWriter : public MCObjectWriter {
// The stream used to write the GOFF records.
raw_pwrite_stream &OS;

// The RootSD section.
MCSectionGOFF *RootSD = nullptr;

public:
GOFFObjectWriter(std::unique_ptr<MCGOFFObjectTargetWriter> MOTW,
raw_pwrite_stream &OS);
~GOFFObjectWriter() override;

void setRootSD(MCSectionGOFF *RootSD) { this->RootSD = RootSD; }

// Implementation of the MCObjectWriter interface.
void recordRelocation(const MCFragment &F, const MCFixup &Fixup,
MCValue Target, uint64_t &FixedValue) override {}
Expand Down
12 changes: 9 additions & 3 deletions llvm/include/llvm/MC/MCGOFFStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

namespace llvm {
class GOFFObjectWriter;
class MCSymbolGOFF;

class MCGOFFStreamer : public MCObjectStreamer {

Expand All @@ -24,15 +25,20 @@ class MCGOFFStreamer : public MCObjectStreamer {

~MCGOFFStreamer() override;

void finishImpl() override;

void changeSection(MCSection *Section, uint32_t Subsection = 0) override;

GOFFObjectWriter &getWriter();

bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override {
return false;
}
void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;

bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;

void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
Align ByteAlignment) override {}

void emitExterns();
};

} // end namespace llvm
Expand Down
42 changes: 39 additions & 3 deletions llvm/include/llvm/MC/MCSymbolGOFF.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,19 @@ namespace llvm {

class MCSymbolGOFF : public MCSymbol {
// Associated data area of the section. Needs to be emitted first.
MCSectionGOFF *ADA;
MCSectionGOFF *ADA = nullptr;

GOFF::LDAttr LDAttributes;
GOFF::ERAttr ERAttributes;

GOFF::ESDExecutable CodeData = GOFF::ESDExecutable::ESD_EXE_Unspecified;
GOFF::ESDLinkageType Linkage = GOFF::ESDLinkageType::ESD_LT_XPLink;

enum SymbolFlags : uint16_t {
SF_LD = 0x01, // LD attributes are set.
SF_LD = 0x01, // LD attributes are set.
SF_ER = 0x02, // ER attributes are set.
SF_Hidden = 0x04, // Symbol is hidden, aka not exported.
SF_Weak = 0x08, // Symbol is weak.
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The above fields CodeData and Linkage as well as the new flags SF_Hidden and SF_Weak duplicate information already present in the LDAttributes or ERAttributes field. This should be avoided - what does it mean if the two places disagree?

Not sure what the right fix is; either we can create and maintain the proper attribute structure at all times, or if not, maybe we should not have the attributes in MCSymbolGOFF at all (only those other fields), and simply generate the proper attributes structure only where it is needed to write out the symbol.


public:
Expand All @@ -39,14 +46,43 @@ class MCSymbolGOFF : public MCSymbol {
modifyFlags(SF_LD, SF_LD);
LDAttributes = Attr;
}
GOFF::LDAttr getLDAttributes() const { return LDAttributes; }
const GOFF::LDAttr &getLDAttributes() const { return LDAttributes; }
GOFF::LDAttr &getLDAttributes() { return LDAttributes; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need a non-const getter at all here?

bool hasLDAttributes() const { return getFlags() & SF_LD; }

void setERAttributes(GOFF::ERAttr Attr) {
modifyFlags(SF_ER, SF_ER);
ERAttributes = Attr;
}
const GOFF::ERAttr &getERAttributes() const { return ERAttributes; }
GOFF::ERAttr &getERAttributes() { return ERAttributes; }
bool hasERAttributes() const { return getFlags() & SF_ER; }

void setADA(MCSectionGOFF *AssociatedDataArea) {
ADA = AssociatedDataArea;
AssociatedDataArea->RequiresNonZeroLength = true;
}
MCSectionGOFF *getADA() const { return ADA; }

bool isExternal() const { return IsExternal; }
void setExternal(bool Value) const { IsExternal = Value; }

void setHidden(bool Value = true) {
modifyFlags(Value ? SF_Hidden : 0, SF_Hidden);
}
bool isHidden() const { return getFlags() & SF_Hidden; }
bool isExported() const { return !isHidden(); }

void setWeak(bool Value = true) { modifyFlags(Value ? SF_Weak : 0, SF_Weak); }
bool isWeak() const { return getFlags() & SF_Weak; }

void setCodeData(GOFF::ESDExecutable Value) { CodeData = Value; }
GOFF::ESDExecutable getCodeData() const { return CodeData; }

void setLinkage(GOFF::ESDLinkageType Value) { Linkage = Value; }
GOFF::ESDLinkageType getLinkage() const { return Linkage; }

void initAttributes();
};
} // end namespace llvm

Expand Down
1 change: 1 addition & 0 deletions llvm/lib/MC/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ add_llvm_component_library(LLVMMC
MCSubtargetInfo.cpp
MCSymbol.cpp
MCSymbolELF.cpp
MCSymbolGOFF.cpp
MCSymbolXCOFF.cpp
MCTargetOptions.cpp
MCTargetOptionsCommandFlags.cpp
Expand Down
33 changes: 29 additions & 4 deletions llvm/lib/MC/GOFFObjectWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,11 +266,24 @@ class GOFFSymbol {
BehavAttrs.setBindingScope(Attr.BindingScope);
BehavAttrs.setAlignment(EDAttr.Alignment);
}

GOFFSymbol(StringRef Name, uint32_t EsdID, uint32_t ParentEsdID,
const GOFF::ERAttr &Attr)
: Name(Name.data(), Name.size()), EsdId(EsdID), ParentEsdId(ParentEsdID),
SymbolType(GOFF::ESD_ST_ExternalReference),
NameSpace(GOFF::ESD_NS_NormalName) {
BehavAttrs.setExecutable(Attr.Executable);
BehavAttrs.setBindingStrength(Attr.BindingStrength);
BehavAttrs.setLinkageType(Attr.Linkage);
BehavAttrs.setAmode(Attr.Amode);
BehavAttrs.setBindingScope(Attr.BindingScope);
}
};

class GOFFWriter {
GOFFOstream OS;
MCAssembler &Asm;
MCSectionGOFF *RootSD;

void writeHeader();
void writeSymbol(const GOFFSymbol &Symbol);
Expand All @@ -279,16 +292,18 @@ class GOFFWriter {

void defineSectionSymbols(const MCSectionGOFF &Section);
void defineLabel(const MCSymbolGOFF &Symbol);
void defineExtern(const MCSymbolGOFF &Symbol);
void defineSymbols();

public:
GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm);
GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm, MCSectionGOFF *RootSD);
uint64_t writeObject();
};
} // namespace

GOFFWriter::GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm)
: OS(OS), Asm(Asm) {}
GOFFWriter::GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm,
MCSectionGOFF *RootSD)
: OS(OS), Asm(Asm), RootSD(RootSD) {}

void GOFFWriter::defineSectionSymbols(const MCSectionGOFF &Section) {
if (Section.isSD()) {
Expand Down Expand Up @@ -328,9 +343,16 @@ void GOFFWriter::defineLabel(const MCSymbolGOFF &Symbol) {
Section.getEDAttributes().NameSpace, Symbol.getLDAttributes());
if (Symbol.getADA())
LD.ADAEsdId = Symbol.getADA()->getOrdinal();
LD.Offset = Asm.getSymbolOffset(Symbol);
writeSymbol(LD);
}

void GOFFWriter::defineExtern(const MCSymbolGOFF &Symbol) {
GOFFSymbol ER(Symbol.getName(), Symbol.getIndex(),
RootSD->getOrdinal(), Symbol.getERAttributes());
writeSymbol(ER);
}

void GOFFWriter::defineSymbols() {
unsigned Ordinal = 0;
// Process all sections.
Expand All @@ -348,6 +370,9 @@ void GOFFWriter::defineSymbols() {
if (Symbol.hasLDAttributes()) {
Symbol.setIndex(++Ordinal);
defineLabel(Symbol);
} else if (Symbol.hasERAttributes()) {
Symbol.setIndex(++Ordinal);
defineExtern(Symbol);
}
}
}
Expand Down Expand Up @@ -523,7 +548,7 @@ GOFFObjectWriter::GOFFObjectWriter(
GOFFObjectWriter::~GOFFObjectWriter() = default;

uint64_t GOFFObjectWriter::writeObject() {
uint64_t Size = GOFFWriter(OS, *Asm).writeObject();
uint64_t Size = GOFFWriter(OS, *Asm, RootSD).writeObject();
return Size;
}

Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/MC/MCAsmStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -774,6 +774,9 @@ bool MCAsmStreamer::emitSymbolAttribute(MCSymbol *Symbol,
// Assemblers currently do not support a .cold directive.
case MCSA_Exported:
// Non-AIX assemblers currently do not support exported visibility.
case MCSA_OSLinkage:
case MCSA_XPLinkage:
// Only for HLASM.
return false;
case MCSA_Memtag:
OS << "\t.memtag\t";
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/MC/MCELFStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDirectives.h"
#include "llvm/MC/MCELFObjectWriter.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCFixup.h"
Expand Down Expand Up @@ -151,6 +152,8 @@ bool MCELFStreamer::emitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
case MCSA_IndirectSymbol:
case MCSA_Exported:
case MCSA_WeakAntiDep:
case MCSA_OSLinkage:
case MCSA_XPLinkage:
return false;

case MCSA_NoDeadStrip:
Expand Down
100 changes: 94 additions & 6 deletions llvm/lib/MC/MCGOFFStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,35 @@
//===----------------------------------------------------------------------===//

#include "llvm/MC/MCGOFFStreamer.h"
#include "llvm/BinaryFormat/GOFF.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDirectives.h"
#include "llvm/MC/MCGOFFObjectWriter.h"
#include "llvm/MC/MCObjectStreamer.h"
#include "llvm/MC/MCSymbolGOFF.h"
#include "llvm/MC/TargetRegistry.h"

using namespace llvm;

MCGOFFStreamer::MCGOFFStreamer(MCContext &Context,
std::unique_ptr<MCAsmBackend> MAB,
std::unique_ptr<MCObjectWriter> OW,
std::unique_ptr<MCCodeEmitter> Emitter)
: MCObjectStreamer(Context, std::move(MAB), std::move(OW),
std::move(Emitter)) {}

MCGOFFStreamer::~MCGOFFStreamer() = default;

void MCGOFFStreamer::finishImpl() {
getWriter().setRootSD(static_cast<MCSectionGOFF *>(
getContext().getObjectFileInfo()->getTextSection())
->getParent());
MCObjectStreamer::finishImpl();
}

GOFFObjectWriter &MCGOFFStreamer::getWriter() {
return static_cast<GOFFObjectWriter &>(getAssembler().getWriter());
}
Expand All @@ -37,6 +55,82 @@ void MCGOFFStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
}
}

void MCGOFFStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
MCObjectStreamer::emitLabel(Symbol, Loc);
static_cast<MCSymbolGOFF *>(Symbol)->initAttributes();
}

bool MCGOFFStreamer::emitSymbolAttribute(MCSymbol *Sym,
MCSymbolAttr Attribute) {
auto *Symbol = static_cast<MCSymbolGOFF *>(Sym);
switch (Attribute) {
case MCSA_Invalid:
case MCSA_Cold:
case MCSA_ELF_TypeIndFunction:
case MCSA_ELF_TypeTLS:
case MCSA_ELF_TypeCommon:
case MCSA_ELF_TypeNoType:
case MCSA_ELF_TypeGnuUniqueObject:
case MCSA_LGlobal:
case MCSA_Extern:
case MCSA_Exported:
case MCSA_IndirectSymbol:
case MCSA_Internal:
case MCSA_LazyReference:
case MCSA_NoDeadStrip:
case MCSA_SymbolResolver:
case MCSA_AltEntry:
case MCSA_PrivateExtern:
case MCSA_Protected:
case MCSA_Reference:
case MCSA_WeakDefinition:
case MCSA_WeakDefAutoPrivate:
case MCSA_WeakAntiDep:
case MCSA_Memtag:
return false;

case MCSA_ELF_TypeFunction:
Symbol->setCodeData(GOFF::ESDExecutable::ESD_EXE_CODE);
break;
case MCSA_ELF_TypeObject:
Symbol->setCodeData(GOFF::ESDExecutable::ESD_EXE_DATA);
break;
case MCSA_OSLinkage:
Symbol->setLinkage(GOFF::ESDLinkageType::ESD_LT_OS);
break;
case MCSA_XPLinkage:
Symbol->setLinkage(GOFF::ESDLinkageType::ESD_LT_XPLink);
break;
case MCSA_Global:
Symbol->setExternal(true);
break;
case MCSA_Local:
Symbol->setExternal(false);
break;
case MCSA_Weak:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for .globl; .local; .weak, does the last directive win? MCELFStreamer.cpp reports warnings/errors.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, currently the last directive wins. I'll check the MCELFStreamer implementation.

case MCSA_WeakReference:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MCSA_WeakReference is used by AsmPrinter::emitGlobalAlias - ensure that GOFF has such a test.

Symbol->setExternal(true);
Symbol->setWeak();
break;
case MCSA_Hidden:
Symbol->setHidden(true);
break;
}

return true;
}

void MCGOFFStreamer::emitExterns() {
for (auto &Symbol : getAssembler().symbols()) {
if (Symbol.isTemporary())
continue;
if (Symbol.isRegistered()) {
auto &Sym = static_cast<MCSymbolGOFF &>(const_cast<MCSymbol &>(Symbol));
Sym.initAttributes();
}
}
}

MCStreamer *llvm::createGOFFStreamer(MCContext &Context,
std::unique_ptr<MCAsmBackend> &&MAB,
std::unique_ptr<MCObjectWriter> &&OW,
Expand All @@ -45,9 +139,3 @@ MCStreamer *llvm::createGOFFStreamer(MCContext &Context,
new MCGOFFStreamer(Context, std::move(MAB), std::move(OW), std::move(CE));
return S;
}
llvm::MCGOFFStreamer::MCGOFFStreamer(MCContext &Context,
std::unique_ptr<MCAsmBackend> MAB,
std::unique_ptr<MCObjectWriter> OW,
std::unique_ptr<MCCodeEmitter> Emitter)
: MCObjectStreamer(Context, std::move(MAB), std::move(OW),
std::move(Emitter)) {}
Loading
Loading