32 using namespace Hexagon;
34 #define DEBUG_TYPE "hexagon-asm-backend"
37 (
"mno-fixup",
cl::desc(
"Disable fixing up resolved relocations for Hexagon"));
44 mutable uint64_t relaxedCnt;
45 std::unique_ptr <MCInstrInfo> MCII;
46 std::unique_ptr <MCInst *> RelaxTarget;
71 if (Extender ==
nullptr)
72 const_cast<HexagonAsmBackend *
>(
this)->Extender =
new (Context)
MCInst;
75 MCInst *takeExtender()
const {
76 assert(Extender !=
nullptr);
77 MCInst * Result = Extender;
78 const_cast<HexagonAsmBackend *
>(
this)->Extender =
nullptr;
82 unsigned getNumFixupKinds()
const override {
95 {
"fixup_Hexagon_LO16", 0, 32, 0 },
96 {
"fixup_Hexagon_HI16", 0, 32, 0 },
97 {
"fixup_Hexagon_32", 0, 32, 0 },
98 {
"fixup_Hexagon_16", 0, 32, 0 },
99 {
"fixup_Hexagon_8", 0, 32, 0 },
100 {
"fixup_Hexagon_GPREL16_0", 0, 32, 0 },
101 {
"fixup_Hexagon_GPREL16_1", 0, 32, 0 },
102 {
"fixup_Hexagon_GPREL16_2", 0, 32, 0 },
103 {
"fixup_Hexagon_GPREL16_3", 0, 32, 0 },
104 {
"fixup_Hexagon_HL16", 0, 32, 0 },
108 {
"fixup_Hexagon_32_6_X", 0, 32, 0 },
114 {
"fixup_Hexagon_16_X", 0, 32, 0 },
115 {
"fixup_Hexagon_12_X", 0, 32, 0 },
116 {
"fixup_Hexagon_11_X", 0, 32, 0 },
117 {
"fixup_Hexagon_10_X", 0, 32, 0 },
118 {
"fixup_Hexagon_9_X", 0, 32, 0 },
119 {
"fixup_Hexagon_8_X", 0, 32, 0 },
120 {
"fixup_Hexagon_7_X", 0, 32, 0 },
121 {
"fixup_Hexagon_6_X", 0, 32, 0 },
123 {
"fixup_Hexagon_COPY", 0, 32, 0 },
124 {
"fixup_Hexagon_GLOB_DAT", 0, 32, 0 },
125 {
"fixup_Hexagon_JMP_SLOT", 0, 32, 0 },
126 {
"fixup_Hexagon_RELATIVE", 0, 32, 0 },
128 {
"fixup_Hexagon_GOTREL_LO16", 0, 32, 0 },
129 {
"fixup_Hexagon_GOTREL_HI16", 0, 32, 0 },
130 {
"fixup_Hexagon_GOTREL_32", 0, 32, 0 },
131 {
"fixup_Hexagon_GOT_LO16", 0, 32, 0 },
132 {
"fixup_Hexagon_GOT_HI16", 0, 32, 0 },
133 {
"fixup_Hexagon_GOT_32", 0, 32, 0 },
134 {
"fixup_Hexagon_GOT_16", 0, 32, 0 },
135 {
"fixup_Hexagon_DTPMOD_32", 0, 32, 0 },
136 {
"fixup_Hexagon_DTPREL_LO16", 0, 32, 0 },
137 {
"fixup_Hexagon_DTPREL_HI16", 0, 32, 0 },
138 {
"fixup_Hexagon_DTPREL_32", 0, 32, 0 },
139 {
"fixup_Hexagon_DTPREL_16", 0, 32, 0 },
142 {
"fixup_Hexagon_GD_GOT_LO16", 0, 32, 0 },
143 {
"fixup_Hexagon_GD_GOT_HI16", 0, 32, 0 },
144 {
"fixup_Hexagon_GD_GOT_32", 0, 32, 0 },
145 {
"fixup_Hexagon_GD_GOT_16", 0, 32, 0 },
146 {
"fixup_Hexagon_LD_GOT_LO16", 0, 32, 0 },
147 {
"fixup_Hexagon_LD_GOT_HI16", 0, 32, 0 },
148 {
"fixup_Hexagon_LD_GOT_32", 0, 32, 0 },
149 {
"fixup_Hexagon_LD_GOT_16", 0, 32, 0 },
150 {
"fixup_Hexagon_IE_LO16", 0, 32, 0 },
151 {
"fixup_Hexagon_IE_HI16", 0, 32, 0 },
152 {
"fixup_Hexagon_IE_32", 0, 32, 0 },
153 {
"fixup_Hexagon_IE_16", 0, 32, 0 },
154 {
"fixup_Hexagon_IE_GOT_LO16", 0, 32, 0 },
155 {
"fixup_Hexagon_IE_GOT_HI16", 0, 32, 0 },
156 {
"fixup_Hexagon_IE_GOT_32", 0, 32, 0 },
157 {
"fixup_Hexagon_IE_GOT_16", 0, 32, 0 },
158 {
"fixup_Hexagon_TPREL_LO16", 0, 32, 0 },
159 {
"fixup_Hexagon_TPREL_HI16", 0, 32, 0 },
160 {
"fixup_Hexagon_TPREL_32", 0, 32, 0 },
161 {
"fixup_Hexagon_TPREL_16", 0, 32, 0 },
163 {
"fixup_Hexagon_GOTREL_32_6_X", 0, 32, 0 },
164 {
"fixup_Hexagon_GOTREL_16_X", 0, 32, 0 },
165 {
"fixup_Hexagon_GOTREL_11_X", 0, 32, 0 },
166 {
"fixup_Hexagon_GOT_32_6_X", 0, 32, 0 },
167 {
"fixup_Hexagon_GOT_16_X", 0, 32, 0 },
168 {
"fixup_Hexagon_GOT_11_X", 0, 32, 0 },
169 {
"fixup_Hexagon_DTPREL_32_6_X", 0, 32, 0 },
170 {
"fixup_Hexagon_DTPREL_16_X", 0, 32, 0 },
171 {
"fixup_Hexagon_DTPREL_11_X", 0, 32, 0 },
172 {
"fixup_Hexagon_GD_GOT_32_6_X", 0, 32, 0 },
173 {
"fixup_Hexagon_GD_GOT_16_X", 0, 32, 0 },
174 {
"fixup_Hexagon_GD_GOT_11_X", 0, 32, 0 },
175 {
"fixup_Hexagon_LD_GOT_32_6_X", 0, 32, 0 },
176 {
"fixup_Hexagon_LD_GOT_16_X", 0, 32, 0 },
177 {
"fixup_Hexagon_LD_GOT_11_X", 0, 32, 0 },
178 {
"fixup_Hexagon_IE_32_6_X", 0, 32, 0 },
179 {
"fixup_Hexagon_IE_16_X", 0, 32, 0 },
180 {
"fixup_Hexagon_IE_GOT_32_6_X", 0, 32, 0 },
181 {
"fixup_Hexagon_IE_GOT_16_X", 0, 32, 0 },
182 {
"fixup_Hexagon_IE_GOT_11_X", 0, 32, 0 },
183 {
"fixup_Hexagon_TPREL_32_6_X", 0, 32, 0 },
184 {
"fixup_Hexagon_TPREL_16_X", 0, 32, 0 },
185 {
"fixup_Hexagon_TPREL_11_X", 0, 32, 0 }
202 bool &IsResolved)
override {
205 switch((
unsigned)Kind) {
354 switch((
unsigned)Kind) {
381 void HandleFixupError(
const int bits,
const int align_bits,
382 const int64_t FixupValue,
const char *fixupStr)
const {
387 std::stringstream errStr;
388 errStr <<
"\nError: value " <<
394 " when resolving " <<
403 void applyFixup(
const MCFixup &Fixup,
char *Data,
unsigned DataSize,
404 uint64_t FixupValue,
bool IsPCRel)
const override {
408 if (!FixupValue)
return;
419 assert(Offset + NumBytes <= DataSize &&
"Invalid fixup offset!");
420 char *InstAddr = Data +
Offset;
425 int sValue = (int)Value;
427 switch((
unsigned)
Kind) {
433 HandleFixupError(7, 2, (int64_t)FixupValue,
"B7_PCREL");
435 InstMask = 0x00001f18;
436 Reloc = (((Value >> 2) & 0x1f) << 8) |
437 ((Value & 0x3) << 3);
442 HandleFixupError(9, 2, (int64_t)FixupValue,
"B9_PCREL");
444 InstMask = 0x003000fe;
445 Reloc = (((Value >> 7) & 0x3) << 20) |
446 ((Value & 0x7f) << 1);
452 if (!(
isIntN(13, sValue)))
453 HandleFixupError(13, 2, (int64_t)FixupValue,
"B13_PCREL");
455 InstMask = 0x00202ffe;
456 Reloc = (((Value >> 12) & 0x1) << 21) |
457 (((Value >> 11) & 0x1) << 13) |
458 ((Value & 0x7ff) << 1);
462 if (!(
isIntN(15, sValue)))
463 HandleFixupError(15, 2, (int64_t)FixupValue,
"B15_PCREL");
465 InstMask = 0x00df20fe;
466 Reloc = (((Value >> 13) & 0x3) << 22) |
467 (((Value >> 8) & 0x1f) << 16) |
468 (((Value >> 7) & 0x1) << 13) |
469 ((Value & 0x7f) << 1);
473 if (!(
isIntN(22, sValue)))
474 HandleFixupError(22, 2, (int64_t)FixupValue,
"B22_PCREL");
476 InstMask = 0x01ff3ffe;
477 Reloc = (((Value >> 13) & 0x1ff) << 16) |
478 ((Value & 0x1fff) << 1);
482 InstMask = 0x0fff3fff;
483 Reloc = (((Value >> 14) & 0xfff) << 16) |
491 InstMask = 0xffffffff;
496 DEBUG(
dbgs() <<
"Name=" << getFixupKindInfo(Kind).
Name <<
"(" <<
497 (
unsigned)Kind <<
")\n");
499 for (
unsigned i = 0;
i < NumBytes;
i++)
500 OldData |= (InstAddr[
i] << (
i * 8)) & (0xff << (
i * 8));
503 ": Offset=" << Offset <<
504 ": Size=" << DataSize <<
511 for (
unsigned i = 0;
i < NumBytes;
i++){
512 InstAddr[
i] &= uint8_t(~InstMask >> (
i * 8)) & 0xff;
513 InstAddr[
i] |= uint8_t(Reloc >> (
i * 8)) & 0xff;
517 for (
unsigned i = 0;
i < NumBytes;
i++)
518 NewData |= (InstAddr[
i] << (
i * 8)) & (0xff << (
i * 8));
522 bool isInstRelaxable(
MCInst const &HMI)
const {
524 bool Relaxable =
false;
549 bool mayNeedRelaxation(
MCInst const &Inst)
const override {
555 bool fixupNeedsRelaxationAdvanced(
const MCFixup &Fixup,
bool Resolved,
562 *RelaxTarget =
nullptr;
565 bool Relaxable = isInstRelaxable(MCI);
566 if (Relaxable ==
false)
570 switch ((
unsigned)Fixup.
getKind()) {
595 int64_t sValue = Value;
598 switch ((
unsigned)Kind) {
612 maxValue = INT64_MAX;
616 bool isFarAway = -maxValue > sValue || sValue > maxValue - 1;
631 bool fixupNeedsRelaxation(
const MCFixup &Fixup, uint64_t Value,
638 MCInst &Res)
const override {
640 "Hexagon relaxInstruction only works on bundles");
649 if (*RelaxTarget == &CrntHMI) {
652 "No room to insert extender for relaxation");
654 MCInst *HMIx = takeExtender();
659 *RelaxTarget =
nullptr;
665 assert(Update &&
"Didn't find relaxation target");
668 bool writeNopData(uint64_t Count,
670 static const uint32_t Nopcode = 0x7f000000,
671 ParseIn = 0x00004000,
672 ParseEnd = 0x0000c000;
675 DEBUG(
dbgs() <<
"Alignment not a multiple of the instruction size:" <<
676 Count % HEXAGON_INSTR_SIZE <<
"/" << HEXAGON_INSTR_SIZE <<
"\n");
686 OW->
write32(Nopcode | ParseBits);
694 auto &Fragments =
I->getFragmentList();
695 for (
auto &J : Fragments) {
696 switch (J.getKind()) {
701 for (
auto K = J.getIterator();
704 switch (K->getKind()) {
713 auto &RF = cast<MCRelaxableFragment>(*K);
723 Inst.erase(Inst.end() - 1);
730 ReplaceInstruction(Asm.
getEmitter(), RF, Inst);
751 return new HexagonAsmBackend(T, OSABI, CPU);
static MCInstrInfo * createMCInstrInfo()
OSType getOS() const
getOS - Get the parsed operating system type of this triple.
This represents an "assembler immediate".
Describe properties that are true of each instruction in the target description file.
bool isBundle(MCInst const &MCI)
MCCodeEmitter & getEmitter() const
A raw_ostream that writes to an SmallVector or SmallString.
const MCSubtargetInfo & getSubtargetInfo()
MCInst deriveExtender(MCInstrInfo const &MCII, MCInst const &Inst, MCOperand const &MO)
MCContext & getContext() const
Defines the object file and target independent interfaces used by the assembler backend to write nati...
void write8(uint8_t Value)
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
const MCInst & getInst() const
Is this fixup kind PCrelative? This is used by the assembler backend to evaluate fixup values in a ta...
MCInst const & instruction(MCInst const &MCB, size_t Index)
Encapsulates the layout of an assembly file at a particular point in time.
#define HEXAGON_PACKET_SIZE
virtual void encodeInstruction(const MCInst &Inst, raw_ostream &OS, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const =0
EncodeInstruction - Encode the given Inst to bytes on the output stream OS.
bool isBranch() const
Returns true if this is a conditional, unconditional, or indirect branch.
Context object for machine code objects.
static cl::opt< bool > DisableFixup("mno-fixup", cl::desc("Disable fixing up resolved relocations for Hexagon"))
raw_ostream & write_hex(unsigned long long N)
Output N in hexadecimal, without any prefix or padding.
SmallVectorImpl< char > & getContents()
uint32_t getOffset() const
MCObjectWriter * createHexagonELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI, StringRef CPU)
Instances of this class represent a single low-level machine instruction.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
static unsigned getFixupKindNumBytes(unsigned Kind)
The number of bytes the fixup may change.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
A relaxable fragment holds on to its MCInst, since it may need to be relaxed during the assembler lay...
const MCExpr * getExpr() const
void write32(uint32_t Value)
static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value, MCContext *Ctx)
uint64_t computeFragmentSize(const MCAsmLayout &Layout, const MCFragment &F) const
Compute the effective fragment size assuming it is laid out at the given SectionAddress and FragmentO...
int64_t getSExtValue() const
Get sign extended value.
void invalidateFragmentsFrom(MCFragment *F)
Invalidate the fragments starting with F because it has been resized.
MCCodeEmitter - Generic instruction encoding interface.
MCFixupKind
Extensible enumeration to represent the type of a fixup.
SmallVectorImpl< MCFixup > & getFixups()
llvm::SmallVectorImpl< MCSection * > & getSectionOrder()
iterator_range< MCInst::const_iterator > bundleInstructions(MCInst const &MCI)
Definition for classes that emit Hexagon machine code from MCInsts.
bool isIntN(unsigned N, int64_t x)
isIntN - Checks if an signed integer fits into the given (dynamic) bit width.
MCFixupKind getKind() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned short getExtendableOp(MCInstrInfo const &MCII, MCInst const &MCI)
Triple - Helper class for working with autoconf configuration names.
void setOpcode(unsigned Op)
bool isExtendable(MCInstrInfo const &MCII, MCInst const &MCI)
A four-byte pc relative fixup.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
bool HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI, MCInst &)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
unsigned getOpcode() const
Target - Wrapper for Target specific information.
Class for arbitrary precision integers.
static MCOperand createInst(const MCInst *Val)
const MCRegisterInfo * getRegisterInfo() const
MCSubtargetInfo - Generic base class for all target subtargets.
MCInstrDesc const & getDesc(MCInstrInfo const &MCII, MCInst const &MCI)
size_t bundleSize(MCInst const &MCI)
Target independent information on a fixup kind.
An abstract base class for streams implementations that also support a pwrite operation.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
#define HEXAGON_INSTR_SIZE
LLVM Value Representation.
Generic interface to target specific assembler backends.
static const unsigned Nop
Instruction opcodes emitted via means other than CodeGen.
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
Lightweight error class with error context and mandatory checking.
MCAssembler & getAssembler() const
Get the assembler object this is a layout for.
Check for a valid bundle.
MCAsmBackend * createHexagonAsmBackend(Target const &T, MCRegisterInfo const &, const Triple &TT, StringRef CPU, const MCTargetOptions &Options)
void addOperand(const MCOperand &Op)
StringRef - Represent a constant reference to a string, i.e.
unsigned getType(MCInstrInfo const &MCII, MCInst const &MCI)
Instances of this class represent operands of the MCInst class.
bool mustNotExtend(MCExpr const &Expr)
virtual const MCFixupKindInfo & getFixupKindInfo(MCFixupKind Kind) const
Get information on a fixup kind.
MCOperand const & getExtendableOperand(MCInstrInfo const &MCII, MCInst const &MCI)
void setInst(const MCInst &Value)
const MCOperand & getOperand(unsigned i) const