Move all flags logic to MCSymbolMachO.

Also delete the now unused MCMachOSymbolFlags.h header as the only enum in there was moved to MCSymbolMachO.

Similarly to ELF and COFF, manipulating the flags is now done via helpers instead of spread
throughout the codebase.

Reviewed by Rafael Espíndola.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@239316 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Pete Cooper
2015-06-08 17:17:28 +00:00
parent cae8bc4504
commit d3869ee8d2
4 changed files with 119 additions and 81 deletions

View File

@ -1,46 +0,0 @@
//===- MCMachOSymbolFlags.h - MachO Symbol Flags ----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file declares the SymbolFlags used for the MachO target.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_MC_MCMACHOSYMBOLFLAGS_H
#define LLVM_MC_MCMACHOSYMBOLFLAGS_H
// These flags are mostly used in MCMachOStreamer.cpp but also needed in
// MachObjectWriter.cpp to test for Weak Definitions of symbols to emit
// the correct relocation information.
namespace llvm {
/// MachOSymbolFlags - We store the value for the 'desc' symbol field in the
/// lowest 16 bits of the implementation defined flags.
enum MachOSymbolFlags { // See <mach-o/nlist.h>.
SF_DescFlagsMask = 0xFFFF,
// Reference type flags.
SF_ReferenceTypeMask = 0x0007,
SF_ReferenceTypeUndefinedNonLazy = 0x0000,
SF_ReferenceTypeUndefinedLazy = 0x0001,
SF_ReferenceTypeDefined = 0x0002,
SF_ReferenceTypePrivateDefined = 0x0003,
SF_ReferenceTypePrivateUndefinedNonLazy = 0x0004,
SF_ReferenceTypePrivateUndefinedLazy = 0x0005,
// Other 'desc' flags.
SF_ThumbFunc = 0x0008,
SF_NoDeadStrip = 0x0020,
SF_WeakReference = 0x0040,
SF_WeakDefinition = 0x0080,
SF_SymbolResolver = 0x0100
};
} // end namespace llvm
#endif

View File

