Index: lib/Target/RISCV/RISCVAsmPrinter.cpp =================================================================== --- lib/Target/RISCV/RISCVAsmPrinter.cpp +++ lib/Target/RISCV/RISCVAsmPrinter.cpp @@ -123,7 +123,7 @@ if (!MO.isReg()) return true; - OS << "0(" << RISCVInstPrinter::getRegisterName(MO.getReg()) << ")"; + OS << "(" << RISCVInstPrinter::getRegisterName(MO.getReg()) << ")"; return false; } Index: lib/Target/RISCV/RISCVISelLowering.h =================================================================== --- lib/Target/RISCV/RISCVISelLowering.h +++ lib/Target/RISCV/RISCVISelLowering.h @@ -87,6 +87,11 @@ // This method returns the name of a target specific DAG node. const char *getTargetNodeName(unsigned Opcode) const override; + // Get the type of an inline asm constraint. + ConstraintType getConstraintType(StringRef Constraint) const override; + + unsigned getInlineAsmMemConstraint(StringRef ConstraintCode) const override; + std::pair getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override; Index: lib/Target/RISCV/RISCVISelLowering.cpp =================================================================== --- lib/Target/RISCV/RISCVISelLowering.cpp +++ lib/Target/RISCV/RISCVISelLowering.cpp @@ -1839,6 +1839,21 @@ return nullptr; } +RISCVTargetLowering::ConstraintType +RISCVTargetLowering::getConstraintType(StringRef Constraint) const { + // Currently only support length 1 constraints. + if (Constraint.size() == 1) { + switch (Constraint[0]) { + case 'A': + return C_Memory; + default: + break; + } + } + + return TargetLowering::getConstraintType(Constraint); +} + std::pair RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, @@ -1857,6 +1872,21 @@ return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT); } +unsigned +RISCVTargetLowering::getInlineAsmMemConstraint(StringRef ConstraintCode) const { + // Currently only support length 1 constraints. + if (ConstraintCode.size() == 1) { + switch (ConstraintCode[0]) { + case 'A': + return InlineAsm::Constraint_m; + default: + break; + } + } + + return TargetLowering::getInlineAsmMemConstraint(ConstraintCode); +} + void RISCVTargetLowering::LowerAsmOperandForConstraint( SDValue Op, std::string &Constraint, std::vector &Ops, SelectionDAG &DAG) const { Index: test/CodeGen/RISCV/inline-asm.ll =================================================================== --- test/CodeGen/RISCV/inline-asm.ll +++ test/CodeGen/RISCV/inline-asm.ll @@ -44,7 +44,7 @@ ; RV32I-LABEL: constraint_m2: ; RV32I: # %bb.0: ; RV32I-NEXT: #APP -; RV32I-NEXT: lw a0, 0(a0) +; RV32I-NEXT: lw a0, (a0) ; RV32I-NEXT: #NO_APP ; RV32I-NEXT: ret %1 = tail call i32 asm "lw $0, $1", "=r,*m"(i32* %a) nounwind @@ -92,4 +92,19 @@ ret void } +define void @constraint_A(i8* %a) { +; RV32I-LABEL: constraint_A: +; RV32I: # %bb.0: +; RV32I-NEXT: #APP +; RV32I-NEXT: sb s0, (a0) +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: #APP +; RV32I-NEXT: lb s1, (a0) +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret + tail call void asm sideeffect "sb s0, $0", "*A"(i8* %a) + tail call void asm sideeffect "lb s1, $0", "*A"(i8* %a) + ret void +} + ; TODO: expend tests for more complex constraints, out of range immediates etc