LLVM: lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

25

26#define DEBUG_TYPE "loongarch-asmbackend"

27

28using namespace llvm;

29

30std::optional

34#define ELF_RELOC(X, Y) .Case(#X, Y)

35#include "llvm/BinaryFormat/ELFRelocs/LoongArch.def"

36#undef ELF_RELOC

37 .Case("BFD_RELOC_NONE", ELF::R_LARCH_NONE)

38 .Case("BFD_RELOC_32", ELF::R_LARCH_32)

39 .Case("BFD_RELOC_64", ELF::R_LARCH_64)

41 if (Type != -1u)

43 }

44 return std::nullopt;

45}

46

50

51

52

53

57 {"fixup_loongarch_abs_hi20", 5, 20, 0},

58 {"fixup_loongarch_abs_lo12", 10, 12, 0},

59 {"fixup_loongarch_abs64_lo20", 5, 20, 0},

60 {"fixup_loongarch_abs64_hi12", 10, 12, 0},

61 {"fixup_loongarch_tls_le_hi20", 5, 20, 0},

62 {"fixup_loongarch_tls_le_lo12", 10, 12, 0},

63 {"fixup_loongarch_tls_le64_lo20", 5, 20, 0},

64 {"fixup_loongarch_tls_le64_hi12", 10, 12, 0},

65

66 };

67

69 "Not all fixup kinds added to Infos array");

70

71

72

75

78

80 "Invalid kind!");

82}

83

87}

88

91 switch (Fixup.getTargetKind()) {

92 default:

101 if (!isInt<18>(Value))

104 Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned");

105 return (Value >> 2) & 0xffff;

106 }

108 if (!isInt<23>(Value))

111 Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned");

112 return ((Value & 0x3fffc) << 8) | ((Value >> 18) & 0x1f);

113 }

115 if (!isInt<28>(Value))

118 Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned");

119 return ((Value & 0x3fffc) << 8) | ((Value >> 18) & 0x3ff);

120 }

123 return (Value >> 12) & 0xfffff;

126 return Value & 0xfff;

129 return (Value >> 32) & 0xfffff;

132 return (Value >> 52) & 0xfff;

133 }

134}

135

138 unsigned I;

143}

144

149 bool IsResolved,

152 return;

153

156 return;

158 MCContext &Ctx = Asm.getContext();

159

160

163

164

166

167

169

171 unsigned NumBytes = alignTo(Info.TargetSize + Info.TargetOffset, 8) / 8;

172

173 assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");

174

175

176 for (unsigned I = 0; I != NumBytes; ++I) {

178 }

179}

180

181

182

183

184

187

189 return false;

190

191

192 const unsigned MinNopLen = 4;

194 return false;

197}

198

199

200

201

202

203

204

205

206

207

210

212 return false;

213

214

215

216 unsigned InsertedNopBytes;

218 return false;

219

221 MCContext &Ctx = Asm.getContext();

223

227

228 auto createExtendedValue = [&]() {

230 if (MCSym == nullptr) {

231

234 Asm.registerSymbol(*Sym);

237 }

240 };

241

243 MCValue Value = MaxBytesToEmit >= InsertedNopBytes

245 : createExtendedValue();

246 Asm.getWriter().recordRelocation(Asm, &AF, Fixup, Value, FixedValue);

247

248 return true;

249}

250

257 return true;

258 switch (Fixup.getTargetKind()) {

259 default:

260 return STI->hasFeature(LoongArch::FeatureRelax);

266 return Target.isAbsolute();

267 }

268}

269

270static inline std::pair<MCFixupKind, MCFixupKind>

