Index: lib/Basic/Targets/RISCV.h =================================================================== --- lib/Basic/Targets/RISCV.h +++ lib/Basic/Targets/RISCV.h @@ -61,9 +61,7 @@ ArrayRef getGCCRegAliases() const override; bool validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &Info) const override { - return false; - } + TargetInfo::ConstraintInfo &Info) const override; bool hasFeature(StringRef Feature) const override; Index: lib/Basic/Targets/RISCV.cpp =================================================================== --- lib/Basic/Targets/RISCV.cpp +++ lib/Basic/Targets/RISCV.cpp @@ -39,6 +39,26 @@ return llvm::makeArrayRef(GCCRegAliases); } +bool RISCVTargetInfo::validateAsmConstraint( + const char *&Name, TargetInfo::ConstraintInfo &Info) const { + switch (*Name) { + default: + return false; + case 'I': + // A 12-bit signed immediate. + Info.setRequiresImmediate(-2048, 2047); + return true; + case 'J': + // Integer zero. + Info.setRequiresImmediate(0); + return true; + case 'K': + // A 5-bit unsigned immediate for CSR access instructions. + Info.setRequiresImmediate(0, 31); + return true; + } +} + void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { Builder.defineMacro("__ELF__"); Index: test/CodeGen/riscv-inline-asm.c =================================================================== --- /dev/null +++ test/CodeGen/riscv-inline-asm.c @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -triple riscv32 -O2 -emit-llvm %s -o - \ +// RUN: | FileCheck %s +// RUN: %clang_cc1 -triple riscv64 -O2 -emit-llvm %s -o - \ +// RUN: | FileCheck %s + +// Test RISC-V specific inline assembly constraints. + +void test_I() { +// CHECK-LABEL: define void @test_I() +// CHECK: call void asm sideeffect "", "I"(i32 2047) + asm volatile ("" :: "I"(2047)); +// CHECK: call void asm sideeffect "", "I"(i32 -2048) + asm volatile ("" :: "I"(-2048)); +} + +void test_J() { +// CHECK-LABEL: define void @test_J() +// CHECK: call void asm sideeffect "", "J"(i32 0) + asm volatile ("" :: "J"(0)); +} + +void test_K() { +// CHECK-LABEL: define void @test_K() +// CHECK: call void asm sideeffect "", "K"(i32 31) + asm volatile ("" :: "K"(31)); +// CHECK: call void asm sideeffect "", "K"(i32 0) + asm volatile ("" :: "K"(0)); +} Index: test/Sema/inline-asm-validate-riscv.c =================================================================== --- /dev/null +++ test/Sema/inline-asm-validate-riscv.c @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -triple riscv32 -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple riscv64 -fsyntax-only -verify %s + +void I(int i) { + static const int BelowMin = -2049; + static const int AboveMax = 2048; + asm volatile ("" :: "I"(i)); // expected-error{{constraint 'I' expects an integer constant expression}} + asm volatile ("" :: "I"(BelowMin)); // expected-error{{value '-2049' out of range for constraint 'I'}} + asm volatile ("" :: "I"(AboveMax)); // expected-error{{value '2048' out of range for constraint 'I'}} +} + +void J(int j) { + static const int BelowMin = -1; + static const int AboveMax = 1; + asm volatile ("" :: "J"(j)); // expected-error{{constraint 'J' expects an integer constant expression}} + asm volatile ("" :: "J"(BelowMin)); // expected-error{{value '-1' out of range for constraint 'J'}} + asm volatile ("" :: "J"(AboveMax)); // expected-error{{value '1' out of range for constraint 'J'}} +} + +void K(int k) { + static const int BelowMin = -1; + static const int AboveMax = 32; + asm volatile ("" :: "K"(k)); // expected-error{{constraint 'K' expects an integer constant expression}} + asm volatile ("" :: "K"(BelowMin)); // expected-error{{value '-1' out of range for constraint 'K'}} + asm volatile ("" :: "K"(AboveMax)); // expected-error{{value '32' out of range for constraint 'K'}} +}