LLVM: lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

25

26using namespace llvm;

27

30

31

32

35 cl::desc("Emit R_RISCV_SET_ULEB128/E_RISCV_SUB_ULEB128 if appropriate"));

36

39 unsigned Type;

41#define ELF_RELOC(NAME, ID) .Case(#NAME, ID)

42#include "llvm/BinaryFormat/ELFRelocs/RISCV.def"

43#undef ELF_RELOC

44#define ELF_RISCV_NONSTANDARD_RELOC(_VENDOR, NAME, ID) .Case(#NAME, ID)

45#include "llvm/BinaryFormat/ELFRelocs/RISCV_nonstandard.def"

46#undef ELF_RISCV_NONSTANDARD_RELOC

47 .Case("BFD_RELOC_NONE", ELF::R_RISCV_NONE)

48 .Case("BFD_RELOC_32", ELF::R_RISCV_32)

49 .Case("BFD_RELOC_64", ELF::R_RISCV_64)

51 if (Type != -1u)

53 }

54 return std::nullopt;

55}

56

60

61

62

63

64 {"fixup_riscv_hi20", 12, 20, 0},

65 {"fixup_riscv_lo12_i", 20, 12, 0},

66 {"fixup_riscv_12_i", 20, 12, 0},

67 {"fixup_riscv_lo12_s", 0, 32, 0},

68 {"fixup_riscv_pcrel_hi20", 12, 20,

70 {"fixup_riscv_pcrel_lo12_i", 20, 12,

72 {"fixup_riscv_pcrel_lo12_s", 0, 32,

75 {"fixup_riscv_tprel_hi20", 12, 20, 0},

76 {"fixup_riscv_tprel_lo12_i", 20, 12, 0},

77 {"fixup_riscv_tprel_lo12_s", 0, 32, 0},

78 {"fixup_riscv_tprel_add", 0, 0, 0},

87 {"fixup_riscv_relax", 0, 0, 0},

88 {"fixup_riscv_align", 0, 0, 0},

89

90 {"fixup_riscv_tlsdesc_hi20", 12, 20,

92 {"fixup_riscv_tlsdesc_load_lo12", 20, 12, 0},

93 {"fixup_riscv_tlsdesc_add_lo12", 20, 12, 0},

94 {"fixup_riscv_tlsdesc_call", 0, 0, 0},

95 };

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

98

99

100

103

106

108 "Invalid kind!");

110}

111

112

113

114

121 return true;

122 switch (Fixup.getTargetKind()) {

123 default:

124 break;

130 if (Target.isAbsolute())

131 return false;

132 break;

137 return true;

138 }

139

140 return STI->hasFeature(RISCV::FeatureRelax) || ForceRelocs;

141}

142

147 return false;

148

150 unsigned Kind = Fixup.getTargetKind();

151

152

153

154

155

156 if (!Resolved && !WasForced)

157 return true;

158

159 switch (Kind) {

160 default:

161 return false;

163

164

167

168

171

172

173 return !isInt<13>(Offset);

174 }

175}

176

181 default:

183 case RISCV::C_BEQZ:

184 case RISCV::C_BNEZ:

185 case RISCV::C_J:

186 case RISCV::C_JAL: {

188 assert(Success && "Can't uncompress instruction");

189 break;

190 }

191 case RISCV::BEQ:

192 case RISCV::BNE:

193 case RISCV::BLT:

194 case RISCV::BGE:

195 case RISCV::BLTU:

196 case RISCV::BGEU:

201 break;

202 }

203 Inst = std::move(Res);

204}

205

208 bool &WasRelaxed) const {

210

211 int64_t LineDelta = DF.getLineDelta();

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

215 size_t OldSize = Data.size();

216

218 [[maybe_unused]] bool IsAbsolute =

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

221

222 Data.clear();

223 Fixups.clear();

225

226

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

230 }

231

233 std::pair<MCFixupKind, MCFixupKind> Fixup;

234

235

236

237

238 if (Value > 60000) {

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

240

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

243

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

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

249 } else {

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

254 }

255

256 const MCBinaryExpr &MBE = cast(AddrDelta);

259

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

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

264 } else {

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

266 }

267

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

269 return true;

270}

271

