mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-28 04:33:05 +00:00
Centralize the handling of the thumb bit.
This patch centralizes the handling of the thumb bit around MCStreamer::isThumbFunc and makes isThumbFunc handle aliases. This fixes a corner case, but the main advantage is having just one way to check if a MCSymbol is thumb or not. This should still be refactored to be ARM only, but at least now it is just one predicate that has to be refactored instead of 3 (isThumbFunc, ELF_Other_ThumbFunc, and SF_ThumbFunc). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@207522 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
65baf804ba
commit
1c5f439f41
@ -902,7 +902,7 @@ private:
|
|||||||
// here. Maybe when the relocation stuff moves to target specific,
|
// here. Maybe when the relocation stuff moves to target specific,
|
||||||
// this can go with it? The streamer would need some target specific
|
// this can go with it? The streamer would need some target specific
|
||||||
// refactoring too.
|
// refactoring too.
|
||||||
SmallPtrSet<const MCSymbol*, 64> ThumbFuncs;
|
mutable SmallPtrSet<const MCSymbol*, 64> ThumbFuncs;
|
||||||
|
|
||||||
/// \brief The bundle alignment size currently set in the assembler.
|
/// \brief The bundle alignment size currently set in the assembler.
|
||||||
///
|
///
|
||||||
@ -995,9 +995,7 @@ public:
|
|||||||
const MCAsmLayout &Layout) const;
|
const MCAsmLayout &Layout) const;
|
||||||
|
|
||||||
/// Check whether a given symbol has been flagged with .thumb_func.
|
/// Check whether a given symbol has been flagged with .thumb_func.
|
||||||
bool isThumbFunc(const MCSymbol *Func) const {
|
bool isThumbFunc(const MCSymbol *Func) const;
|
||||||
return ThumbFuncs.count(Func);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Flag a function symbol as the target of a .thumb_func directive.
|
/// Flag a function symbol as the target of a .thumb_func directive.
|
||||||
void setIsThumbFunc(const MCSymbol *Func) { ThumbFuncs.insert(Func); }
|
void setIsThumbFunc(const MCSymbol *Func) { ThumbFuncs.insert(Func); }
|
||||||
|
@ -24,9 +24,7 @@ namespace llvm {
|
|||||||
ELF_STT_Shift = 0, // Shift value for STT_* flags.
|
ELF_STT_Shift = 0, // Shift value for STT_* flags.
|
||||||
ELF_STB_Shift = 4, // Shift value for STB_* flags.
|
ELF_STB_Shift = 4, // Shift value for STB_* flags.
|
||||||
ELF_STV_Shift = 8, // Shift value for STV_* flags.
|
ELF_STV_Shift = 8, // Shift value for STV_* flags.
|
||||||
ELF_STO_Shift = 10, // Shift value for STO_* flags.
|
ELF_STO_Shift = 10 // Shift value for STO_* flags.
|
||||||
ELF_Other_Shift = 16 // Shift value for llvm local flags,
|
|
||||||
// not part of the final object file
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ELFSymbolFlags {
|
enum ELFSymbolFlags {
|
||||||
@ -49,9 +47,7 @@ namespace llvm {
|
|||||||
ELF_STV_Default = (ELF::STV_DEFAULT << ELF_STV_Shift),
|
ELF_STV_Default = (ELF::STV_DEFAULT << ELF_STV_Shift),
|
||||||
ELF_STV_Internal = (ELF::STV_INTERNAL << ELF_STV_Shift),
|
ELF_STV_Internal = (ELF::STV_INTERNAL << ELF_STV_Shift),
|
||||||
ELF_STV_Hidden = (ELF::STV_HIDDEN << ELF_STV_Shift),
|
ELF_STV_Hidden = (ELF::STV_HIDDEN << ELF_STV_Shift),
|
||||||
ELF_STV_Protected = (ELF::STV_PROTECTED << ELF_STV_Shift),
|
ELF_STV_Protected = (ELF::STV_PROTECTED << ELF_STV_Shift)
|
||||||
|
|
||||||
ELF_Other_ThumbFunc = (1 << ELF_Other_Shift)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
@ -215,7 +215,8 @@ class ELFObjectWriter : public MCObjectWriter {
|
|||||||
const MCAsmLayout &Layout,
|
const MCAsmLayout &Layout,
|
||||||
SectionIndexMapTy &SectionIndexMap);
|
SectionIndexMapTy &SectionIndexMap);
|
||||||
|
|
||||||
bool shouldRelocateWithSymbol(const MCSymbolRefExpr *RefA,
|
bool shouldRelocateWithSymbol(const MCAssembler &Asm,
|
||||||
|
const MCSymbolRefExpr *RefA,
|
||||||
const MCSymbolData *SD, uint64_t C,
|
const MCSymbolData *SD, uint64_t C,
|
||||||
unsigned Type) const;
|
unsigned Type) const;
|
||||||
|
|
||||||
@ -486,6 +487,7 @@ void ELFObjectWriter::WriteHeader(const MCAssembler &Asm,
|
|||||||
|
|
||||||
uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &OrigData,
|
uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &OrigData,
|
||||||
const MCAsmLayout &Layout) {
|
const MCAsmLayout &Layout) {
|
||||||
|
const MCSymbol &OrigSymbol = OrigData.getSymbol();
|
||||||
MCSymbolData *Data = &OrigData;
|
MCSymbolData *Data = &OrigData;
|
||||||
if (Data->isCommon() && Data->isExternal())
|
if (Data->isCommon() && Data->isExternal())
|
||||||
return Data->getCommonAlignment();
|
return Data->getCommonAlignment();
|
||||||
@ -512,8 +514,8 @@ uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &OrigData,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((Data && Data->getFlags() & ELF_Other_ThumbFunc) ||
|
const MCAssembler &Asm = Layout.getAssembler();
|
||||||
OrigData.getFlags() & ELF_Other_ThumbFunc)
|
if (Asm.isThumbFunc(&OrigSymbol))
|
||||||
Res |= 1;
|
Res |= 1;
|
||||||
|
|
||||||
if (!Symbol || !Symbol->isInSection())
|
if (!Symbol || !Symbol->isInSection())
|
||||||
@ -641,8 +643,6 @@ void ELFObjectWriter::WriteSymbol(SymbolTableWriter &Writer, ELFSymbolData &MSD,
|
|||||||
BaseSD = &Layout.getAssembler().getSymbolData(*Base);
|
BaseSD = &Layout.getAssembler().getSymbolData(*Base);
|
||||||
Type = mergeTypeForSet(Type, MCELF::GetType(*BaseSD));
|
Type = mergeTypeForSet(Type, MCELF::GetType(*BaseSD));
|
||||||
}
|
}
|
||||||
if (OrigData.getFlags() & ELF_Other_ThumbFunc)
|
|
||||||
Type = ELF::STT_FUNC;
|
|
||||||
uint8_t Info = (Binding << ELF_STB_Shift) | (Type << ELF_STT_Shift);
|
uint8_t Info = (Binding << ELF_STB_Shift) | (Type << ELF_STT_Shift);
|
||||||
|
|
||||||
// Other and Visibility share the same byte with Visibility using the lower
|
// Other and Visibility share the same byte with Visibility using the lower
|
||||||
@ -737,7 +737,8 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF,
|
|||||||
// It is always valid to create a relocation with a symbol. It is preferable
|
// It is always valid to create a relocation with a symbol. It is preferable
|
||||||
// to use a relocation with a section if that is possible. Using the section
|
// to use a relocation with a section if that is possible. Using the section
|
||||||
// allows us to omit some local symbols from the symbol table.
|
// allows us to omit some local symbols from the symbol table.
|
||||||
bool ELFObjectWriter::shouldRelocateWithSymbol(const MCSymbolRefExpr *RefA,
|
bool ELFObjectWriter::shouldRelocateWithSymbol(const MCAssembler &Asm,
|
||||||
|
const MCSymbolRefExpr *RefA,
|
||||||
const MCSymbolData *SD,
|
const MCSymbolData *SD,
|
||||||
uint64_t C,
|
uint64_t C,
|
||||||
unsigned Type) const {
|
unsigned Type) const {
|
||||||
@ -825,7 +826,7 @@ bool ELFObjectWriter::shouldRelocateWithSymbol(const MCSymbolRefExpr *RefA,
|
|||||||
// bit. With a symbol that is done by just having the symbol have that bit
|
// bit. With a symbol that is done by just having the symbol have that bit
|
||||||
// set, so we would lose the bit if we relocated with the section.
|
// set, so we would lose the bit if we relocated with the section.
|
||||||
// FIXME: We could use the section but add the bit to the relocation value.
|
// FIXME: We could use the section but add the bit to the relocation value.
|
||||||
if (SD->getFlags() & ELF_Other_ThumbFunc)
|
if (Asm.isThumbFunc(&Sym))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (TargetObjectWriter->needsRelocateWithSymbol(Type))
|
if (TargetObjectWriter->needsRelocateWithSymbol(Type))
|
||||||
@ -887,7 +888,7 @@ void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm,
|
|||||||
const MCSymbolData *SymAD = SymA ? &Asm.getSymbolData(*SymA) : nullptr;
|
const MCSymbolData *SymAD = SymA ? &Asm.getSymbolData(*SymA) : nullptr;
|
||||||
|
|
||||||
unsigned Type = GetRelocType(Target, Fixup, IsPCRel);
|
unsigned Type = GetRelocType(Target, Fixup, IsPCRel);
|
||||||
bool RelocateWithSymbol = shouldRelocateWithSymbol(RefA, SymAD, C, Type);
|
bool RelocateWithSymbol = shouldRelocateWithSymbol(Asm, RefA, SymAD, C, Type);
|
||||||
if (!RelocateWithSymbol && SymA && !SymA->isUndefined())
|
if (!RelocateWithSymbol && SymA && !SymA->isUndefined())
|
||||||
C += Layout.getSymbolOffset(SymAD);
|
C += Layout.getSymbolOffset(SymAD);
|
||||||
|
|
||||||
|
@ -323,6 +323,31 @@ void MCAssembler::reset() {
|
|||||||
getLOHContainer().reset();
|
getLOHContainer().reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MCAssembler::isThumbFunc(const MCSymbol *Symbol) const {
|
||||||
|
if (ThumbFuncs.count(Symbol))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!Symbol->isVariable())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// FIXME: It looks like gas support some cases of the form "foo + 2". It
|
||||||
|
// is not clear if that is a bug or a feature.
|
||||||
|
const MCExpr *Expr = Symbol->getVariableValue();
|
||||||
|
const MCSymbolRefExpr *Ref = dyn_cast<MCSymbolRefExpr>(Expr);
|
||||||
|
if (!Ref)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (Ref->getKind() != MCSymbolRefExpr::VK_None)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const MCSymbol &Sym = Ref->getSymbol();
|
||||||
|
if (!isThumbFunc(&Sym))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ThumbFuncs.insert(Symbol); // Cache it.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool MCAssembler::isSymbolLinkerVisible(const MCSymbol &Symbol) const {
|
bool MCAssembler::isSymbolLinkerVisible(const MCSymbol &Symbol) const {
|
||||||
// Non-temporary labels should always be visible to the linker.
|
// Non-temporary labels should always be visible to the linker.
|
||||||
if (!Symbol.isTemporary())
|
if (!Symbol.isTemporary())
|
||||||
|
@ -237,10 +237,6 @@ 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);
|
||||||
|
|
||||||
// Mark the thumb bit on the symbol.
|
|
||||||
MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
|
|
||||||
SD.setFlags(SD.getFlags() | SF_ThumbFunc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
|
bool MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
|
||||||
|
@ -351,6 +351,9 @@ void MachObjectWriter::WriteNlist(MachSymbolData &MSD,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Layout.getAssembler().isThumbFunc(&Symbol))
|
||||||
|
Flags |= SF_ThumbFunc;
|
||||||
|
|
||||||
// struct nlist (12 bytes)
|
// struct nlist (12 bytes)
|
||||||
|
|
||||||
Write32(MSD.StringIndex);
|
Write32(MSD.StringIndex);
|
||||||
|
@ -609,12 +609,8 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EmitThumbFunc(MCSymbol *Func) override {
|
void EmitThumbFunc(MCSymbol *Func) override {
|
||||||
// FIXME: Anything needed here to flag the function as thumb?
|
|
||||||
|
|
||||||
getAssembler().setIsThumbFunc(Func);
|
getAssembler().setIsThumbFunc(Func);
|
||||||
|
EmitSymbolAttribute(Func, MCSA_ELF_TypeFunction);
|
||||||
MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Func);
|
|
||||||
SD.setFlags(SD.getFlags() | ELF_Other_ThumbFunc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper functions for ARM exception handling directives
|
// Helper functions for ARM exception handling directives
|
||||||
|
@ -206,11 +206,11 @@ RecordARMScatteredHalfRelocation(MachObjectWriter *Writer,
|
|||||||
// The thumb bit shouldn't be set in the 'other-half' bit of the
|
// The thumb bit shouldn't be set in the 'other-half' bit of the
|
||||||
// relocation, but it will be set in FixedValue if the base symbol
|
// relocation, but it will be set in FixedValue if the base symbol
|
||||||
// is a thumb function. Clear it out here.
|
// is a thumb function. Clear it out here.
|
||||||
if (A_SD->getFlags() & SF_ThumbFunc)
|
if (Asm.isThumbFunc(A))
|
||||||
FixedValue &= 0xfffffffe;
|
FixedValue &= 0xfffffffe;
|
||||||
break;
|
break;
|
||||||
case ARM::fixup_t2_movt_hi16:
|
case ARM::fixup_t2_movt_hi16:
|
||||||
if (A_SD->getFlags() & SF_ThumbFunc)
|
if (Asm.isThumbFunc(A))
|
||||||
FixedValue &= 0xfffffffe;
|
FixedValue &= 0xfffffffe;
|
||||||
MovtBit = 1;
|
MovtBit = 1;
|
||||||
// Fallthrough
|
// Fallthrough
|
||||||
|
@ -14,6 +14,9 @@ arm_func:
|
|||||||
|
|
||||||
.thumb_set alias_arm_func, arm_func
|
.thumb_set alias_arm_func, arm_func
|
||||||
|
|
||||||
|
alias_arm_func2 = alias_arm_func
|
||||||
|
alias_arm_func3 = alias_arm_func2
|
||||||
|
|
||||||
@ ASM: .thumb_set alias_arm_func, arm_func
|
@ ASM: .thumb_set alias_arm_func, arm_func
|
||||||
|
|
||||||
.thumb
|
.thumb
|
||||||
@ -64,6 +67,18 @@ beta:
|
|||||||
@ CHECK: Type: Function
|
@ CHECK: Type: Function
|
||||||
@ CHECK: }
|
@ CHECK: }
|
||||||
|
|
||||||
|
@ CHECK: Symbol {
|
||||||
|
@ CHECK: Name: alias_arm_func2
|
||||||
|
@ CHECK: Value: 0x1
|
||||||
|
@ CHECK: Type: Function
|
||||||
|
@ CHECK: }
|
||||||
|
|
||||||
|
@ CHECK: Symbol {
|
||||||
|
@ CHECK: Name: alias_arm_func3
|
||||||
|
@ CHECK: Value: 0x1
|
||||||
|
@ CHECK: Type: Function
|
||||||
|
@ CHECK: }
|
||||||
|
|
||||||
@ CHECK: Symbol {
|
@ CHECK: Symbol {
|
||||||
@ CHECK: Name: alias_defined_data
|
@ CHECK: Name: alias_defined_data
|
||||||
@ CHECK: Value: 0x5
|
@ CHECK: Value: 0x5
|
||||||
|
Loading…
Reference in New Issue
Block a user