272 switch (Size) {

273 default:

275 case 6:

276 return std::make_pair(

279 case 8:

280 return std::make_pair(

283 case 16:

284 return std::make_pair(

287 case 32:

288 return std::make_pair(

291 case 64:

292 return std::make_pair(

295 case 128:

296 return std::make_pair(

299 }

300}

301

304 int64_t &Value) const {

307 return std::make_pair(false, false);

310 return std::make_pair(true, true);

311}

312

315 bool &WasRelaxed) const {

317

318 int64_t LineDelta = DF.getLineDelta();

319 const MCExpr &AddrDelta = DF.getAddrDelta();

322 size_t OldSize = Data.size();

323

325 if (AddrDelta.evaluateAsAbsolute(Value, Asm))

326 return false;

328 assert(IsAbsolute && "CFA with invalid expression");

329 (void)IsAbsolute;

330

331 Data.clear();

332 Fixups.clear();

334

335

337 OS << uint8_t(dwarf::DW_LNS_advance_line);

339 }

340

342 std::pair<MCFixupKind, MCFixupKind> FK;

343

344

345

346

347 if (Value > 60000) {

348 unsigned PtrSize = C.getAsmInfo()->getCodePointerSize();

349

350 OS << uint8_t(dwarf::DW_LNS_extended_op);

352

353 OS << uint8_t(dwarf::DW_LNE_set_address);

355 assert((PtrSize == 4 || PtrSize == 8) && "Unexpected pointer size");

358 } else {

359 OS << uint8_t(dwarf::DW_LNS_fixed_advance_pc);

363 }

364

365 const MCBinaryExpr &MBE = cast(AddrDelta);

368

370 OS << uint8_t(dwarf::DW_LNS_extended_op);

372 OS << uint8_t(dwarf::DW_LNE_end_sequence);

373 } else {

374 OS << uint8_t(dwarf::DW_LNS_copy);

375 }

376

377 WasRelaxed = OldSize != Data.size();

378 return true;

379}

380

383 bool &WasRelaxed) const {

384 const MCExpr &AddrDelta = DF.getAddrDelta();

387 size_t OldSize = Data.size();

388

390 if (AddrDelta.evaluateAsAbsolute(Value, Asm))

391 return false;

393 assert(IsAbsolute && "CFA with invalid expression");

394 (void)IsAbsolute;

395

396 Data.clear();

397 Fixups.clear();

399

400 assert(Asm.getContext().getAsmInfo()->getMinInstAlignment() == 1 &&

401 "expected 1-byte alignment");

402 if (Value == 0) {

403 WasRelaxed = OldSize != Data.size();

404 return true;

405 }

406

407 auto AddFixups = [&Fixups,

408 &AddrDelta](unsigned Offset,

409 std::pair<MCFixupKind, MCFixupKind> FK) {

410 const MCBinaryExpr &MBE = cast(AddrDelta);

413 };

414

416 OS << uint8_t(dwarf::DW_CFA_advance_loc);

418 } else if (isUInt<8>(Value)) {

419 OS << uint8_t(dwarf::DW_CFA_advance_loc1);

422 } else if (isUInt<16>(Value)) {

423 OS << uint8_t(dwarf::DW_CFA_advance_loc2);

426 } else if (isUInt<32>(Value)) {

427 OS << uint8_t(dwarf::DW_CFA_advance_loc4);

430 } else {

432 }

433

434 WasRelaxed = OldSize != Data.size();

435 return true;

436}

437

440

441

443

444

445

446 for (; Count >= 4; Count -= 4)

447 OS.write("\0\0\x40\x03", 4);

448

449 return true;

450}

451

456 uint64_t &FixedValue) const {

457 std::pair<MCFixupKind, MCFixupKind> FK;

458 uint64_t FixedValueA, FixedValueB;

461

463 if (!force) {

466

467

468

469

470

471 if (&SecA != &SecB)

472 return false;

473

474

475

476

477 if (!STI.hasFeature(LoongArch::FeatureRelax))

478 return true;

479 }

480

481 switch (Fixup.getKind()) {

484 break;

487 break;

490 break;

493 break;

496 break;

497 default:

499 }

504 auto &Assembler = const_cast<MCAssembler &>(Asm);

505 Asm.getWriter().recordRelocation(Assembler, &F, FA, A, FixedValueA);

506 Asm.getWriter().recordRelocation(Assembler, &F, FB, B, FixedValueB);

507 FixedValue = FixedValueA - FixedValueB;

508 return true;

509}

510

511std::unique_ptr

514 OSABI, Is64Bit, STI.hasFeature(LoongArch::FeatureRelax));

515}

516

524}

unsigned const MachineRegisterInfo * MRI

static uint64_t adjustFixupValue(const MCFixup &Fixup, const MCValue &Target, uint64_t Value, MCContext &Ctx, const Triple &TheTriple, bool IsResolved)

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

Analysis containing CSE Info

static RegisterPass< DebugifyFunctionPass > DF("debugify-function", "Attach debug info to a function")

static std::pair< MCFixupKind, MCFixupKind > getRelocPairForSize(unsigned Size)

static void reportOutOfRangeError(MCContext &Ctx, SMLoc Loc, unsigned N)

static void fixupLeb128(MCContext &Ctx, const MCFixup &Fixup, MutableArrayRef< char > Data, uint64_t Value)

PowerPC TLS Dynamic Call Fixup

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef< char > Data, uint64_t Value, bool IsResolved, const MCSubtargetInfo *STI) const override

Apply the Value for given Fixup into the provided data fragment, at the offset specified by the fixup...

bool relaxDwarfLineAddr(const MCAssembler &Asm, MCDwarfLineAddrFragment &DF, bool &WasRelaxed) const override

