Index: lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp =================================================================== --- lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -39,6 +39,7 @@ #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCTargetOptions.h" #include "llvm/MC/SubtargetFeature.h" +#include "llvm/MC/MCValue.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" @@ -658,7 +659,7 @@ return DiagnosticPredicateTy::NearMatch; } - bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const { + bool isSymbolicUImm12Offset(const MCExpr *Expr) const { AArch64MCExpr::VariantKind ELFRefKind; MCSymbolRefExpr::VariantKind DarwinRefKind; int64_t Addend; @@ -683,7 +684,7 @@ // Note that we don't range-check the addend. It's adjusted modulo page // size when converted, so there is no "out of range" condition when using // @pageoff. - return Addend >= 0 && (Addend % Scale) == 0; + return true; } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) { // @gotpageoff/@tlvppageoff can only be used directly, not with an addend. @@ -699,7 +700,7 @@ const MCConstantExpr *MCE = dyn_cast(getImm()); if (!MCE) - return isSymbolicUImm12Offset(getImm(), Scale); + return isSymbolicUImm12Offset(getImm()); int64_t Val = MCE->getValue(); return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000; @@ -901,7 +902,7 @@ for (unsigned i = 0; i != AllowedModifiers.size(); ++i) { if (ELFRefKind == AllowedModifiers[i]) - return Addend == 0; + return true; } return false; @@ -5305,28 +5306,14 @@ return true; } - const MCBinaryExpr *BE = dyn_cast(Expr); - if (!BE) - return false; - - SE = dyn_cast(BE->getLHS()); - if (!SE) - return false; - DarwinRefKind = SE->getKind(); - - if (BE->getOpcode() != MCBinaryExpr::Add && - BE->getOpcode() != MCBinaryExpr::Sub) - return false; - - // See if the addend is a constant, otherwise there's more going - // on here than we can deal with. - auto AddendExpr = dyn_cast(BE->getRHS()); - if (!AddendExpr) + // Check that it looks like a symbol + an addend + MCValue Res; + bool Relocatable = Expr->evaluateAsRelocatable(Res, nullptr, nullptr); + if (!Relocatable || !Res.getSymA() || Res.getSymB()) return false; - Addend = AddendExpr->getValue(); - if (BE->getOpcode() == MCBinaryExpr::Sub) - Addend = -Addend; + DarwinRefKind = Res.getSymA()->getKind(); + Addend = Res.getConstant(); // It's some symbol reference + a constant addend, but really // shouldn't use both Darwin and ELF syntax. Index: test/MC/AArch64/adr-diagnostics.s =================================================================== --- /dev/null +++ test/MC/AArch64/adr-diagnostics.s @@ -0,0 +1,43 @@ +// RUN: not llvm-mc -triple aarch64-none-linux-gnu %s -filetype=obj -o /dev/null 2>&1 | FileCheck %s + + adr x0, -start +// CHECK: error: expected relocatable expression +// CHECK-NEXT: adr x0, -start +// CHECK-NEXT: ^ + adr x1, start * 10 +// CHECK: error: expected relocatable expression +// CHECK-NEXT: adr x1, start * 10 +// CHECK-NEXT: ^ + adr x2, 2 * (start + 987136) +// CHECK: error: expected relocatable expression +// CHECK-NEXT: adr x2, 2 * (start + 987136) +// CHECK-NEXT: ^ + adr x3, (end + start) +// CHECK: error: expected relocatable expression +// CHECK-NEXT: adr x3, (end + start) +// CHECK-NEXT: ^ + adr x4, #(end - start) +// CHECK: error: No relocation available to represent this relative expression +// CHECK-NEXT: adr x4, #(end - start) +// CHECK-NEXT: ^ + + adrp x0, -start +// CHECK: error: expected relocatable expression +// CHECK-NEXT: adrp x0, -start +// CHECK-NEXT: ^ + adrp x1, start * 10 +// CHECK: error: expected relocatable expression +// CHECK-NEXT: adrp x1, start * 10 +// CHECK-NEXT: ^ + adrp x2, 2 * (start + 987136) +// CHECK: error: expected relocatable expression +// CHECK-NEXT: adrp x2, 2 * (start + 987136) +// CHECK-NEXT: ^ + adrp x3, (end + start) +// CHECK: error: expected relocatable expression +// CHECK-NEXT: adrp x3, (end + start) +// CHECK-NEXT: ^ + adrp x4, #(end - start) +// CHECK: error: No relocation available to represent this relative expression +// CHECK-NEXT: adrp x4, #(end - start) +// CHECK-NEXT: ^ Index: test/MC/AArch64/adr.s =================================================================== --- /dev/null +++ test/MC/AArch64/adr.s @@ -0,0 +1,37 @@ +// RUN: llvm-mc -triple aarch64-elf -filetype=obj %s -o - | llvm-objdump -d -r - | FileCheck %s + + // CHECK: adr x0, #100 + // CHECK-NEXT: adr x2, #0 + // CHECK-NEXT: R_AARCH64_ADR_PREL_LO21 Symbol + // CHECK-NEXT: adr x3, #0 + // CHECK-NEXT: R_AARCH64_ADR_PREL_LO21 Symbol + // CHECK-NEXT: adr x4, #0 + // CHECK-NEXT: R_AARCH64_ADR_PREL_LO21 Symbol+987136 + // CHECK-NEXT: adr x5, #0 + // CHECK-NEXT: R_AARCH64_ADR_PREL_LO21 Symbol+987136 + // CHECK-NEXT: adr x6, #0 + // CHECK-NEXT: R_AARCH64_ADR_PREL_LO21 Symbol+987136 + + adr x0, 100 + adr x2, Symbol + adr x3, Symbol + 0 + adr x4, Symbol + 987136 + adr x5, (0xffffffff000f1000 - 0xffffffff00000000 + Symbol) + adr x6, Symbol + (0xffffffff000f1000 - 0xffffffff00000000) + + // CHECK-NEXT: adrp x0, #0 + // CHECK-NEXT: R_AARCH64_ADR_PREL_PG_HI21 Symbol + // CHECK-NEXT: adrp x2, #0 + // CHECK-NEXT: R_AARCH64_ADR_PREL_PG_HI21 Symbol + // CHECK-NEXT: adrp x3, #0 + // CHECK-NEXT: R_AARCH64_ADR_PREL_PG_HI21 Symbol+987136 + // CHECK-NEXT: adrp x4, #0 + // CHECK-NEXT: R_AARCH64_ADR_PREL_PG_HI21 Symbol+987136 + // CHECK-NEXT: adrp x5, #0 + // CHECK-NEXT: R_AARCH64_ADR_PREL_PG_HI21 Symbol+987136 + + adrp x0, Symbol + adrp x2, Symbol + 0 + adrp x3, Symbol + 987136 + adrp x4, (0xffffffff000f1000 - 0xffffffff00000000 + Symbol) + adrp x5, Symbol + (0xffffffff000f1000 - 0xffffffff00000000) Index: test/MC/AArch64/arm64-elf-relocs.s =================================================================== --- test/MC/AArch64/arm64-elf-relocs.s +++ test/MC/AArch64/arm64-elf-relocs.s @@ -6,82 +6,88 @@ // RUN: FileCheck %s --check-prefix=CHECK-OBJ-LP64 add x0, x2, #:lo12:sym + add x0, x2, #:lo12:sym+12 + add x0, x2, #:lo12:sym-3 // CHECK: add x0, x2, :lo12:sym +// CHECK: add x0, x2, :lo12:sym+12 +// CHECK: add x0, x2, :lo12:sym-3 // CHECK-OBJ-LP64: 0 R_AARCH64_ADD_ABS_LO12_NC sym +// CHECK-OBJ-LP64: 4 R_AARCH64_ADD_ABS_LO12_NC sym+12 +// CHECK-OBJ-LP64: 8 R_AARCH64_ADD_ABS_LO12_NC sym-3 add x5, x7, #:dtprel_lo12:sym // CHECK: add x5, x7, :dtprel_lo12:sym -// CHECK-OBJ-LP64: 4 R_AARCH64_TLSLD_ADD_DTPREL_LO12 sym +// CHECK-OBJ-LP64: c R_AARCH64_TLSLD_ADD_DTPREL_LO12 sym add x9, x12, #:dtprel_lo12_nc:sym // CHECK: add x9, x12, :dtprel_lo12_nc:sym -// CHECK-OBJ-LP64: 8 R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC sym +// CHECK-OBJ-LP64: 10 R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC sym add x20, x30, #:tprel_lo12:sym // CHECK: add x20, x30, :tprel_lo12:sym -// CHECK-OBJ-LP64: c R_AARCH64_TLSLE_ADD_TPREL_LO12 sym +// CHECK-OBJ-LP64: 14 R_AARCH64_TLSLE_ADD_TPREL_LO12 sym add x9, x12, #:tprel_lo12_nc:sym // CHECK: add x9, x12, :tprel_lo12_nc:sym -// CHECK-OBJ-LP64: 10 R_AARCH64_TLSLE_ADD_TPREL_LO12_NC sym +// CHECK-OBJ-LP64: 18 R_AARCH64_TLSLE_ADD_TPREL_LO12_NC sym add x5, x0, #:tlsdesc_lo12:sym // CHECK: add x5, x0, :tlsdesc_lo12:sym -// CHECK-OBJ-LP64: 14 R_AARCH64_TLSDESC_ADD_LO12 sym +// CHECK-OBJ-LP64: 1c R_AARCH64_TLSDESC_ADD_LO12 sym add x0, x2, #:lo12:sym+8 // CHECK: add x0, x2, :lo12:sym -// CHECK-OBJ-LP64: 18 R_AARCH64_ADD_ABS_LO12_NC sym+8 +// CHECK-OBJ-LP64: 20 R_AARCH64_ADD_ABS_LO12_NC sym+8 add x5, x7, #:dtprel_lo12:sym+1 // CHECK: add x5, x7, :dtprel_lo12:sym+1 -// CHECK-OBJ-LP64: 1c R_AARCH64_TLSLD_ADD_DTPREL_LO12 sym+1 +// CHECK-OBJ-LP64: 24 R_AARCH64_TLSLD_ADD_DTPREL_LO12 sym+1 add x9, x12, #:dtprel_lo12_nc:sym+2 // CHECK: add x9, x12, :dtprel_lo12_nc:sym+2 -// CHECK-OBJ-LP64:20 R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC sym+2 +// CHECK-OBJ-LP64: 28 R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC sym+2 add x20, x30, #:tprel_lo12:sym+12 // CHECK: add x20, x30, :tprel_lo12:sym+12 -// CHECK-OBJ-LP64: 24 R_AARCH64_TLSLE_ADD_TPREL_LO12 sym+12 +// CHECK-OBJ-LP64: 2c R_AARCH64_TLSLE_ADD_TPREL_LO12 sym+12 add x9, x12, #:tprel_lo12_nc:sym+54 // CHECK: add x9, x12, :tprel_lo12_nc:sym+54 -// CHECK-OBJ-LP64: 28 R_AARCH64_TLSLE_ADD_TPREL_LO12_NC sym+54 +// CHECK-OBJ-LP64: 30 R_AARCH64_TLSLE_ADD_TPREL_LO12_NC sym+54 add x5, x0, #:tlsdesc_lo12:sym+70 // CHECK: add x5, x0, :tlsdesc_lo12:sym+70 -// CHECK-OBJ-LP64: 2c R_AARCH64_TLSDESC_ADD_LO12 sym+70 +// CHECK-OBJ-LP64: 34 R_AARCH64_TLSDESC_ADD_LO12 sym+70 .hword sym + 4 - . -// CHECK-OBJ-LP64: 30 R_AARCH64_PREL16 sym+4 +// CHECK-OBJ-LP64: 38 R_AARCH64_PREL16 sym+4 .word sym - . + 8 -// CHECK-OBJ-LP64: 32 R_AARCH64_PREL32 sym+8 +// CHECK-OBJ-LP64: 3a R_AARCH64_PREL32 sym+8 .xword sym-. -// CHECK-OBJ-LP64: 36 R_AARCH64_PREL64 sym{{$}} +// CHECK-OBJ-LP64: 3e R_AARCH64_PREL64 sym{{$}} .hword sym -// CHECK-OBJ-LP64: 3e R_AARCH64_ABS16 sym +// CHECK-OBJ-LP64: 46 R_AARCH64_ABS16 sym .word sym+1 -// CHECK-OBJ-LP64: 40 R_AARCH64_ABS32 sym+1 +// CHECK-OBJ-LP64: 48 R_AARCH64_ABS32 sym+1 .xword sym+16 -// CHECK-OBJ-LP64: 44 R_AARCH64_ABS64 sym+16 +// CHECK-OBJ-LP64: 4c R_AARCH64_ABS64 sym+16 adrp x0, sym // CHECK: adrp x0, sym -// CHECK-OBJ-LP64: 4c R_AARCH64_ADR_PREL_PG_HI21 sym +// CHECK-OBJ-LP64: 54 R_AARCH64_ADR_PREL_PG_HI21 sym adrp x15, :got:sym // CHECK: adrp x15, :got:sym -// CHECK-OBJ-LP64: 50 R_AARCH64_ADR_GOT_PAGE sym +// CHECK-OBJ-LP64: 58 R_AARCH64_ADR_GOT_PAGE sym adrp x29, :gottprel:sym // CHECK: adrp x29, :gottprel:sym -// CHECK-OBJ-LP64: 54 R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 sym +// CHECK-OBJ-LP64: 5c R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 sym adrp x2, :tlsdesc:sym // CHECK: adrp x2, :tlsdesc:sym -// CHECK-OBJ-LP64: 58 R_AARCH64_TLSDESC_ADR_PAGE21 sym +// CHECK-OBJ-LP64: 60 R_AARCH64_TLSDESC_ADR_PAGE21 sym // LLVM is not competent enough to do this relocation because the // page boundary could occur anywhere after linking. A relocation @@ -90,33 +96,45 @@ .global trickQuestion trickQuestion: // CHECK: adrp x3, trickQuestion -// CHECK-OBJ-LP64: 5c R_AARCH64_ADR_PREL_PG_HI21 trickQuestion +// CHECK-OBJ-LP64: 64 R_AARCH64_ADR_PREL_PG_HI21 trickQuestion ldrb w2, [x3, :lo12:sym] ldrsb w5, [x7, #:lo12:sym] ldrsb x11, [x13, :lo12:sym] ldr b17, [x19, #:lo12:sym] + ldrb w2, [x3, :lo12:sym+15] + ldrsb w5, [x7, #:lo12:sym-2] + ldr b17, [x19, #:lo12:sym+4] // CHECK: ldrb w2, [x3, :lo12:sym] // CHECK: ldrsb w5, [x7, :lo12:sym] // CHECK: ldrsb x11, [x13, :lo12:sym] // CHECK: ldr b17, [x19, :lo12:sym] +// CHECK: ldrb w2, [x3, :lo12:sym+15] +// CHECK: ldrsb w5, [x7, :lo12:sym-2] +// CHECK: ldr b17, [x19, :lo12:sym+4] // CHECK-OBJ-LP64: R_AARCH64_LDST8_ABS_LO12_NC sym // CHECK-OBJ-LP64: R_AARCH64_LDST8_ABS_LO12_NC sym // CHECK-OBJ-LP64: R_AARCH64_LDST8_ABS_LO12_NC sym // CHECK-OBJ-LP64: R_AARCH64_LDST8_ABS_LO12_NC sym +// CHECK-OBJ-LP64: R_AARCH64_LDST8_ABS_LO12_NC sym+15 +// CHECK-OBJ-LP64: R_AARCH64_LDST8_ABS_LO12_NC sym-2 +// CHECK-OBJ-LP64: R_AARCH64_LDST8_ABS_LO12_NC sym+4 ldrb w23, [x29, #:dtprel_lo12_nc:sym] ldrsb w23, [x19, #:dtprel_lo12:sym] ldrsb x17, [x13, :dtprel_lo12_nc:sym] ldr b11, [x7, #:dtprel_lo12:sym] + ldrb w23, [x29, #:dtprel_lo12_nc:sym+2] // CHECK: ldrb w23, [x29, :dtprel_lo12_nc:sym] // CHECK: ldrsb w23, [x19, :dtprel_lo12:sym] // CHECK: ldrsb x17, [x13, :dtprel_lo12_nc:sym] // CHECK: ldr b11, [x7, :dtprel_lo12:sym] +// CHECK: ldrb w23, [x29, :dtprel_lo12_nc:sym+2] // CHECK-OBJ-LP64: R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC sym // CHECK-OBJ-LP64: R_AARCH64_TLSLD_LDST8_DTPREL_LO12 sym // CHECK-OBJ-LP64: R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC sym // CHECK-OBJ-LP64: R_AARCH64_TLSLD_LDST8_DTPREL_LO12 sym +// CHECK-OBJ-LP64: R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC sym+2 ldrb w1, [x2, :tprel_lo12:sym] ldrsb w3, [x4, #:tprel_lo12_nc:sym] @@ -135,14 +153,17 @@ ldrsh w5, [x7, :lo12:sym] ldrsh x11, [x13, #:lo12:sym] ldr h17, [x19, :lo12:sym] + ldrh w2, [x3, #:lo12:sym+4] // CHECK: ldrh w2, [x3, :lo12:sym] // CHECK: ldrsh w5, [x7, :lo12:sym] // CHECK: ldrsh x11, [x13, :lo12:sym] // CHECK: ldr h17, [x19, :lo12:sym] +// CHECK: ldrh w2, [x3, :lo12:sym+4] // CHECK-OBJ-LP64: R_AARCH64_LDST16_ABS_LO12_NC sym // CHECK-OBJ-LP64: R_AARCH64_LDST16_ABS_LO12_NC sym // CHECK-OBJ-LP64: R_AARCH64_LDST16_ABS_LO12_NC sym // CHECK-OBJ-LP64: R_AARCH64_LDST16_ABS_LO12_NC sym +// CHECK-OBJ-LP64: R_AARCH64_LDST16_ABS_LO12_NC sym+4 ldrh w23, [x29, #:dtprel_lo12_nc:sym] ldrsh w23, [x19, :dtprel_lo12:sym] @@ -203,17 +224,26 @@ ldr x28, [x27, :lo12:sym] ldr d26, [x25, #:lo12:sym] + ldr x28, [x27, :lo12:sym+10] + ldr x28, [x27, :lo12:sym-15] // CHECK: ldr x28, [x27, :lo12:sym] // CHECK: ldr d26, [x25, :lo12:sym] +// CHECK: ldr x28, [x27, :lo12:sym+10] +// CHECK: ldr x28, [x27, :lo12:sym-15] // CHECK-OBJ-LP64: R_AARCH64_LDST64_ABS_LO12_NC sym // CHECK-OBJ-LP64: R_AARCH64_LDST64_ABS_LO12_NC sym +// CHECK-OBJ-LP64: R_AARCH64_LDST64_ABS_LO12_NC sym+10 +// CHECK-OBJ-LP64: R_AARCH64_LDST64_ABS_LO12_NC sym-15 ldr x24, [x23, #:got_lo12:sym] ldr d22, [x21, :got_lo12:sym] + ldr x24, [x23, :got_lo12:sym+7] // CHECK: ldr x24, [x23, :got_lo12:sym] // CHECK: ldr d22, [x21, :got_lo12:sym] +// CHECK: ldr x24, [x23, :got_lo12:sym+7] // CHECK-OBJ-LP64: R_AARCH64_LD64_GOT_LO12_NC sym // CHECK-OBJ-LP64: R_AARCH64_LD64_GOT_LO12_NC sym +// CHECK-OBJ-LP64: R_AARCH64_LD64_GOT_LO12_NC sym+7 ldr x24, [x23, :dtprel_lo12_nc:sym] ldr d22, [x21, #:dtprel_lo12:sym] Index: test/MC/AArch64/basic-a64-diagnostics.s =================================================================== --- test/MC/AArch64/basic-a64-diagnostics.s +++ test/MC/AArch64/basic-a64-diagnostics.s @@ -180,6 +180,12 @@ // CHECK-ERROR-NEXT: add x3, x9, #variable-16 // CHECK-ERROR-NEXT: ^ + // Relocation on a sub + sub x1, x0, :lo12:loc +// CHECK-ERROR: error: invalid immediate expression +// CHECK-ERROR: sub x1, x0, :lo12:loc +// CHECK-ERROR: ^ + //------------------------------------------------------------------------------ @@ -3316,6 +3322,7 @@ adr sp, loc // expects xzr adr x0, :got:loc // bad relocation type + adr x1, :lo12:loc adrp x3, #20 // Immediate unaligned adrp w2, loc // 64-bit register needed adrp x5, :got_lo12:loc // bad relocation type @@ -3325,6 +3332,9 @@ // CHECK-ERROR-NEXT: error: unexpected adr label // CHECK-ERROR-NEXT: adr x0, :got:loc // CHECK-ERROR-NEXT: ^ +// CHECK-ERROR-NEXT: error: unexpected adr label +// CHECK-ERROR-NEXT: adr x1, :lo12:loc +// CHECK-ERROR-NEXT: ^ // CHECK-ERROR-NEXT: error: expected label or encodable integer pc offset // CHECK-ERROR-NEXT: adrp x3, #20 // CHECK-ERROR-NEXT: ^ Index: test/MC/AArch64/elf-reloc-movw.s =================================================================== --- test/MC/AArch64/elf-reloc-movw.s +++ test/MC/AArch64/elf-reloc-movw.s @@ -22,6 +22,10 @@ movz x19, #:abs_g2_s:some_label movn x19, #:abs_g2_s:some_label + movz x19, #:abs_g1:some_label + 20 - 10 + movn x19, #:abs_g2_s:some_label - 20 + 10 + movk x11, #:abs_g3:some_label + 2 * 10 + // OBJ: Relocations [ // OBJ-NEXT: Section {{.*}} .rela.text { // OBJ-NEXT: 0x0 R_AARCH64_MOVW_UABS_G0 some_label 0x0 @@ -38,5 +42,8 @@ // OBJ-NEXT: 0x2C R_AARCH64_MOVW_SABS_G1 some_label 0x0 // OBJ-NEXT: 0x30 R_AARCH64_MOVW_SABS_G2 some_label 0x0 // OBJ-NEXT: 0x34 R_AARCH64_MOVW_SABS_G2 some_label 0x0 +// OBJ-NEXT: 0x38 R_AARCH64_MOVW_UABS_G1 some_label 0xA +// OBJ-NEXT: 0x3C R_AARCH64_MOVW_SABS_G2 some_label 0xFFFFFFFFFFFFFFF6 +// OBJ-NEXT: 0x40 R_AARCH64_MOVW_UABS_G3 some_label 0x14 // OBJ-NEXT: } // OBJ-NEXT: ] Index: test/MC/AArch64/label-arithmetic-elf.s =================================================================== --- test/MC/AArch64/label-arithmetic-elf.s +++ test/MC/AArch64/label-arithmetic-elf.s @@ -13,6 +13,7 @@ cmp x0, #(end - start) sub w0, w1, #(end - start) sub x0, x1, #(end - start) + // FIXME: adr x1, #(end - start) // This could be supported, but currently doesn't work // CHECK: adds w0, w1, #8 // CHECK: adds x0, x1, #8 // CHECK: add w0, w1, #8 @@ -21,6 +22,7 @@ // CHECK: cmp x0, #8 // CHECK: sub w0, w1, #8 // CHECK: sub x0, x1, #8 + // FIXME: adr x1, #8 add w0, w1, #(end - start), lsl #12 cmp w0, #(end - start), lsl #12