mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-30 06:40:53 +00:00
ARM Fixups relative to thumb functions need to have the low bit of the value
set for interworking to work properly. rdar://8755956 llvm-svn: 121778
This commit is contained in:
parent
74ba8b77e6
commit
25d3e79b23
@ -11,6 +11,7 @@
|
|||||||
#define LLVM_MC_MCASSEMBLER_H
|
#define LLVM_MC_MCASSEMBLER_H
|
||||||
|
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
|
#include "llvm/ADT/SmallPtrSet.h"
|
||||||
#include "llvm/ADT/SmallString.h"
|
#include "llvm/ADT/SmallString.h"
|
||||||
#include "llvm/ADT/ilist.h"
|
#include "llvm/ADT/ilist.h"
|
||||||
#include "llvm/ADT/ilist_node.h"
|
#include "llvm/ADT/ilist_node.h"
|
||||||
@ -662,6 +663,15 @@ private:
|
|||||||
|
|
||||||
std::vector<IndirectSymbolData> IndirectSymbols;
|
std::vector<IndirectSymbolData> IndirectSymbols;
|
||||||
|
|
||||||
|
/// The set of function symbols for which a .thumb_func directive has
|
||||||
|
/// been seen.
|
||||||
|
//
|
||||||
|
// FIXME: We really would like this in target specific code rather than
|
||||||
|
// here. Maybe when the relocation stuff moves to target specific,
|
||||||
|
// this can go with it? The streamer would need some target specific
|
||||||
|
// refactoring too.
|
||||||
|
SmallPtrSet<const MCSymbol*, 64> ThumbFuncs;
|
||||||
|
|
||||||
unsigned RelaxAll : 1;
|
unsigned RelaxAll : 1;
|
||||||
unsigned SubsectionsViaSymbols : 1;
|
unsigned SubsectionsViaSymbols : 1;
|
||||||
|
|
||||||
@ -738,6 +748,14 @@ public:
|
|||||||
void WriteSectionData(const MCSectionData *Section, const MCAsmLayout &Layout,
|
void WriteSectionData(const MCSectionData *Section, const MCAsmLayout &Layout,
|
||||||
MCObjectWriter *OW) const;
|
MCObjectWriter *OW) const;
|
||||||
|
|
||||||
|
/// Check whether a given symbol has been flagged with .thumb_func.
|
||||||
|
bool isThumbFunc(const MCSymbol *Func) const {
|
||||||
|
return ThumbFuncs.count(Func);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Flag a function symbol as the target of a .thumb_func directive.
|
||||||
|
void setIsThumbFunc(const MCSymbol *Func) { ThumbFuncs.insert(Func); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Construct a new assembler instance.
|
/// Construct a new assembler instance.
|
||||||
///
|
///
|
||||||
|
@ -235,12 +235,15 @@ bool MCAssembler::EvaluateFixup(const MCObjectWriter &Writer,
|
|||||||
bool IsPCRel = Emitter.getFixupKindInfo(
|
bool IsPCRel = Emitter.getFixupKindInfo(
|
||||||
Fixup.getKind()).Flags & MCFixupKindInfo::FKF_IsPCRel;
|
Fixup.getKind()).Flags & MCFixupKindInfo::FKF_IsPCRel;
|
||||||
bool IsResolved = true;
|
bool IsResolved = true;
|
||||||
|
bool IsThumb = false;
|
||||||
if (const MCSymbolRefExpr *A = Target.getSymA()) {
|
if (const MCSymbolRefExpr *A = Target.getSymA()) {
|
||||||
const MCSymbol &Sym = A->getSymbol().AliasedSymbol();
|
const MCSymbol &Sym = A->getSymbol().AliasedSymbol();
|
||||||
if (Sym.isDefined())
|
if (Sym.isDefined())
|
||||||
Value += Layout.getSymbolOffset(&getSymbolData(Sym));
|
Value += Layout.getSymbolOffset(&getSymbolData(Sym));
|
||||||
else
|
else
|
||||||
IsResolved = false;
|
IsResolved = false;
|
||||||
|
if (isThumbFunc(&Sym))
|
||||||
|
IsThumb = true;
|
||||||
}
|
}
|
||||||
if (const MCSymbolRefExpr *B = Target.getSymB()) {
|
if (const MCSymbolRefExpr *B = Target.getSymB()) {
|
||||||
const MCSymbol &Sym = B->getSymbol().AliasedSymbol();
|
const MCSymbol &Sym = B->getSymbol().AliasedSymbol();
|
||||||
@ -263,6 +266,13 @@ bool MCAssembler::EvaluateFixup(const MCObjectWriter &Writer,
|
|||||||
Value -= Layout.getFragmentOffset(DF) + Fixup.getOffset();
|
Value -= Layout.getFragmentOffset(DF) + Fixup.getOffset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ARM fixups based from a thumb function address need to have the low
|
||||||
|
// bit set. The actual value is always at least 16-bit aligned, so the
|
||||||
|
// low bit is normally clear and available for use as an ISA flag for
|
||||||
|
// interworking.
|
||||||
|
if (IsThumb)
|
||||||
|
Value |= 1;
|
||||||
|
|
||||||
return IsResolved;
|
return IsResolved;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,6 +142,10 @@ void MCMachOStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
|
|||||||
|
|
||||||
void MCMachOStreamer::EmitThumbFunc(MCSymbol *Func) {
|
void MCMachOStreamer::EmitThumbFunc(MCSymbol *Func) {
|
||||||
// FIXME: Flag the function ISA as thumb with DW_AT_APPLE_isa.
|
// FIXME: Flag the function ISA as thumb with DW_AT_APPLE_isa.
|
||||||
|
|
||||||
|
// Remember that the function is a thumb function. Fixup and relocation
|
||||||
|
// values will need adjusted.
|
||||||
|
getAssembler().setIsThumbFunc(Func);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MCMachOStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
|
void MCMachOStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
|
||||||
|
Loading…
Reference in New Issue
Block a user