mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-01 15:11:24 +00:00
Model :upper16: and :lower16: as ARM specific MCTargetExpr. This is a step
in the right direction. It eliminated some hacks and will unblock codegen work. But it's far from being done. It doesn't reject illegal expressions, e.g. (FOO - :lower16:BAR). It also doesn't work in Thumb2 mode at all. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@123369 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
04f5079ca1
commit
7597212abc
@ -155,8 +155,6 @@ public:
|
|||||||
VK_TPOFF,
|
VK_TPOFF,
|
||||||
VK_DTPOFF,
|
VK_DTPOFF,
|
||||||
VK_TLVP, // Mach-O thread local variable relocation
|
VK_TLVP, // Mach-O thread local variable relocation
|
||||||
VK_ARM_HI16, // The R_ARM_MOVT_ABS relocation (:upper16: in the .s file)
|
|
||||||
VK_ARM_LO16, // The R_ARM_MOVW_ABS_NC relocation (:lower16: in the .w file)
|
|
||||||
// FIXME: We'd really like to use the generic Kinds listed above for these.
|
// FIXME: We'd really like to use the generic Kinds listed above for these.
|
||||||
VK_ARM_PLT, // ARM-style PLT references. i.e., (PLT) instead of @PLT
|
VK_ARM_PLT, // ARM-style PLT references. i.e., (PLT) instead of @PLT
|
||||||
VK_ARM_TLSGD, // ditto for TLSGD, GOT, GOTOFF, TPOFF and GOTTPOFF
|
VK_ARM_TLSGD, // ditto for TLSGD, GOT, GOTOFF, TPOFF and GOTTPOFF
|
||||||
@ -421,7 +419,7 @@ public:
|
|||||||
virtual void PrintImpl(raw_ostream &OS) const = 0;
|
virtual void PrintImpl(raw_ostream &OS) const = 0;
|
||||||
virtual bool EvaluateAsRelocatableImpl(MCValue &Res,
|
virtual bool EvaluateAsRelocatableImpl(MCValue &Res,
|
||||||
const MCAsmLayout *Layout) const = 0;
|
const MCAsmLayout *Layout) const = 0;
|
||||||
|
virtual void AddValueSymbols(MCAssembler *) const = 0;
|
||||||
|
|
||||||
static bool classof(const MCExpr *E) {
|
static bool classof(const MCExpr *E) {
|
||||||
return E->getKind() == MCExpr::Target;
|
return E->getKind() == MCExpr::Target;
|
||||||
|
@ -42,10 +42,6 @@ void MCExpr::print(raw_ostream &OS) const {
|
|||||||
// absolute names.
|
// absolute names.
|
||||||
bool UseParens = Sym.getName()[0] == '$';
|
bool UseParens = Sym.getName()[0] == '$';
|
||||||
|
|
||||||
if (SRE.getKind() == MCSymbolRefExpr::VK_ARM_HI16 ||
|
|
||||||
SRE.getKind() == MCSymbolRefExpr::VK_ARM_LO16)
|
|
||||||
OS << MCSymbolRefExpr::getVariantKindName(SRE.getKind());
|
|
||||||
|
|
||||||
if (SRE.getKind() == MCSymbolRefExpr::VK_PPC_HA16 ||
|
if (SRE.getKind() == MCSymbolRefExpr::VK_PPC_HA16 ||
|
||||||
SRE.getKind() == MCSymbolRefExpr::VK_PPC_LO16) {
|
SRE.getKind() == MCSymbolRefExpr::VK_PPC_LO16) {
|
||||||
OS << MCSymbolRefExpr::getVariantKindName(SRE.getKind());
|
OS << MCSymbolRefExpr::getVariantKindName(SRE.getKind());
|
||||||
@ -65,8 +61,6 @@ void MCExpr::print(raw_ostream &OS) const {
|
|||||||
SRE.getKind() == MCSymbolRefExpr::VK_ARM_GOTTPOFF)
|
SRE.getKind() == MCSymbolRefExpr::VK_ARM_GOTTPOFF)
|
||||||
OS << MCSymbolRefExpr::getVariantKindName(SRE.getKind());
|
OS << MCSymbolRefExpr::getVariantKindName(SRE.getKind());
|
||||||
else if (SRE.getKind() != MCSymbolRefExpr::VK_None &&
|
else if (SRE.getKind() != MCSymbolRefExpr::VK_None &&
|
||||||
SRE.getKind() != MCSymbolRefExpr::VK_ARM_HI16 &&
|
|
||||||
SRE.getKind() != MCSymbolRefExpr::VK_ARM_LO16 &&
|
|
||||||
SRE.getKind() != MCSymbolRefExpr::VK_PPC_HA16 &&
|
SRE.getKind() != MCSymbolRefExpr::VK_PPC_HA16 &&
|
||||||
SRE.getKind() != MCSymbolRefExpr::VK_PPC_LO16)
|
SRE.getKind() != MCSymbolRefExpr::VK_PPC_LO16)
|
||||||
OS << '@' << MCSymbolRefExpr::getVariantKindName(SRE.getKind());
|
OS << '@' << MCSymbolRefExpr::getVariantKindName(SRE.getKind());
|
||||||
@ -196,8 +190,6 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
|
|||||||
case VK_TPOFF: return "TPOFF";
|
case VK_TPOFF: return "TPOFF";
|
||||||
case VK_DTPOFF: return "DTPOFF";
|
case VK_DTPOFF: return "DTPOFF";
|
||||||
case VK_TLVP: return "TLVP";
|
case VK_TLVP: return "TLVP";
|
||||||
case VK_ARM_HI16: return ":upper16:";
|
|
||||||
case VK_ARM_LO16: return ":lower16:";
|
|
||||||
case VK_ARM_PLT: return "(PLT)";
|
case VK_ARM_PLT: return "(PLT)";
|
||||||
case VK_ARM_GOT: return "(GOT)";
|
case VK_ARM_GOT: return "(GOT)";
|
||||||
case VK_ARM_GOTOFF: return "(GOTOFF)";
|
case VK_ARM_GOTOFF: return "(GOTOFF)";
|
||||||
|
@ -56,7 +56,10 @@ MCDataFragment *MCObjectStreamer::getOrCreateDataFragment() const {
|
|||||||
|
|
||||||
const MCExpr *MCObjectStreamer::AddValueSymbols(const MCExpr *Value) {
|
const MCExpr *MCObjectStreamer::AddValueSymbols(const MCExpr *Value) {
|
||||||
switch (Value->getKind()) {
|
switch (Value->getKind()) {
|
||||||
case MCExpr::Target: llvm_unreachable("Can't handle target exprs yet!");
|
case MCExpr::Target:
|
||||||
|
cast<MCTargetExpr>(Value)->AddValueSymbols(Assembler);
|
||||||
|
break;
|
||||||
|
|
||||||
case MCExpr::Constant:
|
case MCExpr::Constant:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -251,7 +251,7 @@ namespace {
|
|||||||
return Binary;
|
return Binary;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned getMovtImmOpValue(const MachineInstr &MI, unsigned Op) const {
|
unsigned getHiLo16ImmOpValue(const MachineInstr &MI, unsigned Op) const {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -425,11 +425,11 @@ def imm0_31_m1 : Operand<i32>, PatLeaf<(imm), [{
|
|||||||
let EncoderMethod = "getImmMinusOneOpValue";
|
let EncoderMethod = "getImmMinusOneOpValue";
|
||||||
}
|
}
|
||||||
|
|
||||||
// For movt/movw - sets the MC Encoder method.
|
// i32imm_hilo16 - For movt/movw - sets the MC Encoder method.
|
||||||
// The imm is split into imm{15-12}, imm{11-0}
|
// The imm is split into imm{15-12}, imm{11-0}
|
||||||
//
|
//
|
||||||
def movt_imm : Operand<i32> {
|
def i32imm_hilo16 : Operand<i32> {
|
||||||
let EncoderMethod = "getMovtImmOpValue";
|
let EncoderMethod = "getHiLo16ImmOpValue";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// bf_inv_mask_imm predicate - An AND mask to clear an arbitrary width bitfield
|
/// bf_inv_mask_imm predicate - An AND mask to clear an arbitrary width bitfield
|
||||||
@ -1907,7 +1907,7 @@ def MOVi : AsI1<0b1101, (outs GPR:$Rd), (ins so_imm:$imm), DPFrm, IIC_iMOVi,
|
|||||||
}
|
}
|
||||||
|
|
||||||
let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in
|
let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in
|
||||||
def MOVi16 : AI1<0b1000, (outs GPR:$Rd), (ins movt_imm:$imm),
|
def MOVi16 : AI1<0b1000, (outs GPR:$Rd), (ins i32imm_hilo16:$imm),
|
||||||
DPFrm, IIC_iMOVi,
|
DPFrm, IIC_iMOVi,
|
||||||
"movw", "\t$Rd, $imm",
|
"movw", "\t$Rd, $imm",
|
||||||
[(set GPR:$Rd, imm0_65535:$imm)]>,
|
[(set GPR:$Rd, imm0_65535:$imm)]>,
|
||||||
@ -1922,7 +1922,7 @@ def MOVi16 : AI1<0b1000, (outs GPR:$Rd), (ins movt_imm:$imm),
|
|||||||
}
|
}
|
||||||
|
|
||||||
let Constraints = "$src = $Rd" in
|
let Constraints = "$src = $Rd" in
|
||||||
def MOVTi16 : AI1<0b1010, (outs GPR:$Rd), (ins GPR:$src, movt_imm:$imm),
|
def MOVTi16 : AI1<0b1010, (outs GPR:$Rd), (ins GPR:$src, i32imm_hilo16:$imm),
|
||||||
DPFrm, IIC_iMOVi,
|
DPFrm, IIC_iMOVi,
|
||||||
"movt", "\t$Rd, $imm",
|
"movt", "\t$Rd, $imm",
|
||||||
[(set GPR:$Rd,
|
[(set GPR:$Rd,
|
||||||
@ -3050,7 +3050,7 @@ def MOVCCs : AI1<0b1101, (outs GPR:$Rd),
|
|||||||
}
|
}
|
||||||
|
|
||||||
let isMoveImm = 1 in
|
let isMoveImm = 1 in
|
||||||
def MOVCCi16 : AI1<0b1000, (outs GPR:$Rd), (ins GPR:$false, movt_imm:$imm),
|
def MOVCCi16 : AI1<0b1000, (outs GPR:$Rd), (ins GPR:$false, i32imm_hilo16:$imm),
|
||||||
DPFrm, IIC_iMOVi,
|
DPFrm, IIC_iMOVi,
|
||||||
"movw", "\t$Rd, $imm",
|
"movw", "\t$Rd, $imm",
|
||||||
[]>,
|
[]>,
|
||||||
|
@ -1677,7 +1677,7 @@ def t2MOVi : T2sOneRegImm<(outs rGPR:$Rd), (ins t2_so_imm:$imm), IIC_iMOVi,
|
|||||||
}
|
}
|
||||||
|
|
||||||
let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in
|
let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in
|
||||||
def t2MOVi16 : T2I<(outs rGPR:$Rd), (ins i32imm:$imm), IIC_iMOVi,
|
def t2MOVi16 : T2I<(outs rGPR:$Rd), (ins i32imm_hilo16:$imm), IIC_iMOVi,
|
||||||
"movw", "\t$Rd, $imm",
|
"movw", "\t$Rd, $imm",
|
||||||
[(set rGPR:$Rd, imm0_65535:$imm)]> {
|
[(set rGPR:$Rd, imm0_65535:$imm)]> {
|
||||||
let Inst{31-27} = 0b11110;
|
let Inst{31-27} = 0b11110;
|
||||||
@ -1697,7 +1697,8 @@ def t2MOVi16 : T2I<(outs rGPR:$Rd), (ins i32imm:$imm), IIC_iMOVi,
|
|||||||
}
|
}
|
||||||
|
|
||||||
let Constraints = "$src = $Rd" in
|
let Constraints = "$src = $Rd" in
|
||||||
def t2MOVTi16 : T2I<(outs rGPR:$Rd), (ins rGPR:$src, i32imm:$imm), IIC_iMOVi,
|
def t2MOVTi16 : T2I<(outs rGPR:$Rd),
|
||||||
|
(ins rGPR:$src, i32imm_hilo16:$imm), IIC_iMOVi,
|
||||||
"movt", "\t$Rd, $imm",
|
"movt", "\t$Rd, $imm",
|
||||||
[(set rGPR:$Rd,
|
[(set rGPR:$Rd,
|
||||||
(or (and rGPR:$src, 0xffff), lo16AllZero:$imm))]> {
|
(or (and rGPR:$src, 0xffff), lo16AllZero:$imm))]> {
|
||||||
@ -2684,7 +2685,7 @@ def t2MOVCCi : T2OneRegImm<(outs rGPR:$Rd), (ins rGPR:$false, t2_so_imm:$imm),
|
|||||||
}
|
}
|
||||||
|
|
||||||
let isMoveImm = 1 in
|
let isMoveImm = 1 in
|
||||||
def t2MOVCCi16 : T2I<(outs rGPR:$Rd), (ins rGPR:$false, i32imm:$imm),
|
def t2MOVCCi16 : T2I<(outs rGPR:$Rd), (ins rGPR:$false, i32imm_hilo16:$imm),
|
||||||
IIC_iCMOVi,
|
IIC_iCMOVi,
|
||||||
"movw", "\t$Rd, $imm", []>,
|
"movw", "\t$Rd, $imm", []>,
|
||||||
RegConstraint<"$false = $Rd"> {
|
RegConstraint<"$false = $Rd"> {
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "ARMAddressingModes.h"
|
#include "ARMAddressingModes.h"
|
||||||
#include "ARMFixupKinds.h"
|
#include "ARMFixupKinds.h"
|
||||||
#include "ARMInstrInfo.h"
|
#include "ARMInstrInfo.h"
|
||||||
|
#include "ARMMCExpr.h"
|
||||||
#include "llvm/MC/MCCodeEmitter.h"
|
#include "llvm/MC/MCCodeEmitter.h"
|
||||||
#include "llvm/MC/MCExpr.h"
|
#include "llvm/MC/MCExpr.h"
|
||||||
#include "llvm/MC/MCInst.h"
|
#include "llvm/MC/MCInst.h"
|
||||||
@ -53,9 +54,11 @@ public:
|
|||||||
unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
|
unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
|
||||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||||
|
|
||||||
/// getMovtImmOpValue - Return the encoding for the movw/movt pair
|
/// getHiLo16ImmOpValue - Return the encoding for the hi / low 16-bit of
|
||||||
uint32_t getMovtImmOpValue(const MCInst &MI, unsigned OpIdx,
|
/// the specified operand. This is used for operands with :lower16: and
|
||||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
/// :upper16: prefixes.
|
||||||
|
uint32_t getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx,
|
||||||
|
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||||
|
|
||||||
bool EncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx,
|
bool EncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx,
|
||||||
unsigned &Reg, unsigned &Imm,
|
unsigned &Reg, unsigned &Imm,
|
||||||
@ -626,19 +629,6 @@ getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx,
|
|||||||
return Binary;
|
return Binary;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: This routine needs to handle more MCExpr types
|
|
||||||
static const MCSymbolRefExpr *FindLHSymExpr(const MCExpr *E) {
|
|
||||||
// recurse left child until finding a MCSymbolRefExpr
|
|
||||||
switch (E->getKind()) {
|
|
||||||
case MCExpr::SymbolRef:
|
|
||||||
return cast<MCSymbolRefExpr>(E);
|
|
||||||
case MCExpr::Binary:
|
|
||||||
return FindLHSymExpr(cast<MCBinaryExpr>(E)->getLHS());
|
|
||||||
default:
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: This routine assumes that a binary
|
// FIXME: This routine assumes that a binary
|
||||||
// expression will always result in a PCRel expression
|
// expression will always result in a PCRel expression
|
||||||
// In reality, its only true if one or more subexpressions
|
// In reality, its only true if one or more subexpressions
|
||||||
@ -652,38 +642,40 @@ static bool EvaluateAsPCRel(const MCExpr *Expr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ARMMCCodeEmitter::
|
uint32_t
|
||||||
getMovtImmOpValue(const MCInst &MI, unsigned OpIdx,
|
ARMMCCodeEmitter::getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx,
|
||||||
SmallVectorImpl<MCFixup> &Fixups) const {
|
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||||
// {20-16} = imm{15-12}
|
// {20-16} = imm{15-12}
|
||||||
// {11-0} = imm{11-0}
|
// {11-0} = imm{11-0}
|
||||||
const MCOperand &MO = MI.getOperand(OpIdx);
|
const MCOperand &MO = MI.getOperand(OpIdx);
|
||||||
if (MO.isImm()) {
|
if (MO.isImm())
|
||||||
|
// Hi / lo 16 bits already extracted during earlier passes.
|
||||||
return static_cast<unsigned>(MO.getImm());
|
return static_cast<unsigned>(MO.getImm());
|
||||||
} else if (const MCSymbolRefExpr *Expr =
|
|
||||||
FindLHSymExpr(MO.getExpr())) {
|
// Handle :upper16: and :lower16: assembly prefixes.
|
||||||
// FIXME: :lower16: and :upper16: should be applicable to
|
const MCExpr *E = MO.getExpr();
|
||||||
// to whole expression, not just symbolrefs
|
if (E->getKind() == MCExpr::Target) {
|
||||||
// Until that change takes place, this hack is required to
|
const ARMMCExpr *ARM16Expr = cast<ARMMCExpr>(E);
|
||||||
// generate working code.
|
E = ARM16Expr->getSubExpr();
|
||||||
const MCExpr *OrigExpr = MO.getExpr();
|
|
||||||
MCFixupKind Kind;
|
MCFixupKind Kind;
|
||||||
switch (Expr->getKind()) {
|
switch (ARM16Expr->getKind()) {
|
||||||
default: assert(0 && "Unsupported ARMFixup");
|
default: assert(0 && "Unsupported ARMFixup");
|
||||||
case MCSymbolRefExpr::VK_ARM_HI16:
|
case ARMMCExpr::VK_ARM_HI16:
|
||||||
Kind = MCFixupKind(ARM::fixup_arm_movt_hi16);
|
Kind = MCFixupKind(ARM::fixup_arm_movt_hi16);
|
||||||
if (EvaluateAsPCRel(OrigExpr))
|
if (EvaluateAsPCRel(E))
|
||||||
Kind = MCFixupKind(ARM::fixup_arm_movt_hi16_pcrel);
|
Kind = MCFixupKind(ARM::fixup_arm_movt_hi16_pcrel);
|
||||||
break;
|
break;
|
||||||
case MCSymbolRefExpr::VK_ARM_LO16:
|
case ARMMCExpr::VK_ARM_LO16:
|
||||||
Kind = MCFixupKind(ARM::fixup_arm_movw_lo16);
|
Kind = MCFixupKind(ARM::fixup_arm_movw_lo16);
|
||||||
if (EvaluateAsPCRel(OrigExpr))
|
if (EvaluateAsPCRel(E))
|
||||||
Kind = MCFixupKind(ARM::fixup_arm_movw_lo16_pcrel);
|
Kind = MCFixupKind(ARM::fixup_arm_movw_lo16_pcrel);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Fixups.push_back(MCFixup::Create(0, OrigExpr, Kind));
|
Fixups.push_back(MCFixup::Create(0, E, Kind));
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
llvm_unreachable("Unsupported MCExpr type in MCOperand!");
|
llvm_unreachable("Unsupported MCExpr type in MCOperand!");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1173,8 +1165,8 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS,
|
|||||||
case ARMII::Size4Bytes: Size = 4; break;
|
case ARMII::Size4Bytes: Size = 4; break;
|
||||||
}
|
}
|
||||||
uint32_t Binary = getBinaryCodeForInstr(MI, Fixups);
|
uint32_t Binary = getBinaryCodeForInstr(MI, Fixups);
|
||||||
// Thumb 32-bit wide instructions need to be have the high order halfword
|
// Thumb 32-bit wide instructions need to emit the high order halfword
|
||||||
// emitted first.
|
// first.
|
||||||
if (Subtarget.isThumb() && Size == 4) {
|
if (Subtarget.isThumb() && Size == 4) {
|
||||||
EmitConstant(Binary >> 16, 2, OS);
|
EmitConstant(Binary >> 16, 2, OS);
|
||||||
EmitConstant(Binary & 0xffff, 2, OS);
|
EmitConstant(Binary & 0xffff, 2, OS);
|
||||||
|
73
lib/Target/ARM/ARMMCExpr.cpp
Normal file
73
lib/Target/ARM/ARMMCExpr.cpp
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
//===-- ARMMCExpr.cpp - ARM specific MC expression classes ----------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#define DEBUG_TYPE "armmcexpr"
|
||||||
|
#include "ARMMCExpr.h"
|
||||||
|
#include "llvm/MC/MCContext.h"
|
||||||
|
#include "llvm/MC/MCAssembler.h"
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
|
const ARMMCExpr*
|
||||||
|
ARMMCExpr::Create(VariantKind Kind, const MCExpr *Expr,
|
||||||
|
MCContext &Ctx) {
|
||||||
|
return new (Ctx) ARMMCExpr(Kind, Expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ARMMCExpr::PrintImpl(raw_ostream &OS) const {
|
||||||
|
switch (Kind) {
|
||||||
|
default: assert(0 && "Invalid kind!");
|
||||||
|
case VK_ARM_HI16: OS << ":upper16:"; break;
|
||||||
|
case VK_ARM_LO16: OS << ":lower16:"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MCExpr *Expr = getSubExpr();
|
||||||
|
if (Expr->getKind() != MCExpr::SymbolRef)
|
||||||
|
OS << '(';
|
||||||
|
Expr->print(OS);
|
||||||
|
if (Expr->getKind() != MCExpr::SymbolRef)
|
||||||
|
OS << ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ARMMCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
|
||||||
|
const MCAsmLayout *Layout) const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: This basically copies MCObjectStreamer::AddValueSymbols. Perhaps
|
||||||
|
// that method should be made public?
|
||||||
|
static void AddValueSymbols_(const MCExpr *Value, MCAssembler *Asm) {
|
||||||
|
switch (Value->getKind()) {
|
||||||
|
case MCExpr::Target:
|
||||||
|
assert(0 && "Can't handle nested target expr!");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MCExpr::Constant:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MCExpr::Binary: {
|
||||||
|
const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value);
|
||||||
|
AddValueSymbols_(BE->getLHS(), Asm);
|
||||||
|
AddValueSymbols_(BE->getRHS(), Asm);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MCExpr::SymbolRef:
|
||||||
|
Asm->getOrCreateSymbolData(cast<MCSymbolRefExpr>(Value)->getSymbol());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MCExpr::Unary:
|
||||||
|
AddValueSymbols_(cast<MCUnaryExpr>(Value)->getSubExpr(), Asm);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ARMMCExpr::AddValueSymbols(MCAssembler *Asm) const {
|
||||||
|
AddValueSymbols_(getSubExpr(), Asm);
|
||||||
|
}
|
73
lib/Target/ARM/ARMMCExpr.h
Normal file
73
lib/Target/ARM/ARMMCExpr.h
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
//===-- ARMMCExpr.h - ARM specific MC expression classes ------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef ARMMCEXPR_H
|
||||||
|
#define ARMMCEXPR_H
|
||||||
|
|
||||||
|
#include "llvm/MC/MCExpr.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
|
||||||
|
class ARMMCExpr : public MCTargetExpr {
|
||||||
|
public:
|
||||||
|
enum VariantKind {
|
||||||
|
VK_ARM_None,
|
||||||
|
VK_ARM_HI16, // The R_ARM_MOVT_ABS relocation (:upper16: in the .s file)
|
||||||
|
VK_ARM_LO16 // The R_ARM_MOVW_ABS_NC relocation (:lower16: in the .s file)
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
const VariantKind Kind;
|
||||||
|
const MCExpr *Expr;
|
||||||
|
|
||||||
|
explicit ARMMCExpr(VariantKind _Kind, const MCExpr *_Expr)
|
||||||
|
: Kind(_Kind), Expr(_Expr) {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// @name Construction
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
static const ARMMCExpr *Create(VariantKind Kind, const MCExpr *Expr,
|
||||||
|
MCContext &Ctx);
|
||||||
|
|
||||||
|
static const ARMMCExpr *CreateUpper16(const MCExpr *Expr, MCContext &Ctx) {
|
||||||
|
return Create(VK_ARM_HI16, Expr, Ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const ARMMCExpr *CreateLower16(const MCExpr *Expr, MCContext &Ctx) {
|
||||||
|
return Create(VK_ARM_LO16, Expr, Ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
/// @name Accessors
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/// getOpcode - Get the kind of this expression.
|
||||||
|
VariantKind getKind() const { return Kind; }
|
||||||
|
|
||||||
|
/// getSubExpr - Get the child of this expression.
|
||||||
|
const MCExpr *getSubExpr() const { return Expr; }
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
void PrintImpl(raw_ostream &OS) const;
|
||||||
|
bool EvaluateAsRelocatableImpl(MCValue &Res,
|
||||||
|
const MCAsmLayout *Layout) const;
|
||||||
|
void AddValueSymbols(MCAssembler *) const;
|
||||||
|
|
||||||
|
static bool classof(const MCExpr *E) {
|
||||||
|
return E->getKind() == MCExpr::Target;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool classof(const ARMMCExpr *) { return true; }
|
||||||
|
|
||||||
|
};
|
||||||
|
} // end namespace llvm
|
||||||
|
|
||||||
|
#endif
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include "ARM.h"
|
#include "ARM.h"
|
||||||
#include "ARMAsmPrinter.h"
|
#include "ARMAsmPrinter.h"
|
||||||
|
#include "ARMMCExpr.h"
|
||||||
#include "llvm/Constants.h"
|
#include "llvm/Constants.h"
|
||||||
#include "llvm/CodeGen/MachineBasicBlock.h"
|
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||||
#include "llvm/MC/MCExpr.h"
|
#include "llvm/MC/MCExpr.h"
|
||||||
@ -27,16 +28,25 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
|
|||||||
MCContext &Ctx = Printer.OutContext;
|
MCContext &Ctx = Printer.OutContext;
|
||||||
const MCExpr *Expr;
|
const MCExpr *Expr;
|
||||||
switch (MO.getTargetFlags()) {
|
switch (MO.getTargetFlags()) {
|
||||||
default: assert(0 && "Unknown target flag on symbol operand");
|
default: {
|
||||||
case 0:
|
|
||||||
Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None, Ctx);
|
Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None, Ctx);
|
||||||
|
switch (MO.getTargetFlags()) {
|
||||||
|
default:
|
||||||
|
assert(0 && "Unknown target flag on symbol operand");
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case ARMII::MO_LO16:
|
||||||
|
Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None, Ctx);
|
||||||
|
Expr = ARMMCExpr::CreateLower16(Expr, Ctx);
|
||||||
|
break;
|
||||||
|
case ARMII::MO_HI16:
|
||||||
|
Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None, Ctx);
|
||||||
|
Expr = ARMMCExpr::CreateUpper16(Expr, Ctx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ARMII::MO_LO16:
|
}
|
||||||
Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_ARM_LO16, Ctx);
|
|
||||||
break;
|
|
||||||
case ARMII::MO_HI16:
|
|
||||||
Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_ARM_HI16, Ctx);
|
|
||||||
break;
|
|
||||||
case ARMII::MO_PLT:
|
case ARMII::MO_PLT:
|
||||||
Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_ARM_PLT, Ctx);
|
Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_ARM_PLT, Ctx);
|
||||||
break;
|
break;
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "ARM.h"
|
#include "ARM.h"
|
||||||
#include "ARMAddressingModes.h"
|
#include "ARMAddressingModes.h"
|
||||||
|
#include "ARMMCExpr.h"
|
||||||
#include "ARMBaseRegisterInfo.h"
|
#include "ARMBaseRegisterInfo.h"
|
||||||
#include "ARMSubtarget.h"
|
#include "ARMSubtarget.h"
|
||||||
#include "llvm/MC/MCParser/MCAsmLexer.h"
|
#include "llvm/MC/MCParser/MCAsmLexer.h"
|
||||||
@ -55,7 +56,7 @@ class ARMAsmParser : public TargetAsmParser {
|
|||||||
bool ParseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
|
bool ParseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
|
||||||
bool ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
|
bool ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
|
||||||
bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &);
|
bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &);
|
||||||
bool ParsePrefix(MCSymbolRefExpr::VariantKind &RefKind);
|
bool ParsePrefix(ARMMCExpr::VariantKind &RefKind);
|
||||||
const MCExpr *ApplyPrefixToExpr(const MCExpr *E,
|
const MCExpr *ApplyPrefixToExpr(const MCExpr *E,
|
||||||
MCSymbolRefExpr::VariantKind Variant);
|
MCSymbolRefExpr::VariantKind Variant);
|
||||||
|
|
||||||
@ -870,36 +871,29 @@ bool ARMAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands){
|
|||||||
return false;
|
return false;
|
||||||
case AsmToken::Colon: {
|
case AsmToken::Colon: {
|
||||||
// ":lower16:" and ":upper16:" expression prefixes
|
// ":lower16:" and ":upper16:" expression prefixes
|
||||||
MCSymbolRefExpr::VariantKind RefKind;
|
// FIXME: Check it's an expression prefix,
|
||||||
|
// e.g. (FOO - :lower16:BAR) isn't legal.
|
||||||
|
ARMMCExpr::VariantKind RefKind;
|
||||||
if (ParsePrefix(RefKind))
|
if (ParsePrefix(RefKind))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
const MCExpr *ExprVal;
|
const MCExpr *SubExprVal;
|
||||||
if (getParser().ParseExpression(ExprVal))
|
if (getParser().ParseExpression(SubExprVal))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// TODO: Attach the prefix to the entire expression
|
const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
|
||||||
// instead of just the first symbol.
|
getContext());
|
||||||
const MCExpr *ModExprVal = ApplyPrefixToExpr(ExprVal, RefKind);
|
|
||||||
if (!ModExprVal) {
|
|
||||||
return TokError("invalid modifier '" + getTok().getIdentifier() +
|
|
||||||
"' (no symbols present)");
|
|
||||||
}
|
|
||||||
|
|
||||||
E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
|
E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
|
||||||
Operands.push_back(ARMOperand::CreateImm(ModExprVal, S, E));
|
Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: The next 2 routines are hacks to get ARMAsmParser to understand
|
// ParsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
|
||||||
// :lower16: and :upper16:
|
// :lower16: and :upper16:.
|
||||||
// It still attaches VK_ARM_HI/LO16 to MCSymbolRefExpr, but it really
|
bool ARMAsmParser::ParsePrefix(ARMMCExpr::VariantKind &RefKind) {
|
||||||
// should be attached to the entire MCExpr as a whole - perhaps using
|
RefKind = ARMMCExpr::VK_ARM_None;
|
||||||
// MCTargetExpr?
|
|
||||||
bool ARMAsmParser::ParsePrefix(MCSymbolRefExpr::VariantKind &RefKind) {
|
|
||||||
RefKind = MCSymbolRefExpr::VK_None;
|
|
||||||
|
|
||||||
// :lower16: and :upper16: modifiers
|
// :lower16: and :upper16: modifiers
|
||||||
assert(getLexer().is(AsmToken::Colon) && "expected a :");
|
assert(getLexer().is(AsmToken::Colon) && "expected a :");
|
||||||
@ -912,9 +906,9 @@ bool ARMAsmParser::ParsePrefix(MCSymbolRefExpr::VariantKind &RefKind) {
|
|||||||
|
|
||||||
StringRef IDVal = Parser.getTok().getIdentifier();
|
StringRef IDVal = Parser.getTok().getIdentifier();
|
||||||
if (IDVal == "lower16") {
|
if (IDVal == "lower16") {
|
||||||
RefKind = MCSymbolRefExpr::VK_ARM_LO16;
|
RefKind = ARMMCExpr::VK_ARM_LO16;
|
||||||
} else if (IDVal == "upper16") {
|
} else if (IDVal == "upper16") {
|
||||||
RefKind = MCSymbolRefExpr::VK_ARM_HI16;
|
RefKind = ARMMCExpr::VK_ARM_HI16;
|
||||||
} else {
|
} else {
|
||||||
Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
|
Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
|
||||||
return true;
|
return true;
|
||||||
|
@ -35,6 +35,7 @@ add_llvm_target(ARMCodeGen
|
|||||||
ARMInstrInfo.cpp
|
ARMInstrInfo.cpp
|
||||||
ARMJITInfo.cpp
|
ARMJITInfo.cpp
|
||||||
ARMMCCodeEmitter.cpp
|
ARMMCCodeEmitter.cpp
|
||||||
|
ARMMCExpr.cpp
|
||||||
ARMLoadStoreOptimizer.cpp
|
ARMLoadStoreOptimizer.cpp
|
||||||
ARMMCAsmInfo.cpp
|
ARMMCAsmInfo.cpp
|
||||||
ARMMCInstLower.cpp
|
ARMMCInstLower.cpp
|
||||||
|
@ -11,8 +11,8 @@ barf: @ @barf
|
|||||||
movw r0, :lower16:GOT-(.LPC0_2+8)
|
movw r0, :lower16:GOT-(.LPC0_2+8)
|
||||||
movt r0, :upper16:GOT-(.LPC0_2+16)
|
movt r0, :upper16:GOT-(.LPC0_2+16)
|
||||||
.LPC0_2:
|
.LPC0_2:
|
||||||
@ ASM: movw r0, :lower16:GOT-(.LPC0_2+8)
|
@ ASM: movw r0, :lower16:(GOT-(.LPC0_2+8))
|
||||||
@ ASM-NEXT: movt r0, :upper16:GOT-(.LPC0_2+16)
|
@ ASM-NEXT: movt r0, :upper16:(GOT-(.LPC0_2+16))
|
||||||
|
|
||||||
@@ make sure that the text section fixups are sane too
|
@@ make sure that the text section fixups are sane too
|
||||||
@ OBJ: '.text'
|
@ OBJ: '.text'
|
||||||
|
21
test/MC/ARM/hilo-16bit-relocations.s
Normal file
21
test/MC/ARM/hilo-16bit-relocations.s
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
@ RUN: llvm-mc %s -triple armv7-apple-darwin -show-encoding | FileCheck %s
|
||||||
|
|
||||||
|
_t:
|
||||||
|
movw r0, :lower16:(L_foo$non_lazy_ptr - (L1 + 8))
|
||||||
|
movt r0, :upper16:(L_foo$non_lazy_ptr - (L1 + 8))
|
||||||
|
L1:
|
||||||
|
|
||||||
|
@ CHECK: movw r0, :lower16:(L_foo$non_lazy_ptr-(L1+8)) @ encoding: [A,A,0x00,0xe3]
|
||||||
|
@ CHECK: @ fixup A - offset: 0, value: L_foo$non_lazy_ptr-(L1+8), kind: fixup_arm_movw_lo16_pcrel
|
||||||
|
@ CHECK: movt r0, :upper16:(L_foo$non_lazy_ptr-(L1+8)) @ encoding: [A,A,0x40,0xe3]
|
||||||
|
@ CHECK: @ fixup A - offset: 0, value: L_foo$non_lazy_ptr-(L1+8), kind: fixup_arm_movt_hi16_pcrel
|
||||||
|
|
||||||
|
.comm _foo,4,2
|
||||||
|
|
||||||
|
.section __DATA,__nl_symbol_ptr,non_lazy_symbol_pointers
|
||||||
|
.align 2
|
||||||
|
L_foo$non_lazy_ptr:
|
||||||
|
.indirect_symbol _foo
|
||||||
|
.long 0
|
||||||
|
|
||||||
|
.subsections_via_symbols
|
@ -564,7 +564,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
|
|||||||
REG("QQQQPR");
|
REG("QQQQPR");
|
||||||
|
|
||||||
IMM("i32imm");
|
IMM("i32imm");
|
||||||
IMM("movt_imm");
|
IMM("i32imm_hilo16");
|
||||||
IMM("bf_inv_mask_imm");
|
IMM("bf_inv_mask_imm");
|
||||||
IMM("jtblock_operand");
|
IMM("jtblock_operand");
|
||||||
IMM("nohash_imm");
|
IMM("nohash_imm");
|
||||||
|
Loading…
Reference in New Issue
Block a user