@ -13,11 +13,109 @@
namespace llvm { namespace llvm {
class MCSymbolMachO : public MCSymbol { class MCSymbolMachO : public MCSymbol {
/// \brief We store the value for the 'desc' symbol field in the
/// lowest 16 bits of the implementation defined flags.
enum MachOSymbolFlags : uint16_t { // See <mach-o/nlist.h>.
SF_DescFlagsMask = 0xFFFF,
// Reference type flags.
SF_ReferenceTypeMask = 0x0007,
SF_ReferenceTypeUndefinedNonLazy = 0x0000,
SF_ReferenceTypeUndefinedLazy = 0x0001,
SF_ReferenceTypeDefined = 0x0002,
SF_ReferenceTypePrivateDefined = 0x0003,
SF_ReferenceTypePrivateUndefinedNonLazy = 0x0004,
SF_ReferenceTypePrivateUndefinedLazy = 0x0005,
// Other 'desc' flags.
SF_ThumbFunc = 0x0008,
SF_NoDeadStrip = 0x0020,
SF_WeakReference = 0x0040,
SF_WeakDefinition = 0x0080,
SF_SymbolResolver = 0x0100,
// Common alignment
SF_CommonAlignmentMask = 0xF0FF,
SF_CommonAlignmentShift = 8
};
public: public:
MCSymbolMachO(const StringMapEntry<bool> *Name, bool isTemporary) MCSymbolMachO(const StringMapEntry<bool> *Name, bool isTemporary)
: MCSymbol(SymbolKindMachO, Name, isTemporary) {} : MCSymbol(SymbolKindMachO, Name, isTemporary) {}
// Reference type methods.
void clearReferenceType() const {
modifyFlags(0, SF_ReferenceTypeMask);
}
void setReferenceTypeUndefinedLazy(bool Value) const {
modifyFlags(Value ? SF_ReferenceTypeUndefinedLazy : 0,
SF_ReferenceTypeUndefinedLazy);
}
// Other 'desc' methods.
void setThumbFunc() const {
modifyFlags(SF_ThumbFunc, SF_ThumbFunc);
}
bool isNoDeadStrip() const {
return getFlags() & SF_NoDeadStrip;
}
void setNoDeadStrip() const {
modifyFlags(SF_NoDeadStrip, SF_NoDeadStrip);
}
bool isWeakReference() const {
return getFlags() & SF_WeakReference;
}
void setWeakReference() const {
modifyFlags(SF_WeakReference, SF_WeakReference);
}
bool isWeakDefinition() const {
return getFlags() & SF_WeakDefinition;
}
void setWeakDefinition() const {
modifyFlags(SF_WeakDefinition, SF_WeakDefinition);
}
bool isSymbolResolver() const {
return getFlags() & SF_SymbolResolver;
}
void setSymbolResolver() const {
modifyFlags(SF_SymbolResolver, SF_SymbolResolver);
}
void setDesc(unsigned Value) const {
assert(Value == (Value & SF_DescFlagsMask) &&
"Invalid .desc value!");
setFlags(Value & SF_DescFlagsMask);
}
/// \brief Get the encoded value of the flags as they will be emitted in to
/// the MachO binary
uint16_t getEncodedFlags() const {
uint16_t Flags = getFlags();
// Common alignment is packed into the 'desc' bits.
if (isCommon()) {
if (unsigned Align = getCommonAlignment()) {
unsigned Log2Size = Log2_32(Align);
assert((1U << Log2Size) == Align && "Invalid 'common' alignment!");
if (Log2Size > 15)
report_fatal_error("invalid 'common' alignment '" +
Twine(Align) + "' for '" + getName() + "'",
false);
Flags = (Flags & SF_CommonAlignmentMask) |
(Log2Size << SF_CommonAlignmentShift);
}
}
return Flags;
}
static bool classof(const MCSymbol *S) { return S->isMachO(); } static bool classof(const MCSymbol *S) { return S->isMachO(); }
}; };
} }

View File