274 bool &WasRelaxed) const {

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

278 size_t OldSize = Data.size();

279

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

282 return false;

283 [[maybe_unused]] bool IsAbsolute =

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

286

287 Data.clear();

288 Fixups.clear();

290

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

292 "expected 1-byte alignment");

293 if (Value == 0) {

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

295 return true;

296 }

297

298 auto AddFixups = [&Fixups, &AddrDelta](unsigned Offset,

299 std::pair<unsigned, unsigned> Fixup) {

300 const MCBinaryExpr &MBE = cast(AddrDelta);

301 Fixups.push_back(

304 std::get<0>(Fixup))));

305 Fixups.push_back(

308 std::get<1>(Fixup))));

309 };

310

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

313 AddFixups(0, {ELF::R_RISCV_SET6, ELF::R_RISCV_SUB6});

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

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

317 AddFixups(1, {ELF::R_RISCV_SET8, ELF::R_RISCV_SUB8});

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

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

321 AddFixups(1, {ELF::R_RISCV_SET16, ELF::R_RISCV_SUB16});

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

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

325 AddFixups(1, {ELF::R_RISCV_SET32, ELF::R_RISCV_SUB32});

326 } else {

328 }

329

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

331 return true;

332}

333

336 int64_t &Value) const {

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

343 }

345}

346

347

348

350 switch (Op) {

351 default:

352 return Op;

353 case RISCV::C_BEQZ:

354 return RISCV::BEQ;

355 case RISCV::C_BNEZ:

356 return RISCV::BNE;

357 case RISCV::C_J:

358 case RISCV::C_JAL:

359 return RISCV::JAL;

360 case RISCV::BEQ:

361 return RISCV::PseudoLongBEQ;

362 case RISCV::BNE:

363 return RISCV::PseudoLongBNE;

364 case RISCV::BLT:

365 return RISCV::PseudoLongBLT;

366 case RISCV::BGE:

367 return RISCV::PseudoLongBGE;

368 case RISCV::BLTU:

369 return RISCV::PseudoLongBLTU;

370 case RISCV::BGEU:

371 return RISCV::PseudoLongBGEU;

372 }

373}

374

378}

379

382

383

384

385

386

387

388 if (Count % 2) {

390 Count -= 1;

391 }

392

393 bool UseCompressedNop = STI->hasFeature(RISCV::FeatureStdExtC) ||

394 STI->hasFeature(RISCV::FeatureStdExtZca);

395

396 if (Count % 4 == 2) {

397 OS.write(UseCompressedNop ? "\x01\0" : "\0\0", 2);

398 Count -= 2;

399 }

400

401

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

403 OS.write("\x13\0\0\0", 4);

404

405 return true;

406}

407

410 switch (Fixup.getTargetKind()) {

411 default:

417 llvm_unreachable("Relocation should be unconditionally forced\n");

428 return Value & 0xfff;

430 if (!isInt<12>(Value)) {

432 "operand must be a constant 12-bit integer");

433 }

434 return Value & 0xfff;

438 return (((Value >> 5) & 0x7f) << 25) | ((Value & 0x1f) << 7);

442

443 return ((Value + 0x800) >> 12) & 0xfffff;

445 if (!isInt<21>(Value))

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

449

450 unsigned Sbit = (Value >> 20) & 0x1;

451 unsigned Hi8 = (Value >> 12) & 0xff;

452 unsigned Mid1 = (Value >> 11) & 0x1;

453 unsigned Lo10 = (Value >> 1) & 0x3ff;

454

455

456

457

458 Value = (Sbit << 19) | (Lo10 << 9) | (Mid1 << 8) | Hi8;

460 }

462 if (!isInt<13>(Value))

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

466

467

468 unsigned Sbit = (Value >> 12) & 0x1;

469 unsigned Hi1 = (Value >> 11) & 0x1;

470 unsigned Mid6 = (Value >> 5) & 0x3f;

471 unsigned Lo4 = (Value >> 1) & 0xf;

472

473

474

475

476 Value = (Sbit << 31) | (Mid6 << 25) | (Lo4 << 8) | (Hi1 << 7);

478 }

481

482

483

484 uint64_t UpperImm = (Value + 0x800ULL) & 0xfffff000ULL;

