diff options
| author | Tim Northover <tnorthover@apple.com> | 2014-04-24 12:12:10 +0000 | 
|---|---|---|
| committer | Tim Northover <tnorthover@apple.com> | 2014-04-24 12:12:10 +0000 | 
| commit | 79ec019261e44ad5c03194aa124e4a5b1be04f7d (patch) | |
| tree | dfecc805095d966b2839f8e68f902fcc6ecc384b /llvm/lib | |
| parent | cf16ec238e469dcc83d335fddaa25a713231a2aa (diff) | |
| download | bcm5719-llvm-79ec019261e44ad5c03194aa124e4a5b1be04f7d.tar.gz bcm5719-llvm-79ec019261e44ad5c03194aa124e4a5b1be04f7d.zip | |
AArch64/ARM64: disentangle the "B.CC" and "LDR lit" operands
These can have different relocations in ELF. In particular both:
    b.eq global
    ldr x0, global
are valid, giving different relocations. The only possible way to distinguish
them is via a different fixup, so the operands had to be separated throughout
the backend.
llvm-svn: 207105
Diffstat (limited to 'llvm/lib')
10 files changed, 77 insertions, 37 deletions
| diff --git a/llvm/lib/Target/ARM64/ARM64InstrFormats.td b/llvm/lib/Target/ARM64/ARM64InstrFormats.td index 64113d89625..abb92514a5b 100644 --- a/llvm/lib/Target/ARM64/ARM64InstrFormats.td +++ b/llvm/lib/Target/ARM64/ARM64InstrFormats.td @@ -858,14 +858,14 @@ def dotCcode : Operand<i32> {  // Conditional branch target. 19-bit immediate. The low two bits of the target  // offset are implied zero and so are not part of the immediate. -def BranchTarget19Operand : AsmOperandClass { -  let Name = "BranchTarget19"; +def PCRelLabel19Operand : AsmOperandClass { +  let Name = "PCRelLabel19";  }  def am_brcond : Operand<OtherVT> {    let EncoderMethod = "getCondBranchTargetOpValue"; -  let DecoderMethod = "DecodeCondBranchTarget"; -  let PrintMethod = "printAlignedBranchTarget"; -  let ParserMatchClass = BranchTarget19Operand; +  let DecoderMethod = "DecodePCRelLabel19"; +  let PrintMethod = "printAlignedLabel"; +  let ParserMatchClass = PCRelLabel19Operand;  }  class BranchCond : I<(outs), (ins dotCcode:$cond, am_brcond:$target), @@ -922,7 +922,7 @@ def BranchTarget14Operand : AsmOperandClass {  }  def am_tbrcond : Operand<OtherVT> {    let EncoderMethod = "getTestBranchTargetOpValue"; -  let PrintMethod = "printAlignedBranchTarget"; +  let PrintMethod = "printAlignedLabel";    let ParserMatchClass = BranchTarget14Operand;  } @@ -956,12 +956,12 @@ def BranchTarget26Operand : AsmOperandClass {  }  def am_b_target : Operand<OtherVT> {    let EncoderMethod = "getBranchTargetOpValue"; -  let PrintMethod = "printAlignedBranchTarget"; +  let PrintMethod = "printAlignedLabel";    let ParserMatchClass = BranchTarget26Operand;  }  def am_bl_target : Operand<i64> {    let EncoderMethod = "getBranchTargetOpValue"; -  let PrintMethod = "printAlignedBranchTarget"; +  let PrintMethod = "printAlignedLabel";    let ParserMatchClass = BranchTarget26Operand;  } @@ -2128,9 +2128,18 @@ class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>  // Load literal  //--- +// Load literal address: 19-bit immediate. The low two bits of the target +// offset are implied zero and so are not part of the immediate. +def am_ldrlit : Operand<OtherVT> { +  let EncoderMethod = "getLoadLiteralOpValue"; +  let DecoderMethod = "DecodePCRelLabel19"; +  let PrintMethod = "printAlignedLabel"; +  let ParserMatchClass = PCRelLabel19Operand; +} +  let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in  class LoadLiteral<bits<2> opc, bit V, RegisterClass regtype, string asm> -    : I<(outs regtype:$Rt), (ins am_brcond:$label), +    : I<(outs regtype:$Rt), (ins am_ldrlit:$label),          asm, "\t$Rt, $label", "", []>,        Sched<[WriteLD]> {    bits<5> Rt; @@ -2145,7 +2154,7 @@ class LoadLiteral<bits<2> opc, bit V, RegisterClass regtype, string asm>  let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in  class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat> -    : I<(outs), (ins prfop:$Rt, am_brcond:$label), +    : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),          asm, "\t$Rt, $label", "", pat>,        Sched<[WriteLD]> {    bits<5> Rt; diff --git a/llvm/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp b/llvm/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp index 2f720e9c969..7efc4572bda 100644 --- a/llvm/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp +++ b/llvm/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp @@ -558,7 +558,7 @@ public:        return false;      return (Val >= -(0x2000000 << 2) && Val <= (0x1ffffff << 2));    } -  bool isBranchTarget19() const { +  bool isPCRelLabel19() const {      if (!isImm())        return false;      const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm()); @@ -1272,7 +1272,7 @@ public:      Inst.addOperand(MCOperand::CreateImm(MCE->getValue() >> 2));    } -  void addBranchTarget19Operands(MCInst &Inst, unsigned N) const { +  void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {      // Branch operands don't encode the low bits, so shift them off      // here. If it's a label, however, just put it on directly as there's      // not enough information now to do anything. diff --git a/llvm/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp b/llvm/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp index 097594f0340..2ada4a4cf9e 100644 --- a/llvm/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp +++ b/llvm/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp @@ -87,9 +87,8 @@ static DecodeStatus DecodeFixedPointScaleImm32(llvm::MCInst &Inst, unsigned Imm,  static DecodeStatus DecodeFixedPointScaleImm64(llvm::MCInst &Inst, unsigned Imm,                                                 uint64_t Address,                                                 const void *Decoder); -static DecodeStatus DecodeCondBranchTarget(llvm::MCInst &Inst, unsigned Imm, -                                           uint64_t Address, -                                           const void *Decoder); +static DecodeStatus DecodePCRelLabel19(llvm::MCInst &Inst, unsigned Imm, +                                       uint64_t Address, const void *Decoder);  static DecodeStatus DecodeMRSSystemRegister(llvm::MCInst &Inst, unsigned Imm,                                              uint64_t Address, const void *Decoder);  static DecodeStatus DecodeMSRSystemRegister(llvm::MCInst &Inst, unsigned Imm, @@ -582,8 +581,8 @@ static DecodeStatus DecodeFixedPointScaleImm64(llvm::MCInst &Inst, unsigned Imm,    return Success;  } -static DecodeStatus DecodeCondBranchTarget(llvm::MCInst &Inst, unsigned Imm, -                                           uint64_t Addr, const void *Decoder) { +static DecodeStatus DecodePCRelLabel19(llvm::MCInst &Inst, unsigned Imm, +                                       uint64_t Addr, const void *Decoder) {    int64_t ImmVal = Imm;    const ARM64Disassembler *Dis =        static_cast<const ARM64Disassembler *>(Decoder); diff --git a/llvm/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.cpp b/llvm/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.cpp index 28af3f01666..0dea241ed18 100644 --- a/llvm/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.cpp +++ b/llvm/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.cpp @@ -1422,9 +1422,8 @@ void ARM64InstPrinter::printVectorIndex(const MCInst *MI, unsigned OpNum,    O << "[" << MI->getOperand(OpNum).getImm() << "]";  } -void ARM64InstPrinter::printAlignedBranchTarget(const MCInst *MI, -                                                unsigned OpNum, -                                                raw_ostream &O) { +void ARM64InstPrinter::printAlignedLabel(const MCInst *MI, unsigned OpNum, +                                         raw_ostream &O) {    const MCOperand &Op = MI->getOperand(OpNum);    // If the label has already been resolved to an immediate offset (say, when diff --git a/llvm/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.h b/llvm/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.h index 778e8651b8f..7f2a9fe12a0 100644 --- a/llvm/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.h +++ b/llvm/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.h @@ -69,8 +69,7 @@ protected:    void printExtend(const MCInst *MI, unsigned OpNum, raw_ostream &O);    void printCondCode(const MCInst *MI, unsigned OpNum, raw_ostream &O);    void printDotCondCode(const MCInst *MI, unsigned OpNum, raw_ostream &O); -  void printAlignedBranchTarget(const MCInst *MI, unsigned OpNum, -                                raw_ostream &O); +  void printAlignedLabel(const MCInst *MI, unsigned OpNum, raw_ostream &O);    void printAMIndexed(const MCInst *MI, unsigned OpNum, unsigned Scale,                        raw_ostream &O);    void printAMIndexedWB(const MCInst *MI, unsigned OpNum, unsigned Scale, diff --git a/llvm/lib/Target/ARM64/MCTargetDesc/ARM64AsmBackend.cpp b/llvm/lib/Target/ARM64/MCTargetDesc/ARM64AsmBackend.cpp index 55ba91d7267..c9b95a2c163 100644 --- a/llvm/lib/Target/ARM64/MCTargetDesc/ARM64AsmBackend.cpp +++ b/llvm/lib/Target/ARM64/MCTargetDesc/ARM64AsmBackend.cpp @@ -45,9 +45,10 @@ public:        { "fixup_arm64_ldst_imm12_scale4", 10, 12, 0 },        { "fixup_arm64_ldst_imm12_scale8", 10, 12, 0 },        { "fixup_arm64_ldst_imm12_scale16", 10, 12, 0 }, +      { "fixup_arm64_ldr_pcrel_imm19", 5, 19, PCRelFlagVal },        { "fixup_arm64_movw", 5, 16, 0 },        { "fixup_arm64_pcrel_branch14", 5, 14, PCRelFlagVal }, -      { "fixup_arm64_pcrel_imm19", 5, 19, PCRelFlagVal }, +      { "fixup_arm64_pcrel_branch19", 5, 19, PCRelFlagVal },        { "fixup_arm64_pcrel_branch26", 0, 26, PCRelFlagVal },        { "fixup_arm64_pcrel_call26", 0, 26, PCRelFlagVal },        { "fixup_arm64_tlsdesc_call", 0, 0, 0 } @@ -101,7 +102,8 @@ static unsigned getFixupKindNumBytes(unsigned Kind) {    case ARM64::fixup_arm64_ldst_imm12_scale4:    case ARM64::fixup_arm64_ldst_imm12_scale8:    case ARM64::fixup_arm64_ldst_imm12_scale16: -  case ARM64::fixup_arm64_pcrel_imm19: +  case ARM64::fixup_arm64_ldr_pcrel_imm19: +  case ARM64::fixup_arm64_pcrel_branch19:      return 3;    case ARM64::fixup_arm64_pcrel_adr_imm21: @@ -133,7 +135,8 @@ static uint64_t adjustFixupValue(unsigned Kind, uint64_t Value) {      return AdrImmBits(Value & 0x1fffffULL);    case ARM64::fixup_arm64_pcrel_adrp_imm21:      return AdrImmBits((Value & 0x1fffff000ULL) >> 12); -  case ARM64::fixup_arm64_pcrel_imm19: +  case ARM64::fixup_arm64_ldr_pcrel_imm19: +  case ARM64::fixup_arm64_pcrel_branch19:      // Signed 21-bit immediate      if (SignedValue > 2097151 || SignedValue < -2097152)        report_fatal_error("fixup value out of range"); diff --git a/llvm/lib/Target/ARM64/MCTargetDesc/ARM64ELFObjectWriter.cpp b/llvm/lib/Target/ARM64/MCTargetDesc/ARM64ELFObjectWriter.cpp index fe3070c019e..718501f918e 100644 --- a/llvm/lib/Target/ARM64/MCTargetDesc/ARM64ELFObjectWriter.cpp +++ b/llvm/lib/Target/ARM64/MCTargetDesc/ARM64ELFObjectWriter.cpp @@ -82,11 +82,11 @@ unsigned ARM64ELFObjectWriter::GetRelocType(const MCValue &Target,        return ELF::R_AARCH64_JUMP26;      case ARM64::fixup_arm64_pcrel_call26:        return ELF::R_AARCH64_CALL26; -    case ARM64::fixup_arm64_pcrel_imm19: -      // A bit of an oddity here: shared by both "ldr x0, :gottprel:var" and -      // "b.eq var". +    case ARM64::fixup_arm64_ldr_pcrel_imm19:        if (SymLoc == ARM64MCExpr::VK_GOTTPREL)          return ELF::R_AARCH64_TLSIE_LD_GOTTPREL_PREL19; +      return ELF::R_AARCH64_LD_PREL_LO19; +    case ARM64::fixup_arm64_pcrel_branch19:        return ELF::R_AARCH64_CONDBR19;      default:        llvm_unreachable("Unsupported pc-relative fixup kind"); diff --git a/llvm/lib/Target/ARM64/MCTargetDesc/ARM64FixupKinds.h b/llvm/lib/Target/ARM64/MCTargetDesc/ARM64FixupKinds.h index 02eb91f805f..7106b314ea2 100644 --- a/llvm/lib/Target/ARM64/MCTargetDesc/ARM64FixupKinds.h +++ b/llvm/lib/Target/ARM64/MCTargetDesc/ARM64FixupKinds.h @@ -36,6 +36,11 @@ enum Fixups {    fixup_arm64_ldst_imm12_scale8,    fixup_arm64_ldst_imm12_scale16, +  // fixup_arm64_ldr_pcrel_imm19 - The high 19 bits of a 21-bit pc-relative +  // immediate. Same encoding as fixup_arm64_pcrel_adrhi, except this is used by +  // pc-relative loads and generates relocations directly when necessary. +  fixup_arm64_ldr_pcrel_imm19, +    // FIXME: comment    fixup_arm64_movw, @@ -43,11 +48,10 @@ enum Fixups {    // immediate.    fixup_arm64_pcrel_branch14, -  // fixup_arm64_pcrel_imm19 - The high 19 bits of a 21-bit pc-relative -  // immediate. Same encoding as fixup_arm64_pcrel_adrhi, except this -  // is not used as part of a lo/hi pair and thus generates relocations -  // directly when necessary. -  fixup_arm64_pcrel_imm19, +  // fixup_arm64_pcrel_branch19 - The high 19 bits of a 21-bit pc-relative +  // immediate. Same encoding as fixup_arm64_pcrel_adrhi, except this is use by +  // b.cc and generates relocations directly when necessary. +  fixup_arm64_pcrel_branch19,    // fixup_arm64_pcrel_branch26 - The high 26 bits of a 28-bit pc-relative    // immediate. diff --git a/llvm/lib/Target/ARM64/MCTargetDesc/ARM64MCCodeEmitter.cpp b/llvm/lib/Target/ARM64/MCTargetDesc/ARM64MCCodeEmitter.cpp index 85acdf31916..8910337d0d2 100644 --- a/llvm/lib/Target/ARM64/MCTargetDesc/ARM64MCCodeEmitter.cpp +++ b/llvm/lib/Target/ARM64/MCTargetDesc/ARM64MCCodeEmitter.cpp @@ -83,6 +83,12 @@ public:                                        SmallVectorImpl<MCFixup> &Fixups,                                        const MCSubtargetInfo &STI) const; +  /// getLoadLiteralOpValue - Return the encoded value for a load-literal +  /// pc-relative address. +  uint32_t getLoadLiteralOpValue(const MCInst &MI, unsigned OpIdx, +                                 SmallVectorImpl<MCFixup> &Fixups, +                                 const MCSubtargetInfo &STI) const; +    /// getTestBranchTargetOpValue - Return the encoded value for a test-bit-and-    /// branch target.    uint32_t getTestBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, @@ -305,7 +311,29 @@ uint32_t ARM64MCCodeEmitter::getCondBranchTargetOpValue(      return MO.getImm();    assert(MO.isExpr() && "Unexpected target type!"); -  MCFixupKind Kind = MCFixupKind(ARM64::fixup_arm64_pcrel_imm19); +  MCFixupKind Kind = MCFixupKind(ARM64::fixup_arm64_pcrel_branch19); +  Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc())); + +  ++MCNumFixups; + +  // All of the information is in the fixup. +  return 0; +} + +/// getLoadLiteralOpValue - Return the encoded value for a load-literal +/// pc-relative address. +uint32_t +ARM64MCCodeEmitter::getLoadLiteralOpValue(const MCInst &MI, unsigned OpIdx, +                                          SmallVectorImpl<MCFixup> &Fixups, +                                          const MCSubtargetInfo &STI) const { +  const MCOperand &MO = MI.getOperand(OpIdx); + +  // If the destination is an immediate, we have nothing to do. +  if (MO.isImm()) +    return MO.getImm(); +  assert(MO.isExpr() && "Unexpected target type!"); + +  MCFixupKind Kind = MCFixupKind(ARM64::fixup_arm64_ldr_pcrel_imm19);    Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc()));    ++MCNumFixups; diff --git a/llvm/lib/Target/ARM64/MCTargetDesc/ARM64MachObjectWriter.cpp b/llvm/lib/Target/ARM64/MCTargetDesc/ARM64MachObjectWriter.cpp index f28896c1f9e..1695b393055 100644 --- a/llvm/lib/Target/ARM64/MCTargetDesc/ARM64MachObjectWriter.cpp +++ b/llvm/lib/Target/ARM64/MCTargetDesc/ARM64MachObjectWriter.cpp @@ -136,14 +136,13 @@ void ARM64MachObjectWriter::RecordRelocation(    // ADRP fixups use relocations for the whole symbol value and only    // put the addend in the instruction itself. Clear out any value the    // generic code figured out from the sybmol definition. -  if (Kind == ARM64::fixup_arm64_pcrel_adrp_imm21 || -      Kind == ARM64::fixup_arm64_pcrel_imm19) +  if (Kind == ARM64::fixup_arm64_pcrel_adrp_imm21)      FixedValue = 0;    // imm19 relocations are for conditional branches, which require    // assembler local symbols. If we got here, that's not what we have,    // so complain loudly. -  if (Kind == ARM64::fixup_arm64_pcrel_imm19) { +  if (Kind == ARM64::fixup_arm64_pcrel_branch19) {      Asm.getContext().FatalError(Fixup.getLoc(),                                  "conditional branch requires assembler-local"                                  " label. '" + | 

