mirror of
https://github.com/intel/llvm.git
synced 2026-01-26 12:26:52 +08:00
[AArch64] Transition from MCSymbolRefExpr::VariantKind constants
Shift ELF `@plt` and `@gotpcrel` references in data directives, as well as Mach-O `@specifier` notations, to use `AArch64MCExpr::Specifier` constants. This is a follow-up to #132595. COFF-specific specifiers are not moved yet. In addition, partition @-specifiers into COFF, ELF, and Mach-O, so that mix-and-match is rejected at parse time. ELF and Mach-O specifiers are distinct, with `None` being the only shared value. For Mach-O-specific specifiers, we adopt the `M_xxx` naming convention. Pull Request: https://github.com/llvm/llvm-project/pull/133214
This commit is contained in:
@@ -37,7 +37,7 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
|
||||
SmallPtrSet<GlobalObject *, 2> Used;
|
||||
|
||||
protected:
|
||||
uint8_t PLTRelativeSpecifier = 0;
|
||||
uint16_t PLTRelativeSpecifier = 0;
|
||||
|
||||
public:
|
||||
~TargetLoweringObjectFileELF() override = default;
|
||||
|
||||
@@ -65,10 +65,13 @@ public:
|
||||
/// quote, e.g., `'A`.
|
||||
};
|
||||
|
||||
struct VariantKindDesc {
|
||||
// This describes a @ style relocation specifier (expr@specifier) supported by
|
||||
// AsmParser::parsePrimaryExpr.
|
||||
struct AtSpecifier {
|
||||
uint32_t Kind;
|
||||
StringRef Name;
|
||||
};
|
||||
using VariantKindDesc = AtSpecifier;
|
||||
|
||||
protected:
|
||||
//===------------------------------------------------------------------===//
|
||||
|
||||
@@ -198,14 +198,6 @@ public:
|
||||
|
||||
VK_GOT,
|
||||
VK_GOTPCREL,
|
||||
VK_PLT,
|
||||
VK_TLVP, // Mach-O thread local variable relocations
|
||||
VK_TLVPPAGE,
|
||||
VK_TLVPPAGEOFF,
|
||||
VK_PAGE,
|
||||
VK_PAGEOFF,
|
||||
VK_GOTPAGE,
|
||||
VK_GOTPAGEOFF,
|
||||
VK_SECREL,
|
||||
VK_WEAKREF, // The link between the symbols in .weakref foo, bar
|
||||
|
||||
|
||||
@@ -151,31 +151,32 @@ MCOperand AArch64MCInstLower::lowerSymbolOperandMachO(const MachineOperand &MO,
|
||||
MCSymbol *Sym) const {
|
||||
// FIXME: We would like an efficient form for this, so we don't have to do a
|
||||
// lot of extra uniquing.
|
||||
MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;
|
||||
auto Spec = AArch64MCExpr::None;
|
||||
if ((MO.getTargetFlags() & AArch64II::MO_GOT) != 0) {
|
||||
if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
|
||||
RefKind = MCSymbolRefExpr::VK_GOTPAGE;
|
||||
Spec = AArch64MCExpr::M_GOTPAGE;
|
||||
else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
|
||||
AArch64II::MO_PAGEOFF)
|
||||
RefKind = MCSymbolRefExpr::VK_GOTPAGEOFF;
|
||||
Spec = AArch64MCExpr::M_GOTPAGEOFF;
|
||||
else
|
||||
llvm_unreachable("Unexpected target flags with MO_GOT on GV operand");
|
||||
} else if ((MO.getTargetFlags() & AArch64II::MO_TLS) != 0) {
|
||||
if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
|
||||
RefKind = MCSymbolRefExpr::VK_TLVPPAGE;
|
||||
Spec = AArch64MCExpr::M_TLVPPAGE;
|
||||
else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
|
||||
AArch64II::MO_PAGEOFF)
|
||||
RefKind = MCSymbolRefExpr::VK_TLVPPAGEOFF;
|
||||
Spec = AArch64MCExpr::M_TLVPPAGEOFF;
|
||||
else
|
||||
llvm_unreachable("Unexpected target flags with MO_TLS on GV operand");
|
||||
} else {
|
||||
if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
|
||||
RefKind = MCSymbolRefExpr::VK_PAGE;
|
||||
Spec = AArch64MCExpr::M_PAGE;
|
||||
else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
|
||||
AArch64II::MO_PAGEOFF)
|
||||
RefKind = MCSymbolRefExpr::VK_PAGEOFF;
|
||||
Spec = AArch64MCExpr::M_PAGEOFF;
|
||||
}
|
||||
const MCExpr *Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx);
|
||||
// TODO: Migrate to AArch64MCExpr::create like ELF.
|
||||
const MCExpr *Expr = MCSymbolRefExpr::create(Sym, Spec, Ctx);
|
||||
if (!MO.isJTI() && MO.getOffset())
|
||||
Expr = MCBinaryExpr::createAdd(
|
||||
Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
|
||||
|
||||
@@ -25,6 +25,9 @@ using namespace dwarf;
|
||||
void AArch64_ELFTargetObjectFile::Initialize(MCContext &Ctx,
|
||||
const TargetMachine &TM) {
|
||||
TargetLoweringObjectFileELF::Initialize(Ctx, TM);
|
||||
PLTRelativeSpecifier = AArch64MCExpr::VK_PLT;
|
||||
SupportIndirectSymViaGOTPCRel = true;
|
||||
|
||||
// AARCH64 ELF ABI does not define static relocation type for TLS offset
|
||||
// within a module. Do not generate AT_location for TLS variables.
|
||||
SupportDebugThreadLocalLocation = false;
|
||||
@@ -58,7 +61,7 @@ const MCExpr *AArch64_ELFTargetObjectFile::getIndirectSymViaGOTPCRel(
|
||||
int64_t Offset, MachineModuleInfo *MMI, MCStreamer &Streamer) const {
|
||||
int64_t FinalOffset = Offset + MV.getConstant();
|
||||
const MCExpr *Res =
|
||||
MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_GOTPCREL, getContext());
|
||||
MCSymbolRefExpr::create(Sym, AArch64MCExpr::VK_GOTPCREL, getContext());
|
||||
const MCExpr *Off = MCConstantExpr::create(FinalOffset, getContext());
|
||||
return MCBinaryExpr::createAdd(Res, Off, getContext());
|
||||
}
|
||||
@@ -77,7 +80,7 @@ const MCExpr *AArch64_MachoTargetObjectFile::getTTypeGlobalReference(
|
||||
if (Encoding & (DW_EH_PE_indirect | DW_EH_PE_pcrel)) {
|
||||
const MCSymbol *Sym = TM.getSymbol(GV);
|
||||
const MCExpr *Res =
|
||||
MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_GOT, getContext());
|
||||
MCSymbolRefExpr::create(Sym, AArch64MCExpr::M_GOT, getContext());
|
||||
MCSymbol *PCSym = getContext().createTempSymbol();
|
||||
Streamer.emitLabel(PCSym);
|
||||
const MCExpr *PC = MCSymbolRefExpr::create(PCSym, getContext());
|
||||
@@ -102,7 +105,7 @@ const MCExpr *AArch64_MachoTargetObjectFile::getIndirectSymViaGOTPCRel(
|
||||
// On ARM64 Darwin, we can reference symbols with foo@GOT-., which
|
||||
// is an indirect pc-relative reference.
|
||||
const MCExpr *Res =
|
||||
MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_GOT, getContext());
|
||||
MCSymbolRefExpr::create(Sym, AArch64MCExpr::M_GOT, getContext());
|
||||
MCSymbol *PCSym = getContext().createTempSymbol();
|
||||
Streamer.emitLabel(PCSym);
|
||||
const MCExpr *PC = MCSymbolRefExpr::create(PCSym, getContext());
|
||||
|
||||
@@ -20,11 +20,6 @@ class AArch64_ELFTargetObjectFile : public TargetLoweringObjectFileELF {
|
||||
void Initialize(MCContext &Ctx, const TargetMachine &TM) override;
|
||||
|
||||
public:
|
||||
AArch64_ELFTargetObjectFile() {
|
||||
PLTRelativeSpecifier = MCSymbolRefExpr::VK_PLT;
|
||||
SupportIndirectSymViaGOTPCRel = true;
|
||||
}
|
||||
|
||||
const MCExpr *getIndirectSymViaGOTPCRel(const GlobalValue *GV,
|
||||
const MCSymbol *Sym,
|
||||
const MCValue &MV, int64_t Offset,
|
||||
|
||||
@@ -339,7 +339,7 @@ public:
|
||||
|
||||
static bool classifySymbolRef(const MCExpr *Expr,
|
||||
AArch64MCExpr::Specifier &ELFSpec,
|
||||
MCSymbolRefExpr::VariantKind &DarwinRefKind,
|
||||
AArch64MCExpr::Specifier &DarwinSpec,
|
||||
int64_t &Addend);
|
||||
};
|
||||
|
||||
@@ -889,16 +889,16 @@ public:
|
||||
|
||||
bool isSymbolicUImm12Offset(const MCExpr *Expr) const {
|
||||
AArch64MCExpr::Specifier ELFSpec;
|
||||
MCSymbolRefExpr::VariantKind DarwinRefKind;
|
||||
AArch64MCExpr::Specifier DarwinSpec;
|
||||
int64_t Addend;
|
||||
if (!AArch64AsmParser::classifySymbolRef(Expr, ELFSpec, DarwinRefKind,
|
||||
if (!AArch64AsmParser::classifySymbolRef(Expr, ELFSpec, DarwinSpec,
|
||||
Addend)) {
|
||||
// If we don't understand the expression, assume the best and
|
||||
// let the fixup and relocation code deal with it.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
|
||||
if (DarwinSpec == AArch64MCExpr::M_PAGEOFF ||
|
||||
llvm::is_contained(
|
||||
{AArch64MCExpr::VK_LO12, AArch64MCExpr::VK_GOT_LO12,
|
||||
AArch64MCExpr::VK_GOT_AUTH_LO12, AArch64MCExpr::VK_DTPREL_LO12,
|
||||
@@ -912,8 +912,8 @@ public:
|
||||
// size when converted, so there is no "out of range" condition when using
|
||||
// @pageoff.
|
||||
return true;
|
||||
} else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
|
||||
DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
|
||||
} else if (DarwinSpec == AArch64MCExpr::M_GOTPAGEOFF ||
|
||||
DarwinSpec == AArch64MCExpr::M_TLVPPAGEOFF) {
|
||||
// @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
|
||||
return Addend == 0;
|
||||
}
|
||||
@@ -1006,13 +1006,13 @@ public:
|
||||
}
|
||||
|
||||
AArch64MCExpr::Specifier ELFSpec;
|
||||
MCSymbolRefExpr::VariantKind DarwinRefKind;
|
||||
AArch64MCExpr::Specifier DarwinSpec;
|
||||
int64_t Addend;
|
||||
if (AArch64AsmParser::classifySymbolRef(Expr, ELFSpec, DarwinRefKind,
|
||||
if (AArch64AsmParser::classifySymbolRef(Expr, ELFSpec, DarwinSpec,
|
||||
Addend)) {
|
||||
return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
|
||||
DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF ||
|
||||
(DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0) ||
|
||||
return DarwinSpec == AArch64MCExpr::M_PAGEOFF ||
|
||||
DarwinSpec == AArch64MCExpr::M_TLVPPAGEOFF ||
|
||||
(DarwinSpec == AArch64MCExpr::M_GOTPAGEOFF && Addend == 0) ||
|
||||
llvm::is_contained(
|
||||
{AArch64MCExpr::VK_LO12, AArch64MCExpr::VK_GOT_AUTH_LO12,
|
||||
AArch64MCExpr::VK_DTPREL_HI12, AArch64MCExpr::VK_DTPREL_LO12,
|
||||
@@ -1120,13 +1120,13 @@ public:
|
||||
return false;
|
||||
|
||||
AArch64MCExpr::Specifier ELFSpec;
|
||||
MCSymbolRefExpr::VariantKind DarwinRefKind;
|
||||
AArch64MCExpr::Specifier DarwinSpec;
|
||||
int64_t Addend;
|
||||
if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFSpec, DarwinRefKind,
|
||||
if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFSpec, DarwinSpec,
|
||||
Addend)) {
|
||||
return false;
|
||||
}
|
||||
if (DarwinRefKind != MCSymbolRefExpr::VK_None)
|
||||
if (DarwinSpec != AArch64MCExpr::None)
|
||||
return false;
|
||||
|
||||
return llvm::is_contained(AllowedModifiers, ELFSpec);
|
||||
@@ -3297,22 +3297,22 @@ ParseStatus AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
|
||||
return ParseStatus::Failure;
|
||||
|
||||
AArch64MCExpr::Specifier ELFSpec;
|
||||
MCSymbolRefExpr::VariantKind DarwinRefKind;
|
||||
AArch64MCExpr::Specifier DarwinSpec;
|
||||
int64_t Addend;
|
||||
if (classifySymbolRef(Expr, ELFSpec, DarwinRefKind, Addend)) {
|
||||
if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
|
||||
if (classifySymbolRef(Expr, ELFSpec, DarwinSpec, Addend)) {
|
||||
if (DarwinSpec == AArch64MCExpr::None &&
|
||||
ELFSpec == AArch64MCExpr::VK_INVALID) {
|
||||
// No modifier was specified at all; this is the syntax for an ELF basic
|
||||
// ADRP relocation (unfortunately).
|
||||
Expr =
|
||||
AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
|
||||
} else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
|
||||
DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
|
||||
} else if ((DarwinSpec == AArch64MCExpr::M_GOTPAGE ||
|
||||
DarwinSpec == AArch64MCExpr::M_TLVPPAGE) &&
|
||||
Addend != 0) {
|
||||
return Error(S, "gotpage label reference not allowed an addend");
|
||||
} else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
|
||||
DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
|
||||
DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
|
||||
} else if (DarwinSpec != AArch64MCExpr::M_PAGE &&
|
||||
DarwinSpec != AArch64MCExpr::M_GOTPAGE &&
|
||||
DarwinSpec != AArch64MCExpr::M_TLVPPAGE &&
|
||||
ELFSpec != AArch64MCExpr::VK_ABS_PAGE_NC &&
|
||||
ELFSpec != AArch64MCExpr::VK_GOT_PAGE &&
|
||||
ELFSpec != AArch64MCExpr::VK_GOT_AUTH_PAGE &&
|
||||
@@ -3351,10 +3351,10 @@ ParseStatus AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
|
||||
return ParseStatus::Failure;
|
||||
|
||||
AArch64MCExpr::Specifier ELFSpec;
|
||||
MCSymbolRefExpr::VariantKind DarwinRefKind;
|
||||
AArch64MCExpr::Specifier DarwinSpec;
|
||||
int64_t Addend;
|
||||
if (classifySymbolRef(Expr, ELFSpec, DarwinRefKind, Addend)) {
|
||||
if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
|
||||
if (classifySymbolRef(Expr, ELFSpec, DarwinSpec, Addend)) {
|
||||
if (DarwinSpec == AArch64MCExpr::None &&
|
||||
ELFSpec == AArch64MCExpr::VK_INVALID) {
|
||||
// No modifier was specified at all; this is the syntax for an ELF basic
|
||||
// ADR relocation (unfortunately).
|
||||
@@ -5817,13 +5817,13 @@ bool AArch64AsmParser::validateInstruction(MCInst &Inst, SMLoc &IDLoc,
|
||||
if (Inst.getOperand(2).isExpr()) {
|
||||
const MCExpr *Expr = Inst.getOperand(2).getExpr();
|
||||
AArch64MCExpr::Specifier ELFSpec;
|
||||
MCSymbolRefExpr::VariantKind DarwinRefKind;
|
||||
AArch64MCExpr::Specifier DarwinSpec;
|
||||
int64_t Addend;
|
||||
if (classifySymbolRef(Expr, ELFSpec, DarwinRefKind, Addend)) {
|
||||
if (classifySymbolRef(Expr, ELFSpec, DarwinSpec, Addend)) {
|
||||
|
||||
// Only allow these with ADDXri.
|
||||
if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
|
||||
DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
|
||||
if ((DarwinSpec == AArch64MCExpr::M_PAGEOFF ||
|
||||
DarwinSpec == AArch64MCExpr::M_TLVPPAGEOFF) &&
|
||||
Inst.getOpcode() == AArch64::ADDXri)
|
||||
return false;
|
||||
|
||||
@@ -8192,11 +8192,12 @@ bool AArch64AsmParser::parseAuthExpr(const MCExpr *&Res, SMLoc &EndLoc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AArch64AsmParser::classifySymbolRef(
|
||||
const MCExpr *Expr, AArch64MCExpr::Specifier &ELFSpec,
|
||||
MCSymbolRefExpr::VariantKind &DarwinRefKind, int64_t &Addend) {
|
||||
bool AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
|
||||
AArch64MCExpr::Specifier &ELFSpec,
|
||||
AArch64MCExpr::Specifier &DarwinSpec,
|
||||
int64_t &Addend) {
|
||||
ELFSpec = AArch64MCExpr::VK_INVALID;
|
||||
DarwinRefKind = MCSymbolRefExpr::VK_None;
|
||||
DarwinSpec = AArch64MCExpr::None;
|
||||
Addend = 0;
|
||||
|
||||
if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
|
||||
@@ -8207,7 +8208,7 @@ bool AArch64AsmParser::classifySymbolRef(
|
||||
const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
|
||||
if (SE) {
|
||||
// It's a simple symbol reference with no addend.
|
||||
DarwinRefKind = SE->getKind();
|
||||
DarwinSpec = AArch64MCExpr::Specifier(SE->getKind());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -8223,13 +8224,13 @@ bool AArch64AsmParser::classifySymbolRef(
|
||||
return false;
|
||||
|
||||
if (Res.getSymA())
|
||||
DarwinRefKind = Res.getSymA()->getKind();
|
||||
DarwinSpec = AArch64MCExpr::Specifier(Res.getSymA()->getKind());
|
||||
Addend = Res.getConstant();
|
||||
|
||||
// It's some symbol reference + a constant addend, but really
|
||||
// shouldn't use both Darwin and ELF syntax.
|
||||
return ELFSpec == AArch64MCExpr::VK_INVALID ||
|
||||
DarwinRefKind == MCSymbolRefExpr::VK_None;
|
||||
DarwinSpec == AArch64MCExpr::None;
|
||||
}
|
||||
|
||||
/// Force static initialization.
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "AArch64ExternalSymbolizer.h"
|
||||
#include "MCTargetDesc/AArch64MCExpr.h"
|
||||
#include "Utils/AArch64BaseInfo.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
@@ -19,23 +20,23 @@ using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "aarch64-disassembler"
|
||||
|
||||
static MCSymbolRefExpr::VariantKind
|
||||
getVariant(uint64_t LLVMDisassembler_VariantKind) {
|
||||
static AArch64MCExpr::Specifier
|
||||
getMachOSpecifier(uint64_t LLVMDisassembler_VariantKind) {
|
||||
switch (LLVMDisassembler_VariantKind) {
|
||||
case LLVMDisassembler_VariantKind_None:
|
||||
return MCSymbolRefExpr::VK_None;
|
||||
return AArch64MCExpr::None;
|
||||
case LLVMDisassembler_VariantKind_ARM64_PAGE:
|
||||
return MCSymbolRefExpr::VK_PAGE;
|
||||
return AArch64MCExpr::M_PAGE;
|
||||
case LLVMDisassembler_VariantKind_ARM64_PAGEOFF:
|
||||
return MCSymbolRefExpr::VK_PAGEOFF;
|
||||
return AArch64MCExpr::M_PAGEOFF;
|
||||
case LLVMDisassembler_VariantKind_ARM64_GOTPAGE:
|
||||
return MCSymbolRefExpr::VK_GOTPAGE;
|
||||
return AArch64MCExpr::M_GOTPAGE;
|
||||
case LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF:
|
||||
return MCSymbolRefExpr::VK_GOTPAGEOFF;
|
||||
return AArch64MCExpr::M_GOTPAGEOFF;
|
||||
case LLVMDisassembler_VariantKind_ARM64_TLVP:
|
||||
return MCSymbolRefExpr::VK_TLVPPAGE;
|
||||
return AArch64MCExpr::M_TLVPPAGE;
|
||||
case LLVMDisassembler_VariantKind_ARM64_TLVOFF:
|
||||
return MCSymbolRefExpr::VK_TLVPPAGEOFF;
|
||||
return AArch64MCExpr::M_TLVPPAGEOFF;
|
||||
default:
|
||||
llvm_unreachable("bad LLVMDisassembler_VariantKind");
|
||||
}
|
||||
@@ -170,9 +171,9 @@ bool AArch64ExternalSymbolizer::tryAddingSymbolicOperand(
|
||||
if (SymbolicOp.AddSymbol.Name) {
|
||||
StringRef Name(SymbolicOp.AddSymbol.Name);
|
||||
MCSymbol *Sym = Ctx.getOrCreateSymbol(Name);
|
||||
MCSymbolRefExpr::VariantKind Variant = getVariant(SymbolicOp.VariantKind);
|
||||
if (Variant != MCSymbolRefExpr::VK_None)
|
||||
Add = MCSymbolRefExpr::create(Sym, Variant, Ctx);
|
||||
auto Spec = getMachOSpecifier(SymbolicOp.VariantKind);
|
||||
if (Spec != AArch64MCExpr::None)
|
||||
Add = MCSymbolRefExpr::create(Sym, Spec, Ctx);
|
||||
else
|
||||
Add = MCSymbolRefExpr::create(Sym, Ctx);
|
||||
} else {
|
||||
|
||||
@@ -117,13 +117,9 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
|
||||
bool IsNC = AArch64MCExpr::isNotChecked(RefKind);
|
||||
|
||||
assert((!Target.getSymA() ||
|
||||
Target.getSymA()->getKind() == MCSymbolRefExpr::VK_None ||
|
||||
Target.getSymA()->getKind() == MCSymbolRefExpr::VK_PLT ||
|
||||
Target.getSymA()->getKind() == MCSymbolRefExpr::VK_GOTPCREL) &&
|
||||
"Should only be expression-level modifiers here");
|
||||
|
||||
assert((!Target.getSymB() ||
|
||||
Target.getSymB()->getKind() == MCSymbolRefExpr::VK_None) &&
|
||||
getSpecifier(Target.getSymA()) == AArch64MCExpr::None ||
|
||||
getSpecifier(Target.getSymA()) == AArch64MCExpr::VK_PLT ||
|
||||
getSpecifier(Target.getSymA()) == AArch64MCExpr::VK_GOTPCREL) &&
|
||||
"Should only be expression-level modifiers here");
|
||||
|
||||
switch (SymLoc) {
|
||||
@@ -147,7 +143,8 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
|
||||
case FK_Data_2:
|
||||
return R_CLS(PREL16);
|
||||
case FK_Data_4: {
|
||||
return Target.getAccessVariant() == MCSymbolRefExpr::VK_PLT
|
||||
return AArch64MCExpr::Specifier(Target.getAccessVariant()) ==
|
||||
AArch64MCExpr::VK_PLT
|
||||
? R_CLS(PLT32)
|
||||
: R_CLS(PREL32);
|
||||
}
|
||||
@@ -258,8 +255,8 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
|
||||
case FK_Data_2:
|
||||
return R_CLS(ABS16);
|
||||
case FK_Data_4:
|
||||
return (!IsILP32 &&
|
||||
Target.getAccessVariant() == MCSymbolRefExpr::VK_GOTPCREL)
|
||||
return (!IsILP32 && AArch64MCExpr::Specifier(Target.getAccessVariant()) ==
|
||||
AArch64MCExpr::VK_GOTPCREL)
|
||||
? ELF::R_AARCH64_GOTPCREL32
|
||||
: R_CLS(ABS32);
|
||||
case FK_Data_8: {
|
||||
@@ -554,8 +551,8 @@ bool AArch64ELFObjectWriter::needsRelocateWithSymbol(const MCValue &Val,
|
||||
|
||||
if ((Val.getRefKind() & AArch64MCExpr::VK_GOT) == AArch64MCExpr::VK_GOT)
|
||||
return true;
|
||||
return is_contained({MCSymbolRefExpr::VK_GOTPCREL, MCSymbolRefExpr::VK_PLT},
|
||||
Val.getAccessVariant());
|
||||
return is_contained({AArch64MCExpr::VK_GOTPCREL, AArch64MCExpr::VK_PLT},
|
||||
AArch64MCExpr::Specifier(Val.getAccessVariant()));
|
||||
}
|
||||
|
||||
std::unique_ptr<MCObjectTargetWriter>
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "AArch64MCAsmInfo.h"
|
||||
#include "MCTargetDesc/AArch64MCExpr.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
@@ -30,19 +31,27 @@ static cl::opt<AsmWriterVariantTy> AsmWriterVariant(
|
||||
cl::values(clEnumValN(Generic, "generic", "Emit generic NEON assembly"),
|
||||
clEnumValN(Apple, "apple", "Emit Apple-style NEON assembly")));
|
||||
|
||||
const MCAsmInfo::VariantKindDesc variantKindDescs[] = {
|
||||
const MCAsmInfo::AtSpecifier COFFAtSpecifiers[] = {
|
||||
{MCSymbolRefExpr::VK_COFF_IMGREL32, "IMGREL"},
|
||||
{MCSymbolRefExpr::VK_GOT, "GOT"},
|
||||
{MCSymbolRefExpr::VK_GOTPAGE, "GOTPAGE"},
|
||||
{MCSymbolRefExpr::VK_GOTPAGEOFF, "GOTPAGEOFF"},
|
||||
{MCSymbolRefExpr::VK_GOTPCREL, "GOTPCREL"},
|
||||
{MCSymbolRefExpr::VK_PAGE, "PAGE"},
|
||||
{MCSymbolRefExpr::VK_PAGEOFF, "PAGEOFF"},
|
||||
{MCSymbolRefExpr::VK_PLT, "PLT"},
|
||||
{MCSymbolRefExpr::VK_TLVP, "TLVP"},
|
||||
{MCSymbolRefExpr::VK_TLVPPAGE, "TLVPPAGE"},
|
||||
{MCSymbolRefExpr::VK_TLVPPAGEOFF, "TLVPPAGEOFF"},
|
||||
{MCSymbolRefExpr::VK_WEAKREF, "WEAKREF"},
|
||||
{AArch64MCExpr::M_PAGEOFF, "PAGEOFF"},
|
||||
};
|
||||
|
||||
const MCAsmInfo::AtSpecifier ELFAtSpecifiers[] = {
|
||||
{AArch64MCExpr::VK_GOT, "GOT"},
|
||||
{AArch64MCExpr::VK_GOTPCREL, "GOTPCREL"},
|
||||
{AArch64MCExpr::VK_PLT, "PLT"},
|
||||
};
|
||||
|
||||
const MCAsmInfo::AtSpecifier MachOAtSpecifiers[] = {
|
||||
{AArch64MCExpr::M_GOT, "GOT"},
|
||||
{AArch64MCExpr::M_GOTPAGE, "GOTPAGE"},
|
||||
{AArch64MCExpr::M_GOTPAGEOFF, "GOTPAGEOFF"},
|
||||
{AArch64MCExpr::M_PAGE, "PAGE"},
|
||||
{AArch64MCExpr::M_PAGEOFF, "PAGEOFF"},
|
||||
{AArch64MCExpr::M_TLVP, "TLVP"},
|
||||
{AArch64MCExpr::M_TLVPPAGE, "TLVPPAGE"},
|
||||
{AArch64MCExpr::M_TLVPPAGEOFF, "TLVPPAGEOFF"},
|
||||
};
|
||||
|
||||
AArch64MCAsmInfoDarwin::AArch64MCAsmInfoDarwin(bool IsILP32) {
|
||||
@@ -64,7 +73,7 @@ AArch64MCAsmInfoDarwin::AArch64MCAsmInfoDarwin(bool IsILP32) {
|
||||
|
||||
ExceptionsType = ExceptionHandling::DwarfCFI;
|
||||
|
||||
initializeVariantKinds(variantKindDescs);
|
||||
initializeVariantKinds(MachOAtSpecifiers);
|
||||
}
|
||||
|
||||
const MCExpr *AArch64MCAsmInfoDarwin::getExprForPersonalitySymbol(
|
||||
@@ -75,7 +84,7 @@ const MCExpr *AArch64MCAsmInfoDarwin::getExprForPersonalitySymbol(
|
||||
// version.
|
||||
MCContext &Context = Streamer.getContext();
|
||||
const MCExpr *Res =
|
||||
MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_GOT, Context);
|
||||
MCSymbolRefExpr::create(Sym, AArch64MCExpr::M_GOT, Context);
|
||||
MCSymbol *PCSym = Context.createTempSymbol();
|
||||
Streamer.emitLabel(PCSym);
|
||||
const MCExpr *PC = MCSymbolRefExpr::create(PCSym, Context);
|
||||
@@ -115,7 +124,7 @@ AArch64MCAsmInfoELF::AArch64MCAsmInfoELF(const Triple &T) {
|
||||
|
||||
HasIdentDirective = true;
|
||||
|
||||
initializeVariantKinds(variantKindDescs);
|
||||
initializeVariantKinds(ELFAtSpecifiers);
|
||||
}
|
||||
|
||||
AArch64MCAsmInfoMicrosoftCOFF::AArch64MCAsmInfoMicrosoftCOFF() {
|
||||
@@ -134,7 +143,7 @@ AArch64MCAsmInfoMicrosoftCOFF::AArch64MCAsmInfoMicrosoftCOFF() {
|
||||
ExceptionsType = ExceptionHandling::WinEH;
|
||||
WinEHEncodingType = WinEH::EncodingType::Itanium;
|
||||
|
||||
initializeVariantKinds(variantKindDescs);
|
||||
initializeVariantKinds(COFFAtSpecifiers);
|
||||
}
|
||||
|
||||
AArch64MCAsmInfoGNUCOFF::AArch64MCAsmInfoGNUCOFF() {
|
||||
@@ -153,5 +162,5 @@ AArch64MCAsmInfoGNUCOFF::AArch64MCAsmInfoGNUCOFF() {
|
||||
ExceptionsType = ExceptionHandling::WinEH;
|
||||
WinEHEncodingType = WinEH::EncodingType::Itanium;
|
||||
|
||||
initializeVariantKinds(variantKindDescs);
|
||||
initializeVariantKinds(COFFAtSpecifiers);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ class AArch64MCExpr : public MCTargetExpr {
|
||||
public:
|
||||
enum Specifier : uint16_t {
|
||||
// clang-format off
|
||||
None = 0,
|
||||
// Symbol locations specifying (roughly speaking) what calculation should be
|
||||
// performed to construct the final address for the relocated
|
||||
// symbol. E.g. direct, via the GOT, ...
|
||||
@@ -120,6 +121,20 @@ public:
|
||||
VK_SECREL_LO12 = VK_SECREL | VK_PAGEOFF,
|
||||
VK_SECREL_HI12 = VK_SECREL | VK_HI12,
|
||||
|
||||
// ELF relocation specifiers in data directives:
|
||||
VK_PLT = 0x400,
|
||||
VK_GOTPCREL,
|
||||
|
||||
// Mach-O @ relocation specifiers:
|
||||
M_GOT,
|
||||
M_GOTPAGE,
|
||||
M_GOTPAGEOFF,
|
||||
M_PAGE,
|
||||
M_PAGEOFF,
|
||||
M_TLVP,
|
||||
M_TLVPPAGE,
|
||||
M_TLVPPAGEOFF,
|
||||
|
||||
VK_INVALID = 0xfff
|
||||
// clang-format on
|
||||
};
|
||||
@@ -214,6 +229,13 @@ public:
|
||||
return E->getSpecifier() == VK_AUTH || E->getSpecifier() == VK_AUTHADDR;
|
||||
}
|
||||
};
|
||||
|
||||
// Getter for the legacy representation that encodes the relocation specifier in
|
||||
// MCSymbolRefExpr::SubclassData.
|
||||
static inline AArch64MCExpr::Specifier
|
||||
getSpecifier(const MCSymbolRefExpr *SRE) {
|
||||
return AArch64MCExpr::Specifier(SRE->getKind());
|
||||
}
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
||||
@@ -66,12 +66,12 @@ bool AArch64MachObjectWriter::getAArch64FixupKindMachOInfo(
|
||||
return true;
|
||||
case FK_Data_4:
|
||||
Log2Size = Log2_32(4);
|
||||
if (Sym->getKind() == MCSymbolRefExpr::VK_GOT)
|
||||
if (getSpecifier(Sym) == AArch64MCExpr::M_GOT)
|
||||
RelocType = unsigned(MachO::ARM64_RELOC_POINTER_TO_GOT);
|
||||
return true;
|
||||
case FK_Data_8:
|
||||
Log2Size = Log2_32(8);
|
||||
if (Sym->getKind() == MCSymbolRefExpr::VK_GOT)
|
||||
if (getSpecifier(Sym) == AArch64MCExpr::M_GOT)
|
||||
RelocType = unsigned(MachO::ARM64_RELOC_POINTER_TO_GOT);
|
||||
return true;
|
||||
case AArch64::fixup_aarch64_add_imm12:
|
||||
@@ -81,34 +81,34 @@ bool AArch64MachObjectWriter::getAArch64FixupKindMachOInfo(
|
||||
case AArch64::fixup_aarch64_ldst_imm12_scale8:
|
||||
case AArch64::fixup_aarch64_ldst_imm12_scale16:
|
||||
Log2Size = Log2_32(4);
|
||||
switch (Sym->getKind()) {
|
||||
switch (AArch64MCExpr::Specifier(getSpecifier(Sym))) {
|
||||
default:
|
||||
return false;
|
||||
case MCSymbolRefExpr::VK_PAGEOFF:
|
||||
case AArch64MCExpr::M_PAGEOFF:
|
||||
RelocType = unsigned(MachO::ARM64_RELOC_PAGEOFF12);
|
||||
return true;
|
||||
case MCSymbolRefExpr::VK_GOTPAGEOFF:
|
||||
case AArch64MCExpr::M_GOTPAGEOFF:
|
||||
RelocType = unsigned(MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12);
|
||||
return true;
|
||||
case MCSymbolRefExpr::VK_TLVPPAGEOFF:
|
||||
case AArch64MCExpr::M_TLVPPAGEOFF:
|
||||
RelocType = unsigned(MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12);
|
||||
return true;
|
||||
}
|
||||
case AArch64::fixup_aarch64_pcrel_adrp_imm21:
|
||||
Log2Size = Log2_32(4);
|
||||
// This encompasses the relocation for the whole 21-bit value.
|
||||
switch (Sym->getKind()) {
|
||||
switch (getSpecifier(Sym)) {
|
||||
default:
|
||||
Asm.getContext().reportError(Fixup.getLoc(),
|
||||
"ADR/ADRP relocations must be GOT relative");
|
||||
return false;
|
||||
case MCSymbolRefExpr::VK_PAGE:
|
||||
case AArch64MCExpr::M_PAGE:
|
||||
RelocType = unsigned(MachO::ARM64_RELOC_PAGE21);
|
||||
return true;
|
||||
case MCSymbolRefExpr::VK_GOTPAGE:
|
||||
case AArch64MCExpr::M_GOTPAGE:
|
||||
RelocType = unsigned(MachO::ARM64_RELOC_GOT_LOAD_PAGE21);
|
||||
return true;
|
||||
case MCSymbolRefExpr::VK_TLVPPAGE:
|
||||
case AArch64MCExpr::M_TLVPPAGE:
|
||||
RelocType = unsigned(MachO::ARM64_RELOC_TLVP_LOAD_PAGE21);
|
||||
return true;
|
||||
}
|
||||
@@ -221,7 +221,7 @@ void AArch64MachObjectWriter::recordRelocation(
|
||||
// Check for "_foo@got - .", which comes through here as:
|
||||
// Ltmp0:
|
||||
// ... _foo@got - Ltmp0
|
||||
if (Target.getSymA()->getKind() == MCSymbolRefExpr::VK_GOT &&
|
||||
if (getSpecifier(Target.getSymA()) == AArch64MCExpr::M_GOT &&
|
||||
Asm.getSymbolOffset(*B) ==
|
||||
Asm.getFragmentOffset(*Fragment) + Fixup.getOffset()) {
|
||||
// SymB is the PC, so use a PC-rel pointer-to-GOT relocation.
|
||||
@@ -232,7 +232,7 @@ void AArch64MachObjectWriter::recordRelocation(
|
||||
MRE.r_word1 = (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);
|
||||
Writer->addRelocation(A_Base, Fragment->getParent(), MRE);
|
||||
return;
|
||||
} else if (Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None) {
|
||||
} else if (getSpecifier(Target.getSymA()) != AArch64MCExpr::None) {
|
||||
// Otherwise, neither symbol can be modified.
|
||||
Asm.getContext().reportError(Fixup.getLoc(),
|
||||
"unsupported relocation of modified symbol");
|
||||
|
||||
@@ -61,8 +61,8 @@ unsigned AArch64WinCOFFObjectWriter::getRelocType(
|
||||
FixupKind = FK_PCRel_4;
|
||||
}
|
||||
|
||||
auto Modifier = Target.isAbsolute() ? MCSymbolRefExpr::VK_None
|
||||
: Target.getSymA()->getKind();
|
||||
auto Modifier =
|
||||
Target.isAbsolute() ? AArch64MCExpr::None : Target.getSymA()->getKind();
|
||||
const MCExpr *Expr = Fixup.getValue();
|
||||
|
||||
if (const AArch64MCExpr *A64E = dyn_cast<AArch64MCExpr>(Expr)) {
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
// RUN: llvm-objdump -s %t.obj | FileCheck %s --check-prefix=DATA
|
||||
// RUN: llvm-objdump -s %t-ec.obj | FileCheck %s --check-prefix=DATA
|
||||
|
||||
# RUN: not llvm-mc -triple=aarch64-windows -filetype=obj %s --defsym ERR=1 -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR --implicit-check-not=error:
|
||||
|
||||
// IMAGE_REL_ARM64_ADDR32
|
||||
.Linfo_foo:
|
||||
.asciz "foo"
|
||||
@@ -121,3 +123,8 @@ tbz x0, #0, target
|
||||
|
||||
// DATA: Contents of section .rdata:
|
||||
// DATA-NEXT: 0000 30000000 08000000
|
||||
|
||||
.ifdef ERR
|
||||
# ERR: [[#@LINE+1]]:12: error: invalid variant 'plt'
|
||||
.long func@plt
|
||||
.endif
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# RUN: llvm-mc -triple=aarch64 -filetype=obj %s | llvm-readobj -r - | FileCheck %s
|
||||
# RUN: not llvm-mc -triple=aarch64 -filetype=obj %s --defsym ERR=1 -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR --implicit-check-not=error:
|
||||
# RUN: not llvm-mc -triple=aarch64 -filetype=obj %s --defsym OBJERR=1 -o /dev/null 2>&1 | FileCheck %s --check-prefix=OBJERR --implicit-check-not=error:
|
||||
|
||||
.globl g
|
||||
g:
|
||||
@@ -31,14 +32,21 @@ data1:
|
||||
.word extern@gotpcrel+4
|
||||
.word extern@GOTPCREL-5
|
||||
|
||||
## Test parse-time errors
|
||||
.ifdef ERR
|
||||
# ERR: [[#@LINE+1]]:7: error: symbol 'und' can not be undefined in a subtraction expression
|
||||
# ERR: [[#@LINE+1]]:14: error: invalid variant 'pageoff'
|
||||
.word extern@pageoff
|
||||
.endif
|
||||
|
||||
## Test assemble-time errors
|
||||
.ifdef OBJERR
|
||||
# OBJERR: [[#@LINE+1]]:7: error: symbol 'und' can not be undefined in a subtraction expression
|
||||
.word extern@plt - und
|
||||
|
||||
.quad g@plt - .
|
||||
|
||||
.word extern@gotpcrel - .
|
||||
|
||||
# ERR: [[#@LINE+1]]:7: error: symbol 'und' can not be undefined in a subtraction expression
|
||||
# OBJERR: [[#@LINE+1]]:7: error: symbol 'und' can not be undefined in a subtraction expression
|
||||
.word extern@gotpcrel - und
|
||||
.endif
|
||||
|
||||
Reference in New Issue
Block a user