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 }

248 F.setVarFixups({Fixup});

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

308 F.setVarContents(Data);

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 }

360 F.setVarContents(Data);

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 (F.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.