486 return UpperImm | ((LowerImm << 20) << 32);

487 }

489 if (!isInt<12>(Value))

491

492 unsigned Bit11 = (Value >> 11) & 0x1;

493 unsigned Bit4 = (Value >> 4) & 0x1;

494 unsigned Bit9_8 = (Value >> 8) & 0x3;

495 unsigned Bit10 = (Value >> 10) & 0x1;

496 unsigned Bit6 = (Value >> 6) & 0x1;

497 unsigned Bit7 = (Value >> 7) & 0x1;

498 unsigned Bit3_1 = (Value >> 1) & 0x7;

499 unsigned Bit5 = (Value >> 5) & 0x1;

500 Value = (Bit11 << 10) | (Bit4 << 9) | (Bit9_8 << 7) | (Bit10 << 6) |

501 (Bit6 << 5) | (Bit7 << 4) | (Bit3_1 << 1) | Bit5;

503 }

505 if (!isInt<9>(Value))

507

508 unsigned Bit8 = (Value >> 8) & 0x1;

509 unsigned Bit7_6 = (Value >> 6) & 0x3;

510 unsigned Bit5 = (Value >> 5) & 0x1;

511 unsigned Bit4_3 = (Value >> 3) & 0x3;

512 unsigned Bit2_1 = (Value >> 1) & 0x3;

513 Value = (Bit8 << 12) | (Bit4_3 << 10) | (Bit7_6 << 5) | (Bit2_1 << 3) |

514 (Bit5 << 2);

516 }

517

518 }

519}

520

527 const MCFixup *AUIPCFixup;

530 switch (Fixup.getTargetKind()) {

531 default:

535 AUIPCFixup = &Fixup;

536 AUIPCDF = DF;

537 AUIPCTarget = Target;

538 break;

541 AUIPCFixup = cast(Fixup.getValue())->getPCRelHiFixup(&AUIPCDF);

542 if (!AUIPCFixup) {

543 Asm.getContext().reportError(Fixup.getLoc(),

544 "could not find corresponding %pcrel_hi");

545 return true;

546 }

547

548

549

552 return true;

553 break;

554 }

555 }

556

558 return false;

559

561 const MCSymbolELF &SA = cast(A->getSymbol());

563 return false;

564

568 if (!IsResolved)

569 return false;

570

572 Value -= Asm.getFragmentOffset(*AUIPCDF) + AUIPCFixup->getOffset();

573

575 WasForced = true;

576 return false;

577 }

578

579 return true;

580}

581

586 uint64_t &FixedValue) const {

587 uint64_t FixedValueA, FixedValueB;

588 unsigned TA = 0, TB = 0;

589 switch (Fixup.getKind()) {

591 TA = ELF::R_RISCV_ADD8;

592 TB = ELF::R_RISCV_SUB8;

593 break;

595 TA = ELF::R_RISCV_ADD16;

596 TB = ELF::R_RISCV_SUB16;

597 break;

599 TA = ELF::R_RISCV_ADD32;

600 TB = ELF::R_RISCV_SUB32;

601 break;

603 TA = ELF::R_RISCV_ADD64;

604 TB = ELF::R_RISCV_SUB64;

605 break;

607 TA = ELF::R_RISCV_SET_ULEB128;

608 TB = ELF::R_RISCV_SUB_ULEB128;

609 break;

610 default:

612 }

616 Fixup.getOffset(), nullptr,

619 Fixup.getOffset(), nullptr,

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

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

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

624 FixedValue = FixedValueA - FixedValueB;

625 return true;

626}

627

631 bool IsResolved,

635 return;

636 MCContext &Ctx = Asm.getContext();

639 return;

640

642

643

645

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

648

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

650

651

652

653 for (unsigned i = 0; i != NumBytes; ++i) {

655 }

656}

657

658

659

660

661

664

666 if (!STI->hasFeature(RISCV::FeatureRelax))

667 return false;

668

669 bool UseCompressedNop = STI->hasFeature(RISCV::FeatureStdExtC) ||

670 STI->hasFeature(RISCV::FeatureStdExtZca);

671 unsigned MinNopLen = UseCompressedNop ? 2 : 4;

672

674 return false;

675 } else {

677 return true;

678 }

679}

