-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[GOFF] Emit symbols for functions. #144437
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 6 commits
6261752
194ba3a
c19957c
2fa73af
43dcc13
ee1434b
214d716
1f43993
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,12 +23,24 @@ namespace llvm { | |
|
|
||
| class MCSymbolGOFF : public MCSymbol { | ||
| // Associated data area of the section. Needs to be emitted first. | ||
| MCSectionGOFF *ADA; | ||
| MCSectionGOFF *ADA = nullptr; | ||
|
|
||
| // Owner of the symbol if symbol is an external reference. External references | ||
| // need a section, too, but adding them to a section would make the symbol | ||
| // defined. | ||
| MCSectionGOFF *Owner = 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. | ||
| }; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The above fields 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 |
||
|
|
||
| public: | ||
|
|
@@ -39,14 +51,46 @@ 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; } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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; } | ||
|
|
||
| void setOwner(MCSectionGOFF *Owner) { this->Owner = Owner; } | ||
| MCSectionGOFF *getOwner() const { return Owner; } | ||
|
|
||
| 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 | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,11 +11,14 @@ | |
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #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/MCSymbolGOFF.h" | ||
| #include "llvm/MC/TargetRegistry.h" | ||
|
|
||
| using namespace llvm; | ||
|
|
@@ -37,6 +40,85 @@ 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_TypeFunction: | ||
| case MCSA_ELF_TypeIndFunction: | ||
| case MCSA_ELF_TypeObject: | ||
| 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_Code: | ||
| Symbol->setCodeData(GOFF::ESDExecutable::ESD_EXE_CODE); | ||
| break; | ||
| case MCSA_Data: | ||
| 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); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is local/global/weak tested? |
||
| break; | ||
| case MCSA_Weak: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.setOwner(static_cast<MCSectionGOFF *>(getCurrentSection().first)); | ||
| Sym.initAttributes(); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| MCStreamer *llvm::createGOFFStreamer(MCContext &Context, | ||
| std::unique_ptr<MCAsmBackend> &&MAB, | ||
| std::unique_ptr<MCObjectWriter> &&OW, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| //===- MCSymbolGOFF.cpp - GOFF Symbol Representation ----------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "llvm/MC/MCSymbolGOFF.h" | ||
| #include "llvm/BinaryFormat/GOFF.h" | ||
| #include "llvm/Support/ErrorHandling.h" | ||
|
|
||
| using namespace llvm; | ||
|
|
||
| void MCSymbolGOFF::initAttributes() { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Depending on how we resolve the attribute question above, I don't think we should have this function at all. Either attributes are set up initially at symbol creation and modified on the fly as needed, or else the information is directly taken form flags and other fields at the place where it is needed. |
||
| // Temporary labels are not emitted into the object file. | ||
| if (isTemporary()) | ||
| return; | ||
|
|
||
| // Do not initialize the attributes multiple times. | ||
| if (hasLDAttributes() || hasERAttributes()) | ||
| return; | ||
|
|
||
| GOFF::ESDBindingScope BindingScope = | ||
| isExternal() | ||
| ? (isExported() ? GOFF::ESD_BSC_ImportExport : GOFF::ESD_BSC_Library) | ||
| : GOFF::ESD_BSC_Section; | ||
| GOFF::ESDBindingStrength BindingStrength = | ||
| isWeak() ? GOFF::ESDBindingStrength::ESD_BST_Weak | ||
| : GOFF::ESDBindingStrength::ESD_BST_Strong; | ||
|
|
||
| if (isDefined()) { | ||
| MCSectionGOFF &Section = static_cast<MCSectionGOFF &>(getSection()); | ||
| if (Section.isED()) { | ||
| setLDAttributes(GOFF::LDAttr{false, CodeData, BindingStrength, Linkage, | ||
| GOFF::ESD_AMODE_64, BindingScope}); | ||
| } else if (Section.isPR()) { | ||
| // For data symbols, the attributes are already determind in TLOFI. | ||
| // TODO Does it make sense to it to here? | ||
| } else | ||
| llvm_unreachable("Unexpected section type for label"); | ||
| } else { | ||
| setERAttributes(GOFF::ERAttr{CodeData, BindingStrength, Linkage, | ||
| GOFF::ESD_AMODE_64, BindingScope}); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The above two duplicate the semantics of
MCSA_ELF_TypeFunctionandMCSA_ELF_TypeObjectin a sense. I'm wondering if we can hook into that (already existing) common code logic ...There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed, now using
MCSA_ELF_TypeFunction/MCSA_ELF_TypeObject. It's indeed very similar.