std::unique_ptr< MCObjectTargetWriter > createObjectTargetWriter() const override

bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, const uint64_t Value, const MCSubtargetInfo *STI) override

Hook to check if a relocation is needed for some target specific reason.

std::optional< MCFixupKind > getFixupKind(StringRef Name) const override

Map a relocation name used in .reloc to a fixup kind.

bool shouldInsertFixupForCodeAlign(MCAssembler &Asm, MCAlignFragment &AF) override

Hook which indicates if the target requires a fixup to be generated when handling an align directive ...

DenseMap< MCSection *, const MCSymbolRefExpr * > & getSecToAlignSym()

std::pair< bool, bool > relaxLEB128(const MCAssembler &Asm, MCLEBFragment &LF, int64_t &Value) const override

const MCFixupKindInfo & getFixupKindInfo(MCFixupKind Kind) const override

Get information on a fixup kind.

bool shouldInsertExtraNopBytesForCodeAlign(const MCAlignFragment &AF, unsigned &Size) override

Hook to check if extra nop bytes must be inserted for alignment directive.

unsigned getNumFixupKinds() const override

Get the number of target specific fixup kinds.

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.

bool relaxDwarfCFA(const MCAssembler &Asm, MCDwarfCallFrameFragment &DF, bool &WasRelaxed) const override

bool handleAddSubRelocations(const MCAssembler &Asm, const MCFragment &F, const MCFixup &Fixup, const MCValue &Target, uint64_t &FixedValue) const override

Align getAlignment() const

unsigned getMaxBytesToEmit() const

const MCSubtargetInfo * getSubtargetInfo() const

Generic interface to target specific assembler backends.

virtual const MCFixupKindInfo & getFixupKindInfo(MCFixupKind Kind) const

Get information on a fixup kind.

Binary assembler expressions.

const MCExpr * getLHS() const

Get the left-hand side expression of the binary operator.

const MCExpr * getRHS() const

Get the right-hand side expression of the binary operator.

static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)

Context object for machine code objects.

void reportError(SMLoc L, const Twine &Msg)

MCSymbol * createNamedTempSymbol()

Create a temporary symbol with a unique name whose name cannot be omitted in the symbol table.

SmallVectorImpl< MCFixup > & getFixups()

Base class for the full range of assembler expressions which are needed for parsing.

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 MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, SMLoc Loc=SMLoc())

MCSection * getParent() const

const MCExpr & getValue() const

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.

MCSymbol * getBeginSymbol()

Generic base class for all target subtargets.

bool hasFeature(unsigned Feature) const

const Triple & getTargetTriple() const

Represent a reference to a symbol from inside an expression.

static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)

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).

MCSection & getSection() const

Get the section associated with a defined, non-absolute symbol.

MCFragment * getFragment(bool SetUsed=true) const

This represents an "assembler immediate".

static MCValue get(const MCSymbolRefExpr *SymA, const MCSymbolRefExpr *SymB=nullptr, int64_t Val=0, uint32_t RefKind=0)

MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...

Represents a location in source code.

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

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.

bool isOSBinFormatELF() const

Tests whether the OS uses the ELF binary format.

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_tls_le_lo12

@ fixup_loongarch_abs_hi20

@ fixup_loongarch_abs_lo12

@ fixup_loongarch_abs64_lo20

@ fixup_loongarch_tls_le64_hi12

@ fixup_loongarch_tls_le64_lo20

@ fixup_loongarch_tls_le_hi20

This is an optimization pass for GlobalISel generic memory operations.

int64_t maxIntN(int64_t N)

Gets the maximum value for a N-bit signed integer.

bool isUIntN(unsigned N, uint64_t x)

Checks if an unsigned integer fits into the given (dynamic) bit width.

std::unique_ptr< MCObjectTargetWriter > createLoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit, bool Relax)

MCAsmBackend * createLoongArchAsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options)

MCFixupKind

Extensible enumeration to represent the type of a fixup.

@ FirstLiteralRelocationKind

The range [FirstLiteralRelocationKind, MaxTargetFixupKind) is used for relocations coming from ....

@ 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.

uint64_t alignTo(uint64_t Size, Align A)

Returns a multiple of A needed to store Size bytes.

int64_t minIntN(int64_t N)

Gets the minimum 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.

unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)

Utility function to encode a ULEB128 value to an output stream.

unsigned Log2(Align A)

Returns the log2 of the alignment.

uint64_t value() const

This is a hole in the type system and should not be abused.

Target independent information on a fixup kind.

@ FKF_IsPCRel

Is this fixup kind PCrelative? This is used by the assembler backend to evaluate fixup values in a ta...