mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
Fix PR20056: Implement pseudo LDR <reg>, =<literal/label> for AArch64
This patch is based on the changes from ARM target [1,2] Based on ARM doc [3], if the literal value can be loaded with a valid MOV, it can emit that instruction. This is implemented in this patch. [1] Fix PR18345: ldr= pseudo instruction produces incorrect code when using in inline assembly Author: David Peixotto <dpeixott@codeaurora.org> commitb92cca2228
(r200777) [2] Implement the ldr-pseudo opcode for ARM assembly Author: David Peixotto <dpeixott@codeaurora.org> commit0fa193b086
(r197708) [3] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0802a/CJAHAIBC.html Differential Revision: http://reviews.llvm.org/D4163 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@211533 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
2da970364f
commit
3cffac5061
@ -86,6 +86,27 @@ public:
|
||||
virtual void finish();
|
||||
};
|
||||
|
||||
class AArch64TargetStreamer : public MCTargetStreamer {
|
||||
public:
|
||||
AArch64TargetStreamer(MCStreamer &S);
|
||||
~AArch64TargetStreamer();
|
||||
|
||||
|
||||
void finish() override;
|
||||
|
||||
/// Callback used to implement the ldr= pseudo.
|
||||
/// Add a new entry to the constant pool for the current section and return an
|
||||
/// MCExpr that can be used to refer to the constant pool location.
|
||||
const MCExpr *addConstantPoolEntry(const MCExpr *);
|
||||
|
||||
/// Callback used to implemnt the .ltorg directive.
|
||||
/// Emit contents of constant pool for the current section.
|
||||
void emitCurrentConstantPool();
|
||||
|
||||
private:
|
||||
std::unique_ptr<AssemblerConstantPools> ConstantPools;
|
||||
};
|
||||
|
||||
// FIXME: declared here because it is used from
|
||||
// lib/CodeGen/AsmPrinter/ARMException.cpp.
|
||||
class ARMTargetStreamer : public MCTargetStreamer {
|
||||
|
@ -43,6 +43,11 @@ private:
|
||||
MCSubtargetInfo &STI;
|
||||
MCAsmParser &Parser;
|
||||
|
||||
AArch64TargetStreamer &getTargetStreamer() {
|
||||
MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
|
||||
return static_cast<AArch64TargetStreamer &>(TS);
|
||||
}
|
||||
|
||||
MCAsmParser &getParser() const { return Parser; }
|
||||
MCAsmLexer &getLexer() const { return Parser.getLexer(); }
|
||||
|
||||
@ -67,6 +72,7 @@ private:
|
||||
bool parseDirectiveTLSDescCall(SMLoc L);
|
||||
|
||||
bool parseDirectiveLOH(StringRef LOH, SMLoc L);
|
||||
bool parseDirectiveLtorg(SMLoc L);
|
||||
|
||||
bool validateInstruction(MCInst &Inst, SmallVectorImpl<SMLoc> &Loc);
|
||||
bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
|
||||
@ -105,6 +111,8 @@ public:
|
||||
const MCTargetOptions &Options)
|
||||
: MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
|
||||
MCAsmParserExtension::Initialize(_Parser);
|
||||
if (Parser.getStreamer().getTargetStreamer() == nullptr)
|
||||
new AArch64TargetStreamer(Parser.getStreamer());
|
||||
|
||||
// Initialize the set of available features.
|
||||
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
|
||||
@ -3004,6 +3012,43 @@ bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
|
||||
Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
|
||||
return false;
|
||||
}
|
||||
case AsmToken::Equal: {
|
||||
SMLoc Loc = Parser.getTok().getLoc();
|
||||
if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
|
||||
return Error(Loc, "unexpected token in operand");
|
||||
Parser.Lex(); // Eat '='
|
||||
const MCExpr *SubExprVal;
|
||||
if (getParser().parseExpression(SubExprVal))
|
||||
return true;
|
||||
|
||||
MCContext& Ctx = getContext();
|
||||
E = SMLoc::getFromPointer(Loc.getPointer() - 1);
|
||||
// If the op is an imm and can be fit into a mov, then replace ldr with mov.
|
||||
if (isa<MCConstantExpr>(SubExprVal) && Operands.size() >= 2 &&
|
||||
static_cast<AArch64Operand &>(*Operands[1]).isReg()) {
|
||||
bool IsXReg = AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
|
||||
Operands[1]->getReg());
|
||||
uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
|
||||
uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
|
||||
while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
|
||||
ShiftAmt += 16;
|
||||
Imm >>= 16;
|
||||
}
|
||||
if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
|
||||
Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
|
||||
Operands.push_back(AArch64Operand::CreateImm(
|
||||
MCConstantExpr::Create(Imm, Ctx), S, E, Ctx));
|
||||
if (ShiftAmt)
|
||||
Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
|
||||
ShiftAmt, true, S, E, Ctx));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// If it is a label or an imm that cannot fit in a movz, put it into CP.
|
||||
const MCExpr *CPLoc = getTargetStreamer().addConstantPoolEntry(SubExprVal);
|
||||
Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3810,7 +3855,8 @@ bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
|
||||
return parseDirectiveWord(8, Loc);
|
||||
if (IDVal == ".tlsdesccall")
|
||||
return parseDirectiveTLSDescCall(Loc);
|
||||
|
||||
if (IDVal == ".ltorg" || IDVal == ".pool")
|
||||
return parseDirectiveLtorg(Loc);
|
||||
return parseDirectiveLOH(IDVal, Loc);
|
||||
}
|
||||
|
||||
@ -3911,6 +3957,13 @@ bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// parseDirectiveLtorg
|
||||
/// ::= .ltorg | .pool
|
||||
bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
|
||||
getTargetStreamer().emitCurrentConstantPool();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
|
||||
AArch64MCExpr::VariantKind &ELFRefKind,
|
||||
|
@ -7,6 +7,7 @@ add_llvm_library(LLVMAArch64Desc
|
||||
AArch64MCExpr.cpp
|
||||
AArch64MCTargetDesc.cpp
|
||||
AArch64MachObjectWriter.cpp
|
||||
AArch64TargetStreamer.cpp
|
||||
)
|
||||
add_dependencies(LLVMAArch64Desc AArch64CommonTableGen)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user