@ -23,7 +23,7 @@
#include "llvm/MC/MCObjectStreamer.h" #include "llvm/MC/MCObjectStreamer.h"
#include "llvm/MC/MCSection.h" #include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCSymbolMachO.h"
#include "llvm/Support/Dwarf.h" #include "llvm/Support/Dwarf.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetRegistry.h"
@ -172,7 +172,7 @@ void MCMachOStreamer::EmitEHSymAttributes(const MCSymbol *Symbol,
getAssembler().registerSymbol(*Symbol); getAssembler().registerSymbol(*Symbol);
if (Symbol->isExternal()) if (Symbol->isExternal())
EmitSymbolAttribute(EHSymbol, MCSA_Global); EmitSymbolAttribute(EHSymbol, MCSA_Global);
if (Symbol->getFlags() & SF_WeakDefinition) if (cast<MCSymbolMachO>(Symbol)->isWeakDefinition())
EmitSymbolAttribute(EHSymbol, MCSA_WeakDefinition); EmitSymbolAttribute(EHSymbol, MCSA_WeakDefinition);
if (Symbol->isPrivateExtern()) if (Symbol->isPrivateExtern())
EmitSymbolAttribute(EHSymbol, MCSA_PrivateExtern); EmitSymbolAttribute(EHSymbol, MCSA_PrivateExtern);
@ -197,7 +197,7 @@ void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) {
// //
// FIXME: Cleanup this code, these bits should be emitted based on semantic // FIXME: Cleanup this code, these bits should be emitted based on semantic
// properties, not on the order of definition, etc. // properties, not on the order of definition, etc.
Symbol->setFlags(Symbol->getFlags() & ~SF_ReferenceTypeMask); cast<MCSymbolMachO>(Symbol)->clearReferenceType();
} }
void MCMachOStreamer::EmitDataRegion(DataRegionData::KindTy Kind) { void MCMachOStreamer::EmitDataRegion(DataRegionData::KindTy Kind) {
@ -272,10 +272,13 @@ void MCMachOStreamer::EmitThumbFunc(MCSymbol *Symbol) {
// Remember that the function is a thumb function. Fixup and relocation // Remember that the function is a thumb function. Fixup and relocation
// values will need adjusted. // values will need adjusted.
getAssembler().setIsThumbFunc(Symbol); getAssembler().setIsThumbFunc(Symbol);
cast<MCSymbolMachO>(Symbol)->setThumbFunc();
} }
bool MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol, bool MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Sym,
MCSymbolAttr Attribute) { MCSymbolAttr Attribute) {
MCSymbolMachO *Symbol = cast<MCSymbolMachO>(Sym);
// Indirect symbols are handled differently, to match how 'as' handles // Indirect symbols are handled differently, to match how 'as' handles
// them. This makes writing matching .o files easier. // them. This makes writing matching .o files easier.
if (Attribute == MCSA_IndirectSymbol) { if (Attribute == MCSA_IndirectSymbol) {
@ -324,25 +327,25 @@ bool MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
// //
// FIXME: Cleanup this code, these bits should be emitted based on semantic // FIXME: Cleanup this code, these bits should be emitted based on semantic
// properties, not on the order of definition, etc. // properties, not on the order of definition, etc.
Symbol->setFlags(Symbol->getFlags() & ~SF_ReferenceTypeUndefinedLazy); Symbol->setReferenceTypeUndefinedLazy(false);
break; break;
case MCSA_LazyReference: case MCSA_LazyReference:
// FIXME: This requires -dynamic. // FIXME: This requires -dynamic.
Symbol->setFlags(Symbol->getFlags() | SF_NoDeadStrip); Symbol->setNoDeadStrip();
if (Symbol->isUndefined()) if (Symbol->isUndefined())
Symbol->setFlags(Symbol->getFlags() | SF_ReferenceTypeUndefinedLazy); Symbol->setReferenceTypeUndefinedLazy(true);
break; break;
// Since .reference sets the no dead strip bit, it is equivalent to // Since .reference sets the no dead strip bit, it is equivalent to
// .no_dead_strip in practice. // .no_dead_strip in practice.
case MCSA_Reference: case MCSA_Reference:
case MCSA_NoDeadStrip: case MCSA_NoDeadStrip:
Symbol->setFlags(Symbol->getFlags() | SF_NoDeadStrip); Symbol->setNoDeadStrip();
break; break;
case MCSA_SymbolResolver: case MCSA_SymbolResolver:
Symbol->setFlags(Symbol->getFlags() | SF_SymbolResolver); Symbol->setSymbolResolver();
break; break;
case MCSA_PrivateExtern: case MCSA_PrivateExtern:
@ -353,17 +356,18 @@ bool MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
case MCSA_WeakReference: case MCSA_WeakReference:
// FIXME: This requires -dynamic. // FIXME: This requires -dynamic.
if (Symbol->isUndefined()) if (Symbol->isUndefined())
Symbol->setFlags(Symbol->getFlags() | SF_WeakReference); Symbol->setWeakReference();
break; break;
case MCSA_WeakDefinition: case MCSA_WeakDefinition:
// FIXME: 'as' enforces that this is defined and global. The manual claims // FIXME: 'as' enforces that this is defined and global. The manual claims
// it has to be in a coalesced section, but this isn't enforced. // it has to be in a coalesced section, but this isn't enforced.
Symbol->setFlags(Symbol->getFlags() | SF_WeakDefinition); Symbol->setWeakDefinition();
break; break;
case MCSA_WeakDefAutoPrivate: case MCSA_WeakDefAutoPrivate:
Symbol->setFlags(Symbol->getFlags() | SF_WeakDefinition | SF_WeakReference); Symbol->setWeakDefinition();
Symbol->setWeakReference();
break; break;
} }
@ -372,10 +376,8 @@ bool MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
void MCMachOStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { void MCMachOStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
// Encode the 'desc' value into the lowest implementation defined bits. // Encode the 'desc' value into the lowest implementation defined bits.
assert(DescValue == (DescValue & SF_DescFlagsMask) &&
"Invalid .desc value!");
getAssembler().registerSymbol(*Symbol); getAssembler().registerSymbol(*Symbol);
Symbol->setFlags(DescValue & SF_DescFlagsMask); cast<MCSymbolMachO>(Symbol)->setDesc(DescValue);
} }
void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,

