Index: lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp =================================================================== --- lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -453,20 +453,36 @@ VK == RISCVMCExpr::VK_RISCV_None; } - bool isUImm20() const { + bool isUImm20LUI() const { RISCVMCExpr::VariantKind VK; int64_t Imm; bool IsValid; if (!isImm()) return false; bool IsConstantImm = evaluateConstantImm(Imm, VK); - if (!IsConstantImm) + if (!IsConstantImm) { IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm); - else - IsValid = isUInt<20>(Imm); - return IsValid && (VK == RISCVMCExpr::VK_RISCV_None || - VK == RISCVMCExpr::VK_RISCV_HI || - VK == RISCVMCExpr::VK_RISCV_PCREL_HI); + return IsValid && VK == RISCVMCExpr::VK_RISCV_HI; + } else { + return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None || + VK == RISCVMCExpr::VK_RISCV_HI); + } + } + + bool isUImm20AUIPC() const { + RISCVMCExpr::VariantKind VK; + int64_t Imm; + bool IsValid; + if (!isImm()) + return false; + bool IsConstantImm = evaluateConstantImm(Imm, VK); + if (!IsConstantImm) { + IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm); + return IsValid && VK == RISCVMCExpr::VK_RISCV_PCREL_HI; + } else { + return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None || + VK == RISCVMCExpr::VK_RISCV_PCREL_HI); + } } bool isSImm21Lsb0() const { return isBareSimmNLsb0<21>(); } @@ -791,8 +807,15 @@ return generateImmOutOfRangeError( Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2, "immediate must be a multiple of 2 bytes in the range"); - case Match_InvalidUImm20: - return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1); + case Match_InvalidUImm20LUI: + return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1, + "operand must be a symbol with %hi() " + "modifier or an integer in the range"); + case Match_InvalidUImm20AUIPC: + return generateImmOutOfRangeError( + Operands, ErrorInfo, 0, (1 << 20) - 1, + "operand must be a symbol with %pcrel_hi() modifier or an integer in " + "the range"); case Match_InvalidSImm21Lsb0: return generateImmOutOfRangeError( Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2, Index: lib/Target/RISCV/RISCVInstrInfo.td =================================================================== --- lib/Target/RISCV/RISCVInstrInfo.td +++ lib/Target/RISCV/RISCVInstrInfo.td @@ -143,8 +143,7 @@ }]; } -def uimm20 : Operand { - let ParserMatchClass = UImmAsmOperand<20>; +class UImm20Operand : Operand { let EncoderMethod = "getImmOpValue"; let DecoderMethod = "decodeUImmOperand<20>"; let MCOperandPredicate = [{ @@ -155,6 +154,13 @@ }]; } +def uimm20_lui : UImm20Operand { + let ParserMatchClass = UImmAsmOperand<20, "LUI">; +} +def uimm20_auipc : UImm20Operand { + let ParserMatchClass = UImmAsmOperand<20, "AUIPC">; +} + // A 21-bit signed immediate where the least significant bit is zero. def simm21_lsb0 : Operand { let ParserMatchClass = SImmAsmOperand<21, "Lsb0">; @@ -285,10 +291,10 @@ //===----------------------------------------------------------------------===// let hasSideEffects = 0, isReMaterializable = 1, mayLoad = 0, mayStore = 0 in { -def LUI : RVInstU; -def AUIPC : RVInstU; let isCall = 1 in Index: test/MC/RISCV/rv32i-invalid.s =================================================================== --- test/MC/RISCV/rv32i-invalid.s +++ test/MC/RISCV/rv32i-invalid.s @@ -37,9 +37,9 @@ bgeu t0, t1, -13 # CHECK: :[[@LINE]]:14: error: immediate must be a multiple of 2 bytes in the range [-4096, 4094] ## uimm20 -lui a0, -1 # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [0, 1048575] -lui s0, 1048576 # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [0, 1048575] -auipc zero, -0xf # CHECK: :[[@LINE]]:13: error: immediate must be an integer in the range [0, 1048575] +lui a0, -1 # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575] +lui s0, 1048576 # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575] +auipc zero, -0xf # CHECK: :[[@LINE]]:13: error: operand must be a symbol with %pcrel_hi() modifier or an integer in the range [0, 1048575] ## simm21_lsb0 jal gp, -1048578 # CHECK: :[[@LINE]]:9: error: immediate must be a multiple of 2 bytes in the range [-1048576, 1048574] @@ -92,8 +92,8 @@ bgeu t0, t1, %pcrel_lo(d) # CHECK: :[[@LINE]]:14: error: immediate must be a multiple of 2 bytes in the range [-4096, 4094] ## uimm20 -lui a0, %lo(1) # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [0, 1048575] -auipc a1, %lo(foo) # CHECK: :[[@LINE]]:11: error: immediate must be an integer in the range [0, 1048575] +lui a0, %lo(1) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575] +auipc a1, %lo(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi() modifier or an integer in the range [0, 1048575] ## simm21_lsb0 jal gp, %lo(1) # CHECK: :[[@LINE]]:9: error: immediate must be a multiple of 2 bytes in the range [-1048576, 1048574] @@ -105,6 +105,19 @@ jal gp, %pcrel_lo(4) # CHECK: :[[@LINE]]:9: error: immediate must be a multiple of 2 bytes in the range [-1048576, 1048574] jal gp, %pcrel_lo(d) # CHECK: :[[@LINE]]:9: error: immediate must be a multiple of 2 bytes in the range [-1048576, 1048574] +# Bare symbol names when an operand modifier is required and unsupported +# operand modifiers. + +lui a0, foo # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575] +lui a0, %lo(foo) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575] +lui a0, %pcrel_lo(foo) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575] +lui a0, %pcrel_hi(foo) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575] + +auipc a0, foo # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi() modifier or an integer in the range [0, 1048575] +auipc a0, %lo(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi() modifier or an integer in the range [0, 1048575] +auipc a0, %hi(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi() modifier or an integer in the range [0, 1048575] +auipc a0, %pcrel_lo(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi() modifier or an integer in the range [0, 1048575] + # Unrecognized operand modifier addi t0, sp, %modifer(255) # CHECK: :[[@LINE]]:15: error: unrecognized operand modifier Index: test/MC/RISCV/rv32i-valid.s =================================================================== --- test/MC/RISCV/rv32i-valid.s +++ test/MC/RISCV/rv32i-valid.s @@ -30,6 +30,11 @@ # CHECK-ASM-AND-OBJ: lui gp, 0 # CHECK-ASM: encoding: [0xb7,0x01,0x00,0x00] lui gp, 0 +# CHECK-ASM: lui a0, %hi(foo) +# CHECK-ASM: encoding: [0x37,0bAAAA0101,A,A] +# CHECK-OBJ: lui a0, 0 +# CHECK-OBJ: R_RISCV_HI20 foo +lui a0, %hi(foo) # CHECK-ASM-AND-OBJ: auipc a0, 2 # CHECK-ASM: encoding: [0x17,0x25,0x00,0x00] @@ -43,6 +48,11 @@ # CHECK-ASM-AND-OBJ: auipc gp, 0 # CHECK-ASM: encoding: [0x97,0x01,0x00,0x00] auipc gp, 0 +# CHECK-ASM: auipc a0, %pcrel_hi(foo) +# CHECK-ASM: encoding: [0x17,0bAAAA0101,A,A] +# CHECK-OBJ: auipc a0, 0 +# CHECK-OBJ: R_RISCV_PCREL_HI20 foo +auipc a0, %pcrel_hi(foo) # CHECK-ASM-AND-OBJ: jal a2, 1048574 # CHECK-ASM: encoding: [0x6f,0xf6,0xff,0x7f]