Index: lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp =================================================================== --- lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -310,12 +310,14 @@ return RISCVFPRndMode::stringToRoundingMode(Str) != RISCVFPRndMode::Invalid; } - bool isImmXLen() const { + bool isImmXLenLI() const { int64_t Imm; RISCVMCExpr::VariantKind VK; if (!isImm()) return false; bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); + if (VK == RISCVMCExpr::VK_RISCV_LO || VK == RISCVMCExpr::VK_RISCV_PCREL_LO) + return true; // Given only Imm, ensuring that the actually specified constant is either // a signed or unsigned 64-bit number is unfortunately impossible. bool IsInRange = isRV64() ? true : isInt<32>(Imm) || isUInt<32>(Imm); @@ -782,7 +784,7 @@ switch(Result) { default: break; - case Match_InvalidImmXLen: + case Match_InvalidImmXLenLI: if (isRV64()) { SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); return Error(ErrorLoc, "operand must be a constant 64-bit integer"); @@ -1449,7 +1451,17 @@ Inst.setLoc(IDLoc); if (Inst.getOpcode() == RISCV::PseudoLI) { - auto Reg = Inst.getOperand(0).getReg(); + unsigned Reg = Inst.getOperand(0).getReg(); + const MCOperand &Op1 = Inst.getOperand(1); + if (Op1.isExpr()) { + // We must have li reg, %lo(sym) or li reg, %pcrel_lo(sym) or similar. + // Just convert to an addi. This allows compatibility with gas. + emitToStreamer(Out, MCInstBuilder(RISCV::ADDI) + .addReg(Reg) + .addReg(RISCV::X0) + .addExpr(Op1.getExpr())); + return false; + } int64_t Imm = Inst.getOperand(1).getImm(); // On RV32 the immediate here can either be a signed or an unsigned // 32-bit number. Sign extension has to be performed to ensure that Imm Index: lib/Target/RISCV/RISCVInstrInfo.td =================================================================== --- lib/Target/RISCV/RISCVInstrInfo.td +++ lib/Target/RISCV/RISCVInstrInfo.td @@ -198,8 +198,10 @@ } // A parameterized register class alternative to i32imm/i64imm from Target.td. -def ixlenimm : Operand { - let ParserMatchClass = ImmXLenAsmOperand<"">; +def ixlenimm : Operand; + +def ixlenimm_li : Operand { + let ParserMatchClass = ImmXLenAsmOperand<"", "LI">; } // Standalone (codegen-only) immleaf patterns. @@ -497,7 +499,7 @@ // expanded to real instructions immediately. let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 32, isCodeGenOnly = 0, isAsmParserOnly = 1 in -def PseudoLI : Pseudo<(outs GPR:$rd), (ins ixlenimm:$imm), [], +def PseudoLI : Pseudo<(outs GPR:$rd), (ins ixlenimm_li:$imm), [], "li", "$rd, $imm">; def : InstAlias<"mv $rd, $rs", (ADDI GPR:$rd, GPR:$rs, 0)>; Index: test/MC/RISCV/rv32i-aliases-valid.s =================================================================== --- test/MC/RISCV/rv32i-aliases-valid.s +++ test/MC/RISCV/rv32i-aliases-valid.s @@ -3,10 +3,10 @@ # RUN: llvm-mc %s -triple=riscv32 \ # RUN: | FileCheck -check-prefixes=CHECK-EXPAND,CHECK-ALIAS %s # RUN: llvm-mc -filetype=obj -triple riscv32 < %s \ -# RUN: | llvm-objdump -riscv-no-aliases -d - \ -# RUN: | FileCheck -check-prefixes=CHECK-EXPAND,CHECK-INST %s +# RUN: | llvm-objdump -riscv-no-aliases -d -r - \ +# RUN: | FileCheck -check-prefixes=CHECK-OBJ-NOALIAS,CHECK-EXPAND,CHECK-INST %s # RUN: llvm-mc -filetype=obj -triple riscv32 < %s \ -# RUN: | llvm-objdump -d - \ +# RUN: | llvm-objdump -d -r - \ # RUN: | FileCheck -check-prefixes=CHECK-EXPAND,CHECK-ALIAS %s # The following check prefixes are used in this test: @@ -69,6 +69,19 @@ # CHECK-EXPAND: addi a2, zero, -1 li x12, 0xFFFFFFFF +# CHECK-EXPAND: addi a0, zero, 1110 +li a0, %lo(0x123456) +# CHECK-OBJ-NOALIAS: addi a0, zero, 0 +# CHECK-OBJ: R_RISCV_PCREL_LO12 +li a0, %pcrel_lo(0x123456) + +# CHECK-OBJ-NOALIAS: addi a0, zero, 0 +# CHECK-OBJ: R_RISCV_LO12 +li a0, %lo(foo) +# CHECK-OBJ-NOALIAS: addi a0, zero, 0 +# CHECK-OBJ: R_RISCV_PCREL_LO12 +li a0, %pcrel_lo(foo) + # CHECK-INST: csrrs t4, instreth, zero # CHECK-ALIAS: rdinstreth t4 rdinstreth x29 Index: test/MC/RISCV/rv64i-aliases-valid.s =================================================================== --- test/MC/RISCV/rv64i-aliases-valid.s +++ test/MC/RISCV/rv64i-aliases-valid.s @@ -4,7 +4,7 @@ # RUN: | FileCheck -check-prefixes=CHECK-EXPAND,CHECK-ALIAS %s # RUN: llvm-mc -filetype=obj -triple riscv64 < %s \ # RUN: | llvm-objdump -riscv-no-aliases -d - \ -# RUN: | FileCheck -check-prefixes=CHECK-EXPAND,CHECK-INST %s +# RUN: | FileCheck -check-prefixes=CHECK-OBJ-NOALIAS,CHECK-EXPAND,CHECK-INST %s # RUN: llvm-mc -filetype=obj -triple riscv64 < %s \ # RUN: | llvm-objdump -d - \ # RUN: | FileCheck -check-prefixes=CHECK-EXPAND,CHECK-ALIAS %s @@ -105,6 +105,19 @@ # CHECK-EXPAND: addi t5, zero, -1 li t5, 0xFFFFFFFFFFFFFFFF +# CHECK-EXPAND: addi a0, zero, 1110 +li a0, %lo(0x123456) +# CHECK-OBJ-NOALIAS: addi a0, zero, 0 +# CHECK-OBJ: R_RISCV_PCREL_LO12 +li a0, %pcrel_lo(0x123456) + +# CHECK-OBJ-NOALIAS: addi a0, zero, 0 +# CHECK-OBJ: R_RISCV_LO12 +li a0, %lo(foo) +# CHECK-OBJ-NOALIAS: addi a0, zero, 0 +# CHECK-OBJ: R_RISCV_PCREL_LO12 +li a0, %pcrel_lo(foo) + # CHECK-INST: subw t6, zero, ra # CHECK-ALIAS: negw t6, ra negw x31, x1