diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -11267,4 +11267,6 @@ // RISC-V builtin required extension warning def err_riscv_builtin_requires_extension : Error< "builtin requires '%0' extension support to be enabled">; +def err_riscv_builtin_invalid_lmul : Error< + "LMUL argument must be in the range [0,3] or [5,7]">; } // end of sema component. diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -12539,6 +12539,7 @@ bool CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall); bool CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + bool CheckRISCVLMUL(CallExpr *TheCall, unsigned ArgNum); bool CheckRISCVBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -3417,6 +3417,26 @@ return false; } +bool Sema::CheckRISCVLMUL(CallExpr *TheCall, unsigned ArgNum) { + llvm::APSInt Result; + + // We can't check the value of a dependent argument. + Expr *Arg = TheCall->getArg(ArgNum); + if (Arg->isTypeDependent() || Arg->isValueDependent()) + return false; + + // Check constant-ness first. + if (SemaBuiltinConstantArg(TheCall, ArgNum, Result)) + return true; + + int64_t Val = Result.getSExtValue(); + if ((Val >= 0 && Val <= 3) || (Val >= 5 && Val <= 7)) + return false; + + return Diag(TheCall->getBeginLoc(), diag::err_riscv_builtin_invalid_lmul) + << Arg->getSourceRange(); +} + bool Sema::CheckRISCVBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall) { @@ -3448,7 +3468,19 @@ << TheCall->getSourceRange() << StringRef(FeatureStr); } - return FeatureMissing; + if (FeatureMissing) + return true; + + switch (BuiltinID) { + case RISCV::BI__builtin_rvv_vsetvli: + return SemaBuiltinConstantArgRange(TheCall, 1, 0, 3) || + CheckRISCVLMUL(TheCall, 2); + case RISCV::BI__builtin_rvv_vsetvlimax: + return SemaBuiltinConstantArgRange(TheCall, 0, 0, 3) || + CheckRISCVLMUL(TheCall, 1); + } + + return false; } bool Sema::CheckSystemZBuiltinFunctionCall(unsigned BuiltinID, diff --git a/clang/test/CodeGen/RISCV/rvv_errors.c b/clang/test/CodeGen/RISCV/rvv_errors.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/RISCV/rvv_errors.c @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 %s -triple=riscv64 -target-feature +experimental-v -fsyntax-only -verify + +void test() { + __builtin_rvv_vsetvli(1, 7, 0); // expected-error {{argument value 7 is outside the valid range [0, 3]}} + __builtin_rvv_vsetvlimax(-1, 0); // expected-error {{argument value 18446744073709551615 is outside the valid range [0, 3]}} + __builtin_rvv_vsetvli(1, 0, 4); // expected-error {{LMUL argument must be in the range [0,3] or [5,7]}} + __builtin_rvv_vsetvlimax(0, 4); // expected-error {{LMUL argument must be in the range [0,3] or [5,7]}} + __builtin_rvv_vsetvli(1, 0, 8); // expected-error {{LMUL argument must be in the range [0,3] or [5,7]}} + __builtin_rvv_vsetvlimax(0, -1); // expected-error {{LMUL argument must be in the range [0,3] or [5,7]}} +}