View File

@ -18,7 +18,7 @@
#include "llvm/MC/MCMachOSymbolFlags.h" #include "llvm/MC/MCMachOSymbolFlags.h"
#include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCSymbolMachO.h"
#include "llvm/MC/MCValue.h" #include "llvm/MC/MCValue.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
@ -46,7 +46,7 @@ bool MachObjectWriter::doesSymbolRequireExternRelocation(const MCSymbol &S) {
// References to weak definitions require external relocation entries; the // References to weak definitions require external relocation entries; the
// definition may not always be the one in the same object file. // definition may not always be the one in the same object file.
if (S.getFlags() & SF_WeakDefinition) if (cast<MCSymbolMachO>(S).isWeakDefinition())
return true; return true;
// Otherwise, we can use an internal relocation. // Otherwise, we can use an internal relocation.
@ -327,7 +327,6 @@ void MachObjectWriter::writeNlist(MachSymbolData &MSD,
const MCSymbol *AliasedSymbol = &findAliasedSymbol(*Symbol); const MCSymbol *AliasedSymbol = &findAliasedSymbol(*Symbol);
uint8_t SectionIndex = MSD.SectionIndex; uint8_t SectionIndex = MSD.SectionIndex;
uint8_t Type = 0; uint8_t Type = 0;
uint16_t Flags = Symbol->getFlags();
uint64_t Address = 0; uint64_t Address = 0;
bool IsAlias = Symbol != AliasedSymbol; bool IsAlias = Symbol != AliasedSymbol;
@ -371,22 +370,7 @@ void MachObjectWriter::writeNlist(MachSymbolData &MSD,
// Common symbols are encoded with the size in the address // Common symbols are encoded with the size in the address
// field, and their alignment in the flags. // field, and their alignment in the flags.
Address = Symbol->getCommonSize(); Address = Symbol->getCommonSize();
// Common alignment is packed into the 'desc' bits.
if (unsigned Align = Symbol->getCommonAlignment()) {
unsigned Log2Size = Log2_32(Align);
assert((1U << Log2Size) == Align && "Invalid 'common' alignment!");
if (Log2Size > 15)
report_fatal_error("invalid 'common' alignment '" +
Twine(Align) + "' for '" + Symbol->getName() + "'",
false);
// FIXME: Keep this mask with the SymbolFlags enumeration.
Flags = (Flags & 0xF0FF) | (Log2Size << 8);
} }
}
if (Layout.getAssembler().isThumbFunc(Symbol))
Flags |= SF_ThumbFunc;
// struct nlist (12 bytes) // struct nlist (12 bytes)
@ -396,7 +380,7 @@ void MachObjectWriter::writeNlist(MachSymbolData &MSD,
// The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc' // The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc'
// value. // value.
write16(Flags); write16(cast<MCSymbolMachO>(Symbol)->getEncodedFlags());
if (is64Bit()) if (is64Bit())
write64(Address); write64(Address);
else else
@ -515,7 +499,7 @@ void MachObjectWriter::bindIndirectSymbols(MCAssembler &Asm) {
bool Created; bool Created;
Asm.registerSymbol(*it->Symbol, &Created); Asm.registerSymbol(*it->Symbol, &Created);
if (Created) if (Created)
it->Symbol->setFlags(it->Symbol->getFlags() | 0x0001); cast<MCSymbolMachO>(it->Symbol)->setReferenceTypeUndefinedLazy(true);
} }
} }