LLVM: lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
26
27#define DEBUG_TYPE "loongarch-asmbackend"
28
29using namespace llvm;
30
32 uint8_t OSABI, bool Is64Bit,
35 Is64Bit(Is64Bit), TargetOptions(Options) {}
36
37std::optional
39 if (STI.getTargetTriple().isOSBinFormatELF()) {
41#define ELF_RELOC(X, Y) .Case(#X, Y)
42#include "llvm/BinaryFormat/ELFRelocs/LoongArch.def"
43#undef ELF_RELOC
44 .Case("BFD_RELOC_NONE", ELF::R_LARCH_NONE)
45 .Case("BFD_RELOC_32", ELF::R_LARCH_32)
46 .Case("BFD_RELOC_64", ELF::R_LARCH_64)
48 if (Type != -1u)
50 }
51 return std::nullopt;
52}
53
56
57
58
59
60 {"fixup_loongarch_b16", 10, 16, 0},
61 {"fixup_loongarch_b21", 0, 26, 0},
62 {"fixup_loongarch_b26", 0, 26, 0},
63 {"fixup_loongarch_abs_hi20", 5, 20, 0},
64 {"fixup_loongarch_abs_lo12", 10, 12, 0},
65 {"fixup_loongarch_abs64_lo20", 5, 20, 0},
66 {"fixup_loongarch_abs64_hi12", 10, 12, 0},
67 };
68
70 "Not all fixup kinds added to Infos array");
71
72
73
75 return {};
76
79
82 "Invalid kind!");
84}
85
90
93 switch (Fixup.getKind()) {
94 default:
106 Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned");
107 return (Value >> 2) & 0xffff;
108 }
113 Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned");
114 return ((Value & 0x3fffc) << 8) | ((Value >> 18) & 0x1f);
115 }
120 Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned");
121 return ((Value & 0x3fffc) << 8) | ((Value >> 18) & 0x3ff);
122 }
124 return (Value >> 12) & 0xfffff;
126 return Value & 0xfff;
128 return (Value >> 32) & 0xfffff;
130 return (Value >> 52) & 0xfff;
131 }
132}
133
136 unsigned I;
140 Ctx.reportError(Fixup.getLoc(), "Invalid uleb128 value!");
141}
142
148 return;
149
150 auto Kind = Fixup.getKind();
152 return;
155
156
159
160
162
163
164 Value <<= Info.TargetOffset;
165
166 unsigned NumBytes = alignTo(Info.TargetSize + Info.TargetOffset, 8) / 8;
167
168 assert(Fixup.getOffset() + NumBytes <= F.getSize() &&
169 "Invalid fixup offset!");
170
171
172 for (unsigned I = 0; I != NumBytes; ++I) {
174 }
175}
176
177static inline std::pair<MCFixupKind, MCFixupKind>
179 switch (Size) {
180 default:
182 case 6:
183 return std::make_pair(ELF::R_LARCH_ADD6, ELF::R_LARCH_SUB6);
184 case 8:
185 return std::make_pair(ELF::R_LARCH_ADD8, ELF::R_LARCH_SUB8);
186 case 16:
187 return std::make_pair(ELF::R_LARCH_ADD16, ELF::R_LARCH_SUB16);
188 case 32:
189 return std::make_pair(ELF::R_LARCH_ADD32, ELF::R_LARCH_SUB32);
190 case 64:
191 return std::make_pair(ELF::R_LARCH_ADD64, ELF::R_LARCH_SUB64);
192 case 128:
193 return std::make_pair(ELF::R_LARCH_ADD_ULEB128, ELF::R_LARCH_SUB_ULEB128);
194 }
195}
196
197
198
199
200
201
203
204
205
206
207
208
209
210 auto *Sec = F.getParent();
211 if (F.getLayoutOrder() <= Sec->firstLinkerRelaxable())
212 return false;
213
214
215
216 const unsigned MinNopLen = 4;
217 unsigned MaxBytesToEmit = F.getAlignMaxBytesToEmit();
218 if (MaxBytesToEmit < MinNopLen)
219 return false;
220
221 Size = F.getAlignment().value() - MinNopLen;
222 if (F.getAlignment() <= MinNopLen)
223 return false;
224
226 const MCExpr *Expr = nullptr;
227 if (MaxBytesToEmit >= Size) {
229 } else {
232 if (SymRef == nullptr) {
233
234 MCSymbol *Sym = Ctx.createNamedTempSymbol("la-relax-align");
236 Asm->registerSymbol(*Sym);
239 }
241 SymRef,
243 Ctx),
244 Ctx);
245 }
249 F.setLinkerRelaxable();
250 return true;
251}
252
254 int64_t &Value) const {
255 const MCExpr &Expr = F.getLEBValue();
257 return std::make_pair(false, false);
259 return std::make_pair(true, true);
260}
261
264 int64_t LineDelta = F.getDwarfLineDelta();
265 const MCExpr &AddrDelta = F.getDwarfAddrDelta();
267 if (AddrDelta.evaluateAsAbsolute(Value, *Asm))
268 return false;
269 [[maybe_unused]] bool IsAbsolute =
272
275
276
278 OS << uint8_t(dwarf::DW_LNS_advance_line);
280 }
281
282
283
284
285 unsigned PCBytes;
286 if (Value > 60000) {
287 unsigned PtrSize = C.getAsmInfo()->getCodePointerSize();
288 assert((PtrSize == 4 || PtrSize == 8) && "Unexpected pointer size");
289 PCBytes = PtrSize;
290 OS << uint8_t(dwarf::DW_LNS_extended_op) << uint8_t(PtrSize + 1)
291 << uint8_t(dwarf::DW_LNE_set_address);
293 } else {
294 PCBytes = 2;
295 OS << uint8_t(dwarf::DW_LNS_fixed_advance_pc);
297 }
299
301 OS << uint8_t(dwarf::DW_LNS_extended_op);
303 OS << uint8_t(dwarf::DW_LNE_end_sequence);
304 } else {
305 OS << uint8_t(dwarf::DW_LNS_copy);
306 }
307
311 return true;
312}
313
315 const MCExpr &AddrDelta = F.getDwarfAddrDelta();
318 if (AddrDelta.evaluateAsAbsolute(Value, *Asm))
319 return false;
321 assert(IsAbsolute && "CFA with invalid expression");
322 (void)IsAbsolute;
323
324 assert(getContext().getAsmInfo()->getMinInstAlignment() == 1 &&
325 "expected 1-byte alignment");
326 if (Value == 0) {
327 F.clearVarContents();
328 F.clearVarFixups();
329 return true;
330 }
331
332 auto AddFixups = [&Fixups,
333 &AddrDelta](unsigned Offset,
334 std::pair<MCFixupKind, MCFixupKind> FK) {
338 };
339
343 OS << uint8_t(dwarf::DW_CFA_advance_loc);
346 OS << uint8_t(dwarf::DW_CFA_advance_loc1);
350 OS << uint8_t(dwarf::DW_CFA_advance_loc2);
354 OS << uint8_t(dwarf::DW_CFA_advance_loc4);
357 } else {
359 }
361 F.setVarFixups(Fixups);
362 return true;
363}
364
367
368
370
371
372
374 OS.write("\0\0\x40\x03", 4);
375
376 return true;
377}
378
379bool LoongArchAsmBackend::isPCRelFixupResolved(const MCSymbol *SymA,
381
382
383 if (.getParent()->isLinkerRelaxable())
384 return true;
385
386
387
388
389
390 if (!PCRelTemp)
397}
398
401 bool IsResolved) {
402 auto Fallback = [&]() {
404 return true;
405 };
406 uint64_t FixedValueA, FixedValueB;
407 if (Target.getSubSym()) {
409 "relocatable SymA-SymB cannot have relocation specifier");
410 std::pair<MCFixupKind, MCFixupKind> FK;
413
415 if (!force) {
418 const MCSection &SecCur = *F.getParent();
419
420
421
422
423
424
425
426
427
428 if (&SecA != &SecB && &SecB == &SecCur &&
429 isPCRelFixupResolved(Target.getSubSym(), F))
431
432
433
434
436 return true;
437 }
438
439 switch (Fixup.getKind()) {
442 break;
445 break;
448 break;
451 break;
454 break;
455 default:
457 }
462 Asm->getWriter().recordRelocation(F, FA, A, FixedValueA);
463 Asm->getWriter().recordRelocation(F, FB, B, FixedValueB);
464 FixedValue = FixedValueA - FixedValueB;
465 return false;
466 }
467
468
469
470 if (Fixup.isLinkerRelaxable())
471 IsResolved = false;
472 if (IsResolved && Fixup.isPCRel())
473 IsResolved = isPCRelFixupResolved(Target.getAddSym(), F);
474
475 if (!IsResolved)
476 Asm->getWriter().recordRelocation(F, Fixup, Target, FixedValue);
477
478 if (Fixup.isLinkerRelaxable()) {
480 Asm->getWriter().recordRelocation(F, FA, MCValue::get(nullptr),
481 FixedValueA);
482 }
483
484 return true;
485}
486
487std::unique_ptr
491
unsigned const MachineRegisterInfo * MRI
static uint64_t adjustFixupValue(const MCFixup &Fixup, const MCValue &Target, uint64_t Value, MCContext &Ctx, const Triple &TheTriple, bool IsResolved)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static std::pair< MCFixupKind, MCFixupKind > getRelocPairForSize(unsigned Size)
Definition LoongArchAsmBackend.cpp:178
static void fixupLeb128(MCContext &Ctx, const MCFixup &Fixup, uint8_t *Data, uint64_t Value)
Definition LoongArchAsmBackend.cpp:134
static void reportOutOfRangeError(MCContext &Ctx, SMLoc Loc, unsigned N)
Definition LoongArchAsmBackend.cpp:86
PowerPC TLS Dynamic Call Fixup
bool relaxDwarfCFA(MCFragment &) const override
Definition LoongArchAsmBackend.cpp:314
std::unique_ptr< MCObjectTargetWriter > createObjectTargetWriter() const override
Definition LoongArchAsmBackend.cpp:488
bool addReloc(const MCFragment &, const MCFixup &, const MCValue &, uint64_t &FixedValue, bool IsResolved)
Definition LoongArchAsmBackend.cpp:399
std::optional< MCFixupKind > getFixupKind(StringRef Name) const override
Map a relocation name used in .reloc to a fixup kind.
Definition LoongArchAsmBackend.cpp:38
DenseMap< MCSection *, const MCSymbolRefExpr * > & getSecToAlignSym()
bool relaxDwarfLineAddr(MCFragment &) const override
Definition LoongArchAsmBackend.cpp:262
LoongArchAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI, bool Is64Bit, const MCTargetOptions &Options)
Definition LoongArchAsmBackend.cpp:31
bool writeNopData(raw_ostream &OS, uint64_t Count, const MCSubtargetInfo *STI) const override
Write an (optimal) nop sequence of Count bytes to the given output.
Definition LoongArchAsmBackend.cpp:365
void applyFixup(const MCFragment &, const MCFixup &, const MCValue &Target, uint8_t *Data, uint64_t Value, bool IsResolved) override
Definition LoongArchAsmBackend.cpp:143
bool relaxAlign(MCFragment &F, unsigned &Size) override
Definition LoongArchAsmBackend.cpp:202
std::pair< bool, bool > relaxLEB128(MCFragment &F, int64_t &Value) const override
Definition LoongArchAsmBackend.cpp:253
MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override
Get information on a fixup kind.
Definition LoongArchAsmBackend.cpp:54
Generic interface to target specific assembler backends.
MCAsmBackend(llvm::endianness Endian)
virtual MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const
Get information on a fixup kind.
MCContext & getContext() const
void maybeAddReloc(const MCFragment &, const MCFixup &, const MCValue &, uint64_t &Value, bool IsResolved)
Binary assembler expressions.
const MCExpr * getLHS() const
Get the left-hand side expression of the binary operator.
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
const MCExpr * getRHS() const
Get the right-hand side expression of the binary operator.
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Context object for machine code objects.
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
Base class for the full range of assembler expressions which are needed for parsing.
static LLVM_ABI bool evaluateSymbolicAdd(const MCAssembler *, bool, const MCValue &, const MCValue &, MCValue &)
LLVM_ABI bool evaluateKnownAbsolute(int64_t &Res, const MCAssembler &Asm) const
Aggressive variant of evaluateAsRelocatable when relocations are unavailable (e.g.
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
static MCFixupKind getDataKindForSize(unsigned Size)
Return the generic fixup kind for a value with the given size.
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, bool PCRel=false)
Consider bit fields if we need more flags.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Instances of this class represent a uniqued identifier for a section in the current translation unit.
bool isLinkerRelaxable() const
MCSymbol * getBeginSymbol()
Generic base class for all target subtargets.
const Triple & getTargetTriple() const
Represent a reference to a symbol from inside an expression.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
bool isInSection() const
isInSection - Check if this symbol is defined in some section (i.e., it is defined but not absolute).
void setFragment(MCFragment *F) const
Mark the symbol as defined in the fragment F.
MCSection & getSection() const
Get the section associated with a defined, non-absolute symbol.
MCFragment * getFragment() const
static MCValue get(const MCSymbol *SymA, const MCSymbol *SymB=nullptr, int64_t Val=0, uint32_t Specifier=0)
const MCSymbol * getSubSym() const
Represents a location in source code.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
This class implements an extremely fast bulk output stream that can only output to a stream.
raw_ostream & write_zeros(unsigned NumZeros)
write_zeros - Insert 'NumZeros' nulls.
uint64_t tell() const
tell - Return the current offset with the file.
raw_ostream & write(unsigned char C)
A raw_ostream that writes to an SmallVector or SmallString.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
@ fixup_loongarch_abs64_hi12
@ fixup_loongarch_abs_hi20
@ fixup_loongarch_abs_lo12
@ fixup_loongarch_abs64_lo20
bool isRelocation(MCFixupKind FixupKind)
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
This is an optimization pass for GlobalISel generic memory operations.
std::unique_ptr< MCObjectTargetWriter > createLoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit)
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
constexpr int64_t minIntN(int64_t N)
Gets the minimum value for a N-bit signed integer.
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
uint16_t MCFixupKind
Extensible enumeration to represent the type of a fixup.
MCAsmBackend * createLoongArchAsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options)
Definition LoongArchAsmBackend.cpp:492
FunctionAddr VTableAddr Count
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
@ FirstLiteralRelocationKind
@ FK_Data_8
A eight-byte fixup.
@ FK_Data_1
A one-byte fixup.
@ FK_Data_4
A four-byte fixup.
@ FK_Data_leb128
A leb128 fixup.
@ FK_Data_2
A two-byte fixup.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
constexpr int64_t maxIntN(int64_t N)
Gets the maximum value for a N-bit signed integer.
unsigned encodeSLEB128(int64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a SLEB128 value to an output stream.
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
unsigned Log2(Align A)
Returns the log2 of the alignment.
Target independent information on a fixup kind.