77// ===----------------------------------------------------------------------===//
88
99#include " RISCVAsmBackend.h"
10+ #include " RISCVFixupKinds.h"
1011#include " RISCVMCExpr.h"
1112#include " llvm/ADT/APInt.h"
1213#include " llvm/MC/MCAsmInfo.h"
@@ -37,7 +38,7 @@ static cl::opt<bool> ULEB128Reloc(
3738RISCVAsmBackend::RISCVAsmBackend (const MCSubtargetInfo &STI, uint8_t OSABI,
3839 bool Is64Bit, const MCTargetOptions &Options)
3940 : MCAsmBackend(llvm::endianness::little, ELF::R_RISCV_RELAX), STI(STI),
40- OSABI(OSABI), Is64Bit(Is64Bit), TargetOptions(Options) {
41+ OSABI(OSABI), Is64Bit(Is64Bit), TargetOptions(Options), VendorSymbols() {
4142 RISCVFeatures::validate (STI.getTargetTriple (), STI.getFeatureBits ());
4243}
4344
@@ -84,10 +85,12 @@ MCFixupKindInfo RISCVAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
8485 {" fixup_riscv_call" , 0 , 64 , MCFixupKindInfo::FKF_IsPCRel},
8586 {" fixup_riscv_call_plt" , 0 , 64 , MCFixupKindInfo::FKF_IsPCRel},
8687
87- {" fixup_riscv_qc_e_branch" , 0 , 48 , MCFixupKindInfo::FKF_IsPCRel},
88- {" fixup_riscv_qc_e_32" , 16 , 32 , 0 },
89- {" fixup_riscv_qc_abs20_u" , 12 , 20 , 0 },
90- {" fixup_riscv_qc_e_jump_plt" , 0 , 48 , MCFixupKindInfo::FKF_IsPCRel},
88+ {" fixup_riscv_qc_e_branch" , 0 , 48 ,
89+ MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsTarget},
90+ {" fixup_riscv_qc_e_32" , 16 , 32 , MCFixupKindInfo::FKF_IsTarget},
91+ {" fixup_riscv_qc_abs20_u" , 12 , 20 , MCFixupKindInfo::FKF_IsTarget},
92+ {" fixup_riscv_qc_e_jump_plt" , 0 , 48 ,
93+ MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsTarget},
9194 };
9295 static_assert ((std::size (Infos)) == RISCV::NumTargetFixupKinds,
9396 " Not all fixup kinds added to Infos array" );
@@ -571,37 +574,10 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
571574 }
572575}
573576
574- bool RISCVAsmBackend::evaluateTargetFixup (
575- const MCAssembler &Asm, const MCFixup &Fixup, const MCFragment *DF,
576- const MCValue &Target, const MCSubtargetInfo *STI, uint64_t &Value) {
577- const MCFixup *AUIPCFixup;
578- const MCFragment *AUIPCDF;
579- MCValue AUIPCTarget;
580- switch (Fixup.getTargetKind ()) {
581- default :
582- llvm_unreachable (" Unexpected fixup kind!" );
583- case RISCV::fixup_riscv_pcrel_hi20:
584- AUIPCFixup = &Fixup;
585- AUIPCDF = DF;
586- AUIPCTarget = Target;
587- break ;
588- case RISCV::fixup_riscv_pcrel_lo12_i:
589- case RISCV::fixup_riscv_pcrel_lo12_s: {
590- AUIPCFixup = cast<RISCVMCExpr>(Fixup.getValue ())->getPCRelHiFixup (&AUIPCDF);
591- if (!AUIPCFixup) {
592- Asm.getContext ().reportError (Fixup.getLoc (),
593- " could not find corresponding %pcrel_hi" );
594- return true ;
595- }
596-
597- // MCAssembler::evaluateFixup will emit an error for this case when it sees
598- // the %pcrel_hi, so don't duplicate it when also seeing the %pcrel_lo.
599- const MCExpr *AUIPCExpr = AUIPCFixup->getValue ();
600- if (!AUIPCExpr->evaluateAsRelocatable (AUIPCTarget, &Asm))
601- return true ;
602- break ;
603- }
604- }
577+ static bool evaluateAUIPCFixup (const MCAssembler &Asm,
578+ const MCFixup *AUIPCFixup,
579+ const MCFragment *AUIPCDF, MCValue AUIPCTarget,
580+ uint64_t &Value) {
605581
606582 if (!AUIPCTarget.getAddSym ())
607583 return false ;
@@ -622,6 +598,129 @@ bool RISCVAsmBackend::evaluateTargetFixup(
622598 return AUIPCFixup->getTargetKind () == RISCV::fixup_riscv_pcrel_hi20;
623599}
624600
601+ StringRef
602+ RISCVAsmBackend::getVendorSymbolNameForRelocation (unsigned FixupKind) const {
603+ switch (FixupKind) {
604+ case RISCV::fixup_riscv_qc_e_branch:
605+ case RISCV::fixup_riscv_qc_abs20_u:
606+ case RISCV::fixup_riscv_qc_e_32:
607+ case RISCV::fixup_riscv_qc_e_jump_plt:
608+ return " QUALCOMM" ;
609+ }
610+
611+ return " " ;
612+ }
613+
614+ bool RISCVAsmBackend::evaluateVendorFixup (const MCAssembler &Asm,
615+ const MCFixup &Fixup,
616+ const MCFragment *DF,
617+ const MCValue &Target,
618+ const MCSubtargetInfo *STI,
619+ uint64_t &Value, bool RecordReloc) {
620+ // This is a copy of the target-independent branch of
621+ // MCAssembler::evaluateFixup
622+ bool IsResolved = false ;
623+ const MCSymbol *Add = Target.getAddSym ();
624+ const MCSymbol *Sub = Target.getSubSym ();
625+ Value = Target.getConstant ();
626+ if (Add && Add->isDefined ())
627+ Value += Asm.getSymbolOffset (*Add);
628+ if (Sub && Sub->isDefined ())
629+ Value -= Asm.getSymbolOffset (*Sub);
630+
631+ unsigned FixupFlags = getFixupKindInfo (Fixup.getKind ()).Flags ;
632+ if (FixupFlags & MCFixupKindInfo::FKF_IsPCRel) {
633+ Value -= Asm.getFragmentOffset (*DF) + Fixup.getOffset ();
634+
635+ if (Add && !Sub && !Add->isUndefined () && !Add->isAbsolute ()) {
636+ IsResolved = Asm.getWriter ().isSymbolRefDifferenceFullyResolvedImpl (
637+ Asm, *Add, *DF, false , true );
638+ }
639+ } else {
640+ IsResolved = Target.isAbsolute ();
641+ }
642+ // End copy of MCAssembler::evaluateFixup
643+
644+ // If we failed to resolve, or we need to force relocations (relaxations), then
645+ // record a vendor relocation too.
646+ if ((!IsResolved || shouldForceRelocation (Asm, Fixup, Target, STI)) &&
647+ RecordReloc) {
648+ // Here are the additions to emit a vendor relocation for fixups that need
649+ // them.
650+ MCContext &Ctx = Asm.getContext ();
651+
652+ StringRef VendorIdentifier =
653+ getVendorSymbolNameForRelocation (Fixup.getTargetKind ());
654+
655+ auto It = VendorSymbols.find (VendorIdentifier);
656+ if (It == VendorSymbols.end ()) {
657+ auto *VendorSymbol =
658+ cast<MCSymbolELF>(Ctx.createLocalSymbol (VendorIdentifier));
659+
660+ // Vendor Symbols are Absolute, Local, NOTYPE.
661+ VendorSymbol->setType (ELF::STT_NOTYPE);
662+ VendorSymbol->setBinding (ELF::STB_LOCAL);
663+ VendorSymbol->setVariableValue (MCConstantExpr::create (0 , Ctx));
664+ const_cast <MCAssembler &>(Asm).registerSymbol (*VendorSymbol);
665+
666+ It = VendorSymbols.try_emplace (VendorIdentifier, VendorSymbol).first ;
667+ }
668+
669+ MCSymbolELF *VendorSymbol = It->getValue ();
670+ const MCExpr *VendorExpr = MCSymbolRefExpr::create (VendorSymbol, Ctx);
671+ MCFixup VendorFixup =
672+ MCFixup::create (Fixup.getOffset (), VendorExpr,
673+ FirstLiteralRelocationKind + ELF::R_RISCV_VENDOR);
674+ // Explicitly create MCValue so that the absolute symbol is not evaluated to
675+ // a constant.
676+ MCValue VendorTarget = MCValue::get (VendorSymbol);
677+ uint64_t VendorValue;
678+ Asm.getWriter ().recordRelocation (const_cast <MCAssembler &>(Asm), DF,
679+ VendorFixup, VendorTarget, VendorValue);
680+ }
681+
682+ return IsResolved;
683+ }
684+
685+ bool RISCVAsmBackend::evaluateTargetFixup (const MCAssembler &Asm,
686+ const MCFixup &Fixup,
687+ const MCFragment *DF,
688+ const MCValue &Target,
689+ const MCSubtargetInfo *STI,
690+ uint64_t &Value, bool RecordReloc) {
691+ switch (Fixup.getTargetKind ()) {
692+ case RISCV::fixup_riscv_pcrel_hi20:
693+ return evaluateAUIPCFixup (Asm, &Fixup, DF, Target, Value);
694+ case RISCV::fixup_riscv_pcrel_lo12_i:
695+ case RISCV::fixup_riscv_pcrel_lo12_s: {
696+ const MCFragment *AUIPCDF;
697+ const MCFixup *AUIPCFixup =
698+ cast<RISCVMCExpr>(Fixup.getValue ())->getPCRelHiFixup (&AUIPCDF);
699+ if (!AUIPCFixup) {
700+ Asm.getContext ().reportError (Fixup.getLoc (),
701+ " could not find corresponding %pcrel_hi" );
702+ return true ;
703+ }
704+
705+ // MCAssembler::evaluateFixup will emit an error for this case when it sees
706+ // the %pcrel_hi, so don't duplicate it when also seeing the %pcrel_lo.
707+ const MCExpr *AUIPCExpr = AUIPCFixup->getValue ();
708+ MCValue AUIPCTarget;
709+ if (!AUIPCExpr->evaluateAsRelocatable (AUIPCTarget, &Asm))
710+ return true ;
711+
712+ return evaluateAUIPCFixup (Asm, AUIPCFixup, AUIPCDF, AUIPCTarget, Value);
713+ }
714+ case RISCV::fixup_riscv_qc_e_branch:
715+ case RISCV::fixup_riscv_qc_abs20_u:
716+ case RISCV::fixup_riscv_qc_e_32:
717+ case RISCV::fixup_riscv_qc_e_jump_plt:
718+ return evaluateVendorFixup (Asm, Fixup, DF, Target, STI, Value, RecordReloc);
719+ }
720+
721+ llvm_unreachable (" Unexpected target fixup kind!" );
722+ }
723+
625724bool RISCVAsmBackend::handleAddSubRelocations (const MCAssembler &Asm,
626725 const MCFragment &F,
627726 const MCFixup &Fixup,
0 commit comments