680

681

682

683

684

685

688

690 if (!STI->hasFeature(RISCV::FeatureRelax))

691 return false;

692

693

694

695 unsigned Count;

697 return false;

698

699 MCContext &Ctx = Asm.getContext();

701

704

707

708 Asm.getWriter().recordRelocation(Asm, &AF, Fixup, NopBytes, FixedValue);

709

710 return true;

711}

712

713std::unique_ptr

716}

717

725}

unsigned const MachineRegisterInfo * MRI

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

This file implements a class to represent arbitrary precision integral constant values and operations...

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

PowerPC TLS Dynamic Call Fixup

static cl::opt< bool > RelaxBranches("riscv-asm-relax-branches", cl::init(true), cl::Hidden)

static cl::opt< bool > ULEB128Reloc("riscv-uleb128-reloc", cl::init(true), cl::Hidden, cl::desc("Emit R_RISCV_SET_ULEB128/E_RISCV_SUB_ULEB128 if appropriate"))

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

This class represents an Operation in the Expression.

Align getAlignment() 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)

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.

bool evaluateAsRelocatable(MCValue &Res, const MCAssembler *Asm, const MCFixup *Fixup) const

Try to evaluate the expression to a relocatable value, i.e.

Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...

const MCExpr * getValue() const

uint32_t getOffset() const

static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, SMLoc Loc=SMLoc())

MCSection * getParent() const

Instances of this class represent a single low-level machine instruction.

unsigned getOpcode() const

void addOperand(const MCOperand Op)

void setOpcode(unsigned Op)

const MCOperand & getOperand(unsigned i) const

const MCExpr & getValue() const

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

Generic base class for all target subtargets.

bool hasFeature(unsigned Feature) const

const Triple & getTargetTriple() const

unsigned getBinding() const

Represent a reference to a symbol from inside an expression.

bool isUndefined(bool SetUsed=true) const

isUndefined - Check if this symbol undefined (i.e., implicitly defined).

MCSection & getSection() const

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

This represents an "assembler immediate".

int64_t getConstant() const

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

const MCSymbolRefExpr * getSymB() const

const MCSymbolRefExpr * getSymA() const

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

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

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

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

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

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

void relaxInstruction(MCInst &Inst, const MCSubtargetInfo &STI) const override

Relax the instruction in the given fragment to the next wider instruction.

bool evaluateTargetFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCFragment *DF, const MCValue &Target, const MCSubtargetInfo *STI, uint64_t &Value, bool &WasForced) override

const MCFixupKindInfo & getFixupKindInfo(MCFixupKind Kind) const override

Get information on a fixup kind.

bool fixupNeedsRelaxationAdvanced(const MCAssembler &Asm, const MCFixup &Fixup, bool Resolved, uint64_t Value, const MCRelaxableFragment *DF, const bool WasForced) const override

Target specific predicate for whether a given fixup requires the associated instruction to be relaxed...

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.

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

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

bool mayNeedRelaxation(const MCInst &Inst, const MCSubtargetInfo &STI) const override

Check whether the given instruction may need relaxation.

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.

unsigned getRelaxedOpcode(unsigned Op) const

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

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

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

unsigned getNumFixupKinds() const override

Get the number of target specific fixup kinds.

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

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

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.

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.

bool uncompress(MCInst &OutInst, const MCInst &MI, const MCSubtargetInfo &STI)

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

@ fixup_riscv_tprel_lo12_s

@ fixup_riscv_tls_got_hi20

@ fixup_riscv_tls_gd_hi20

@ fixup_riscv_pcrel_lo12_i

@ fixup_riscv_pcrel_lo12_s

@ fixup_riscv_tprel_lo12_i

@ fixup_riscv_tlsdesc_load_lo12

@ fixup_riscv_tlsdesc_hi20

initializer< Ty > init(const Ty &Val)

This is an optimization pass for GlobalISel generic memory operations.

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

bool isUIntN(unsigned N, uint64_t x)

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

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.

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

uint64_t alignTo(uint64_t Size, Align A)

Returns a multiple of A needed to store Size bytes.

DWARFExpression::Operation Op

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.

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_IsTarget

Should this fixup be evaluated in a target dependent manner?

@ FKF_IsPCRel

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