r239737 - This patch implements clang support for the ACLE special register intrinsics
Luke Cheeseman
luke.cheeseman at arm.com
Mon Jun 15 10:51:01 PDT 2015
Author: lukecheeseman
Date: Mon Jun 15 12:51:01 2015
New Revision: 239737
URL: http://llvm.org/viewvc/llvm-project?rev=239737&view=rev
Log:
This patch implements clang support for the ACLE special register intrinsics
in section 10.1, __arm_{w,r}sr{,p,64}.
This includes arm_acle.h definitions with builtins and codegen to support
these, the intrinsics are implemented by generating read/write_register calls
which get appropriately lowered in the backend based on the register string
provided. SemaChecking is also implemented to fault invalid parameters.
Differential Revision: http://reviews.llvm.org/D9697
Added:
cfe/trunk/test/Sema/aarch64-special-register.c
cfe/trunk/test/Sema/arm-special-register.c
Modified:
cfe/trunk/include/clang/Basic/BuiltinsAArch64.def
cfe/trunk/include/clang/Basic/BuiltinsARM.def
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/CodeGen/CGBuiltin.cpp
cfe/trunk/lib/Headers/arm_acle.h
cfe/trunk/lib/Sema/SemaChecking.cpp
cfe/trunk/test/CodeGen/arm_acle.c
cfe/trunk/test/CodeGen/builtins-arm.c
cfe/trunk/test/CodeGen/builtins-arm64.c
Modified: cfe/trunk/include/clang/Basic/BuiltinsAArch64.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/BuiltinsAArch64.def?rev=239737&r1=239736&r2=239737&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/BuiltinsAArch64.def (original)
+++ cfe/trunk/include/clang/Basic/BuiltinsAArch64.def Mon Jun 15 12:51:01 2015
@@ -53,4 +53,12 @@ BUILTIN(__builtin_arm_isb, "vUi", "nc")
// Prefetch
BUILTIN(__builtin_arm_prefetch, "vvC*UiUiUiUi", "nc")
+// System Registers
+BUILTIN(__builtin_arm_rsr, "UicC*", "nc")
+BUILTIN(__builtin_arm_rsr64, "LUicC*", "nc")
+BUILTIN(__builtin_arm_rsrp, "v*cC*", "nc")
+BUILTIN(__builtin_arm_wsr, "vcC*Ui", "nc")
+BUILTIN(__builtin_arm_wsr64, "vcC*LUi", "nc")
+BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc")
+
#undef BUILTIN
Modified: cfe/trunk/include/clang/Basic/BuiltinsARM.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/BuiltinsARM.def?rev=239737&r1=239736&r2=239737&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/BuiltinsARM.def (original)
+++ cfe/trunk/include/clang/Basic/BuiltinsARM.def Mon Jun 15 12:51:01 2015
@@ -84,6 +84,14 @@ BUILTIN(__builtin_arm_isb, "vUi", "nc")
// Prefetch
BUILTIN(__builtin_arm_prefetch, "vvC*UiUi", "nc")
+// System registers (ACLE)
+BUILTIN(__builtin_arm_rsr, "UicC*", "nc")
+BUILTIN(__builtin_arm_rsr64, "LLUicC*", "nc")
+BUILTIN(__builtin_arm_rsrp, "v*cC*", "nc")
+BUILTIN(__builtin_arm_wsr, "vcC*Ui", "nc")
+BUILTIN(__builtin_arm_wsr64, "vcC*LLUi", "nc")
+BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc")
+
// MSVC
LANGBUILTIN(__emit, "vIUiC", "", ALL_MS_LANGUAGES)
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=239737&r1=239736&r2=239737&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Jun 15 12:51:01 2015
@@ -108,6 +108,7 @@ def err_ice_ambiguous_conversion : Error
def err_ice_too_large : Error<
"integer constant expression evaluates to value %0 that cannot be "
"represented in a %1-bit %select{signed|unsigned}2 integer type">;
+def err_expr_not_string_literal : Error<"expression is not a string literal">;
// Semantic analysis of constant literals.
def ext_predef_outside_function : Warning<
@@ -424,6 +425,7 @@ def warn_redecl_library_builtin : Warnin
"incompatible redeclaration of library function %0">,
InGroup<DiagGroup<"incompatible-library-redeclaration">>;
def err_builtin_definition : Error<"definition of builtin function %0">;
+def err_arm_invalid_specialreg : Error<"invalid special register for builtin">;
def warn_builtin_unknown : Warning<"use of unknown builtin %0">,
InGroup<ImplicitFunctionDeclare>, DefaultError;
def warn_dyn_class_memaccess : Warning<
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=239737&r1=239736&r2=239737&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Jun 15 12:51:01 2015
@@ -8604,7 +8604,9 @@ private:
llvm::APSInt &Result);
bool SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum,
int Low, int High);
-
+ bool SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall,
+ int ArgNum, unsigned ExpectedFieldNum,
+ bool AllowName);
public:
enum FormatStringType {
FST_Scanf,
Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=239737&r1=239736&r2=239737&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Mon Jun 15 12:51:01 2015
@@ -3279,6 +3279,66 @@ Value *CodeGenFunction::GetValueForARMHi
}
}
+// Generates the IR for the read/write special register builtin,
+// ValueType is the type of the value that is to be written or read,
+// RegisterType is the type of the register being written to or read from.
+static Value *EmitSpecialRegisterBuiltin(CodeGenFunction &CGF,
+ const CallExpr *E,
+ llvm::Type *RegisterType,
+ llvm::Type *ValueType, bool IsRead) {
+ // write and register intrinsics only support 32 and 64 bit operations.
+ assert((RegisterType->isIntegerTy(32) || RegisterType->isIntegerTy(64))
+ && "Unsupported size for register.");
+
+ CodeGen::CGBuilderTy &Builder = CGF.Builder;
+ CodeGen::CodeGenModule &CGM = CGF.CGM;
+ LLVMContext &Context = CGM.getLLVMContext();
+
+ const Expr *SysRegStrExpr = E->getArg(0)->IgnoreParenCasts();
+ StringRef SysReg = cast<StringLiteral>(SysRegStrExpr)->getString();
+
+ llvm::Metadata *Ops[] = { llvm::MDString::get(Context, SysReg) };
+ llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops);
+ llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName);
+
+ llvm::Type *Types[] = { RegisterType };
+
+ bool MixedTypes = RegisterType->isIntegerTy(64) && ValueType->isIntegerTy(32);
+ assert(!(RegisterType->isIntegerTy(32) && ValueType->isIntegerTy(64))
+ && "Can't fit 64-bit value in 32-bit register");
+
+ if (IsRead) {
+ llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::read_register, Types);
+ llvm::Value *Call = Builder.CreateCall(F, Metadata);
+
+ if (MixedTypes)
+ // Read into 64 bit register and then truncate result to 32 bit.
+ return Builder.CreateTrunc(Call, ValueType);
+
+ if (ValueType->isPointerTy())
+ // Have i32/i64 result (Call) but want to return a VoidPtrTy (i8*).
+ return Builder.CreateIntToPtr(Call, ValueType);
+
+ return Call;
+ }
+
+ llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::write_register, Types);
+ llvm::Value *ArgValue = CGF.EmitScalarExpr(E->getArg(1));
+ if (MixedTypes) {
+ // Extend 32 bit write value to 64 bit to pass to write.
+ ArgValue = Builder.CreateZExt(ArgValue, RegisterType);
+ return Builder.CreateCall(F, { Metadata, ArgValue });
+ }
+
+ if (ValueType->isPointerTy()) {
+ // Have VoidPtrTy ArgValue but want to return an i32/i64.
+ ArgValue = Builder.CreatePtrToInt(ArgValue, RegisterType);
+ return Builder.CreateCall(F, { Metadata, ArgValue });
+ }
+
+ return Builder.CreateCall(F, { Metadata, ArgValue });
+}
+
Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
const CallExpr *E) {
if (auto Hint = GetValueForARMHint(BuiltinID))
@@ -3491,6 +3551,37 @@ Value *CodeGenFunction::EmitARMBuiltinEx
}
}
+ if (BuiltinID == ARM::BI__builtin_arm_rsr ||
+ BuiltinID == ARM::BI__builtin_arm_rsr64 ||
+ BuiltinID == ARM::BI__builtin_arm_rsrp ||
+ BuiltinID == ARM::BI__builtin_arm_wsr ||
+ BuiltinID == ARM::BI__builtin_arm_wsr64 ||
+ BuiltinID == ARM::BI__builtin_arm_wsrp) {
+
+ bool IsRead = BuiltinID == ARM::BI__builtin_arm_rsr ||
+ BuiltinID == ARM::BI__builtin_arm_rsr64 ||
+ BuiltinID == ARM::BI__builtin_arm_rsrp;
+
+ bool IsPointerBuiltin = BuiltinID == ARM::BI__builtin_arm_rsrp ||
+ BuiltinID == ARM::BI__builtin_arm_wsrp;
+
+ bool Is64Bit = BuiltinID == ARM::BI__builtin_arm_rsr64 ||
+ BuiltinID == ARM::BI__builtin_arm_wsr64;
+
+ llvm::Type *ValueType;
+ llvm::Type *RegisterType;
+ if (IsPointerBuiltin) {
+ ValueType = VoidPtrTy;
+ RegisterType = Int32Ty;
+ } else if (Is64Bit) {
+ ValueType = RegisterType = Int64Ty;
+ } else {
+ ValueType = RegisterType = Int32Ty;
+ }
+
+ return EmitSpecialRegisterBuiltin(*this, E, RegisterType, ValueType, IsRead);
+ }
+
// Find out if any arguments are required to be integer constant
// expressions.
unsigned ICEArguments = 0;
@@ -4239,6 +4330,36 @@ Value *CodeGenFunction::EmitAArch64Built
return Builder.CreateCall(F, {Arg0, Arg1});
}
+ if (BuiltinID == AArch64::BI__builtin_arm_rsr ||
+ BuiltinID == AArch64::BI__builtin_arm_rsr64 ||
+ BuiltinID == AArch64::BI__builtin_arm_rsrp ||
+ BuiltinID == AArch64::BI__builtin_arm_wsr ||
+ BuiltinID == AArch64::BI__builtin_arm_wsr64 ||
+ BuiltinID == AArch64::BI__builtin_arm_wsrp) {
+
+ bool IsRead = BuiltinID == AArch64::BI__builtin_arm_rsr ||
+ BuiltinID == AArch64::BI__builtin_arm_rsr64 ||
+ BuiltinID == AArch64::BI__builtin_arm_rsrp;
+
+ bool IsPointerBuiltin = BuiltinID == AArch64::BI__builtin_arm_rsrp ||
+ BuiltinID == AArch64::BI__builtin_arm_wsrp;
+
+ bool Is64Bit = BuiltinID != AArch64::BI__builtin_arm_rsr &&
+ BuiltinID != AArch64::BI__builtin_arm_wsr;
+
+ llvm::Type *ValueType;
+ llvm::Type *RegisterType = Int64Ty;
+ if (IsPointerBuiltin) {
+ ValueType = VoidPtrTy;
+ } else if (Is64Bit) {
+ ValueType = Int64Ty;
+ } else {
+ ValueType = Int32Ty;
+ }
+
+ return EmitSpecialRegisterBuiltin(*this, E, RegisterType, ValueType, IsRead);
+ }
+
// Find out if any arguments are required to be integer constant
// expressions.
unsigned ICEArguments = 0;
Modified: cfe/trunk/lib/Headers/arm_acle.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Headers/arm_acle.h?rev=239737&r1=239736&r2=239737&view=diff
==============================================================================
--- cfe/trunk/lib/Headers/arm_acle.h (original)
+++ cfe/trunk/lib/Headers/arm_acle.h Mon Jun 15 12:51:01 2015
@@ -289,6 +289,14 @@ static __inline__ uint32_t __attribute__
}
#endif
+/* 10.1 Special register intrinsics */
+#define __arm_rsr(sysreg) __builtin_arm_rsr(sysreg)
+#define __arm_rsr64(sysreg) __builtin_arm_rsr64(sysreg)
+#define __arm_rsrp(sysreg) __builtin_arm_rsrp(sysreg)
+#define __arm_wsr(sysreg, v) __builtin_arm_wsr(sysreg, v)
+#define __arm_wsr64(sysreg, v) __builtin_arm_wsr64(sysreg, v)
+#define __arm_wsrp(sysreg, v) __builtin_arm_wsrp(sysreg, v)
+
#if defined(__cplusplus)
}
#endif
Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=239737&r1=239736&r2=239737&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Mon Jun 15 12:51:01 2015
@@ -836,6 +836,16 @@ bool Sema::CheckARMBuiltinFunctionCall(u
SemaBuiltinConstantArgRange(TheCall, 2, 0, 1);
}
+ if (BuiltinID == ARM::BI__builtin_arm_rsr64 ||
+ BuiltinID == ARM::BI__builtin_arm_wsr64)
+ return SemaBuiltinARMSpecialReg(BuiltinID, TheCall, 0, 3, false);
+
+ if (BuiltinID == ARM::BI__builtin_arm_rsr ||
+ BuiltinID == ARM::BI__builtin_arm_rsrp ||
+ BuiltinID == ARM::BI__builtin_arm_wsr ||
+ BuiltinID == ARM::BI__builtin_arm_wsrp)
+ return SemaBuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);
+
if (CheckNeonBuiltinFunctionCall(BuiltinID, TheCall))
return true;
@@ -876,6 +886,16 @@ bool Sema::CheckAArch64BuiltinFunctionCa
SemaBuiltinConstantArgRange(TheCall, 4, 0, 1);
}
+ if (BuiltinID == AArch64::BI__builtin_arm_rsr64 ||
+ BuiltinID == AArch64::BI__builtin_arm_wsr64)
+ return SemaBuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, false);
+
+ if (BuiltinID == AArch64::BI__builtin_arm_rsr ||
+ BuiltinID == AArch64::BI__builtin_arm_rsrp ||
+ BuiltinID == AArch64::BI__builtin_arm_wsr ||
+ BuiltinID == AArch64::BI__builtin_arm_wsrp)
+ return SemaBuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);
+
if (CheckNeonBuiltinFunctionCall(BuiltinID, TheCall))
return true;
@@ -2592,6 +2612,107 @@ bool Sema::SemaBuiltinConstantArgRange(C
return false;
}
+
+/// SemaBuiltinARMSpecialReg - Handle a check if argument ArgNum of CallExpr
+/// TheCall is an ARM/AArch64 special register string literal.
+bool Sema::SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall,
+ int ArgNum, unsigned ExpectedFieldNum,
+ bool AllowName) {
+ bool IsARMBuiltin = BuiltinID == ARM::BI__builtin_arm_rsr64 ||
+ BuiltinID == ARM::BI__builtin_arm_wsr64 ||
+ BuiltinID == ARM::BI__builtin_arm_rsr ||
+ BuiltinID == ARM::BI__builtin_arm_rsrp ||
+ BuiltinID == ARM::BI__builtin_arm_wsr ||
+ BuiltinID == ARM::BI__builtin_arm_wsrp;
+ bool IsAArch64Builtin = BuiltinID == AArch64::BI__builtin_arm_rsr64 ||
+ BuiltinID == AArch64::BI__builtin_arm_wsr64 ||
+ BuiltinID == AArch64::BI__builtin_arm_rsr ||
+ BuiltinID == AArch64::BI__builtin_arm_rsrp ||
+ BuiltinID == AArch64::BI__builtin_arm_wsr ||
+ BuiltinID == AArch64::BI__builtin_arm_wsrp;
+ assert((IsARMBuiltin || IsAArch64Builtin) && "Unexpected ARM builtin.");
+
+ // We can't check the value of a dependent argument.
+ Expr *Arg = TheCall->getArg(ArgNum);
+ if (Arg->isTypeDependent() || Arg->isValueDependent())
+ return false;
+
+ // Check if the argument is a string literal.
+ if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts()))
+ return Diag(TheCall->getLocStart(), diag::err_expr_not_string_literal)
+ << Arg->getSourceRange();
+
+ // Check the type of special register given.
+ StringRef Reg = cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString();
+ SmallVector<StringRef, 6> Fields;
+ Reg.split(Fields, ":");
+
+ if (Fields.size() != ExpectedFieldNum && !(AllowName && Fields.size() == 1))
+ return Diag(TheCall->getLocStart(), diag::err_arm_invalid_specialreg)
+ << Arg->getSourceRange();
+
+ // If the string is the name of a register then we cannot check that it is
+ // valid here but if the string is of one the forms described in ACLE then we
+ // can check that the supplied fields are integers and within the valid
+ // ranges.
+ if (Fields.size() > 1) {
+ bool FiveFields = Fields.size() == 5;
+
+ bool ValidString = true;
+ if (IsARMBuiltin) {
+ ValidString &= Fields[0].startswith_lower("cp") ||
+ Fields[0].startswith_lower("p");
+ if (ValidString)
+ Fields[0] =
+ Fields[0].drop_front(Fields[0].startswith_lower("cp") ? 2 : 1);
+
+ ValidString &= Fields[2].startswith_lower("c");
+ if (ValidString)
+ Fields[2] = Fields[2].drop_front(1);
+
+ if (FiveFields) {
+ ValidString &= Fields[3].startswith_lower("c");
+ if (ValidString)
+ Fields[3] = Fields[3].drop_front(1);
+ }
+ }
+
+ SmallVector<int, 5> Ranges;
+ if (FiveFields)
+ Ranges.append({IsAArch64Builtin ? 1 : 15, 7, 7, 15, 15});
+ else
+ Ranges.append({15, 7, 15});
+
+ for (unsigned i=0; i<Fields.size(); ++i) {
+ int IntField;
+ ValidString &= !Fields[i].getAsInteger(10, IntField);
+ ValidString &= (IntField >= 0 && IntField <= Ranges[i]);
+ }
+
+ if (!ValidString)
+ return Diag(TheCall->getLocStart(), diag::err_arm_invalid_specialreg)
+ << Arg->getSourceRange();
+
+ } else if (IsAArch64Builtin && Fields.size() == 1) {
+ // If the register name is one of those that appear in the condition below
+ // and the special register builtin being used is one of the write builtins,
+ // then we require that the argument provided for writing to the register
+ // is an integer constant expression. This is because it will be lowered to
+ // an MSR (immediate) instruction, so we need to know the immediate at
+ // compile time.
+ if (TheCall->getNumArgs() != 2)
+ return false;
+
+ std::string RegLower = Reg.lower();
+ if (RegLower != "spsel" && RegLower != "daifset" && RegLower != "daifclr" &&
+ RegLower != "pan" && RegLower != "uao")
+ return false;
+
+ return SemaBuiltinConstantArgRange(TheCall, 1, 0, 15);
+ }
+
+ return false;
+}
/// SemaBuiltinLongjmp - Handle __builtin_longjmp(void *env[5], int val).
/// This checks that the target supports __builtin_longjmp and
Modified: cfe/trunk/test/CodeGen/arm_acle.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/arm_acle.c?rev=239737&r1=239736&r2=239737&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/arm_acle.c (original)
+++ cfe/trunk/test/CodeGen/arm_acle.c Mon Jun 15 12:51:01 2015
@@ -336,3 +336,69 @@ uint32_t test_crc32cw(uint32_t a, uint32
uint32_t test_crc32cd(uint32_t a, uint64_t b) {
return __crc32cd(a, b);
}
+
+/* 10.1 Special register intrinsics */
+// ARM-LABEL: test_rsr
+// AArch64: call i64 @llvm.read_register.i64(metadata !1)
+// AArch32: call i32 @llvm.read_register.i32(metadata !3)
+uint32_t test_rsr() {
+#ifdef __ARM_32BIT_STATE
+ return __arm_rsr("cp1:2:c3:c4:5");
+#else
+ return __arm_rsr("1:2:3:4:5");
+#endif
+}
+
+// ARM-LABEL: test_rsr64
+// AArch64: call i64 @llvm.read_register.i64(metadata !1)
+// AArch32: call i64 @llvm.read_register.i64(metadata !4)
+uint64_t test_rsr64() {
+#ifdef __ARM_32BIT_STATE
+ return __arm_rsr64("cp1:2:c3");
+#else
+ return __arm_rsr64("1:2:3:4:5");
+#endif
+}
+
+// ARM-LABEL: test_rsrp
+// AArch64: call i64 @llvm.read_register.i64(metadata !2)
+// AArch32: call i32 @llvm.read_register.i32(metadata !5)
+void *test_rsrp() {
+ return __arm_rsrp("sysreg");
+}
+
+// ARM-LABEL: test_wsr
+// AArch64: call void @llvm.write_register.i64(metadata !1, i64 %1)
+// AArch32: call void @llvm.write_register.i32(metadata !3, i32 %v)
+void test_wsr(uint32_t v) {
+#ifdef __ARM_32BIT_STATE
+ __arm_wsr("cp1:2:c3:c4:5", v);
+#else
+ __arm_wsr("1:2:3:4:5", v);
+#endif
+}
+
+// ARM-LABEL: test_wsr64
+// AArch64: call void @llvm.write_register.i64(metadata !1, i64 %v)
+// AArch32: call void @llvm.write_register.i64(metadata !4, i64 %v)
+void test_wsr64(uint64_t v) {
+#ifdef __ARM_32BIT_STATE
+ __arm_wsr64("cp1:2:c3", v);
+#else
+ __arm_wsr64("1:2:3:4:5", v);
+#endif
+}
+
+// ARM-LABEL: test_wsrp
+// AArch64: call void @llvm.write_register.i64(metadata !2, i64 %1)
+// AArch32: call void @llvm.write_register.i32(metadata !5, i32 %1)
+void test_wsrp(void *v) {
+ __arm_wsrp("sysreg", v);
+}
+
+// AArch32: !3 = !{!"cp1:2:c3:c4:5"}
+// AArch32: !4 = !{!"cp1:2:c3"}
+// AArch32: !5 = !{!"sysreg"}
+
+// AArch64: !1 = !{!"1:2:3:4:5"}
+// AArch64: !2 = !{!"sysreg"}
Modified: cfe/trunk/test/CodeGen/builtins-arm.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/builtins-arm.c?rev=239737&r1=239736&r2=239737&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/builtins-arm.c (original)
+++ cfe/trunk/test/CodeGen/builtins-arm.c Mon Jun 15 12:51:01 2015
@@ -84,3 +84,42 @@ void prefetch(int i) {
__builtin_arm_prefetch(&i, 1, 0);
// CHECK: call {{.*}} @llvm.prefetch(i8* %{{.*}}, i32 1, i32 3, i32 0)
}
+
+unsigned rsr() {
+ // CHECK: [[V0:[%A-Za-z0-9.]+]] = {{.*}} call i32 @llvm.read_register.i32(metadata !7)
+ // CHECK-NEXT: ret i32 [[V0]]
+ return __builtin_arm_rsr("cp1:2:c3:c4:5");
+}
+
+unsigned long long rsr64() {
+ // CHECK: [[V0:[%A-Za-z0-9.]+]] = {{.*}} call i64 @llvm.read_register.i64(metadata !8)
+ // CHECK-NEXT: ret i64 [[V0]]
+ return __builtin_arm_rsr64("cp1:2:c3");
+}
+
+void *rsrp() {
+ // CHECK: [[V0:[%A-Za-z0-9.]+]] = {{.*}} call i32 @llvm.read_register.i32(metadata !9)
+ // CHECK-NEXT: [[V1:[%A-Za-z0-9.]+]] = inttoptr i32 [[V0]] to i8*
+ // CHECK-NEXT: ret i8* [[V1]]
+ return __builtin_arm_rsrp("sysreg");
+}
+
+void wsr(unsigned v) {
+ // CHECK: call void @llvm.write_register.i32(metadata !7, i32 %v)
+ __builtin_arm_wsr("cp1:2:c3:c4:5", v);
+}
+
+void wsr64(unsigned long long v) {
+ // CHECK: call void @llvm.write_register.i64(metadata !8, i64 %v)
+ __builtin_arm_wsr64("cp1:2:c3", v);
+}
+
+void wsrp(void *v) {
+ // CHECK: [[V0:[%A-Za-z0-9.]+]] = ptrtoint i8* %v to i32
+ // CHECK-NEXT: call void @llvm.write_register.i32(metadata !9, i32 [[V0]])
+ __builtin_arm_wsrp("sysreg", v);
+}
+
+// CHECK: !7 = !{!"cp1:2:c3:c4:5"}
+// CHECK: !8 = !{!"cp1:2:c3"}
+// CHECK: !9 = !{!"sysreg"}
Modified: cfe/trunk/test/CodeGen/builtins-arm64.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/builtins-arm64.c?rev=239737&r1=239736&r2=239737&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/builtins-arm64.c (original)
+++ cfe/trunk/test/CodeGen/builtins-arm64.c Mon Jun 15 12:51:01 2015
@@ -43,3 +43,39 @@ void prefetch() {
__builtin_arm_prefetch(0, 0, 0, 0, 0); // plil1keep
// CHECK: call {{.*}} @llvm.prefetch(i8* null, i32 0, i32 3, i32 0)
}
+
+unsigned rsr() {
+ // CHECK: [[V0:[%A-Za-z0-9.]+]] = {{.*}} call i64 @llvm.read_register.i64(metadata !1)
+ // CHECK-NEXT: trunc i64 [[V0]] to i32
+ return __builtin_arm_rsr("1:2:3:4:5");
+}
+
+unsigned long rsr64() {
+ // CHECK: call i64 @llvm.read_register.i64(metadata !1)
+ return __builtin_arm_rsr64("1:2:3:4:5");
+}
+
+void *rsrp() {
+ // CHECK: [[V0:[%A-Za-z0-9.]+]] = {{.*}} call i64 @llvm.read_register.i64(metadata !1)
+ // CHECK-NEXT: inttoptr i64 [[V0]] to i8*
+ return __builtin_arm_rsrp("1:2:3:4:5");
+}
+
+void wsr(unsigned v) {
+ // CHECK: [[V0:[%A-Za-z0-9.]+]] = zext i32 %v to i64
+ // CHECK-NEXT: call void @llvm.write_register.i64(metadata !1, i64 [[V0]])
+ __builtin_arm_wsr("1:2:3:4:5", v);
+}
+
+void wsr64(unsigned long v) {
+ // CHECK: call void @llvm.write_register.i64(metadata !1, i64 %v)
+ __builtin_arm_wsr64("1:2:3:4:5", v);
+}
+
+void wsrp(void *v) {
+ // CHECK: [[V0:[%A-Za-z0-9.]+]] = ptrtoint i8* %v to i64
+ // CHECK-NEXT: call void @llvm.write_register.i64(metadata !1, i64 [[V0]])
+ __builtin_arm_wsrp("1:2:3:4:5", v);
+}
+
+// CHECK: !1 = !{!"1:2:3:4:5"}
Added: cfe/trunk/test/Sema/aarch64-special-register.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/aarch64-special-register.c?rev=239737&view=auto
==============================================================================
--- cfe/trunk/test/Sema/aarch64-special-register.c (added)
+++ cfe/trunk/test/Sema/aarch64-special-register.c Mon Jun 15 12:51:01 2015
@@ -0,0 +1,77 @@
+// RUN: %clang_cc1 -ffreestanding -fsyntax-only -verify -triple aarch64 %s
+
+void string_literal(unsigned v) {
+ __builtin_arm_wsr(0, v); // expected-error {{expression is not a string literal}}
+}
+
+void wsr_1(unsigned v) {
+ __builtin_arm_wsr("sysreg", v);
+}
+
+void wsrp_1(void *v) {
+ __builtin_arm_wsrp("sysreg", v);
+}
+
+void wsr64_1(unsigned long v) {
+ __builtin_arm_wsr64("sysreg", v); //expected-error {{invalid special register for builtin}}
+}
+
+unsigned rsr_1() {
+ return __builtin_arm_rsr("sysreg");
+}
+
+void *rsrp_1() {
+ return __builtin_arm_rsrp("sysreg");
+}
+
+unsigned long rsr64_1() {
+ return __builtin_arm_rsr64("sysreg"); //expected-error {{invalid special register for builtin}}
+}
+
+void wsr_2(unsigned v) {
+ __builtin_arm_wsr("0:1:2:3:4", v);
+}
+
+void wsrp_2(void *v) {
+ __builtin_arm_wsrp("0:1:2:3:4", v);
+}
+
+void wsr64_2(unsigned long v) {
+ __builtin_arm_wsr64("0:1:2:3:4", v);
+}
+
+unsigned rsr_2() {
+ return __builtin_arm_rsr("0:1:2:3:4");
+}
+
+void *rsrp_2() {
+ return __builtin_arm_rsrp("0:1:2:3:4");
+}
+
+unsigned long rsr64_2() {
+ return __builtin_arm_rsr64("0:1:2:3:4");
+}
+
+void wsr_3(unsigned v) {
+ __builtin_arm_wsr("0:1:2", v); //expected-error {{invalid special register for builtin}}
+}
+
+void wsrp_3(void *v) {
+ __builtin_arm_wsrp("0:1:2", v); //expected-error {{invalid special register for builtin}}
+}
+
+void wsr64_3(unsigned long v) {
+ __builtin_arm_wsr64("0:1:2", v); //expected-error {{invalid special register for builtin}}
+}
+
+unsigned rsr_3() {
+ return __builtin_arm_rsr("0:1:2"); //expected-error {{invalid special register for builtin}}
+}
+
+void *rsrp_3() {
+ return __builtin_arm_rsrp("0:1:2"); //expected-error {{invalid special register for builtin}}
+}
+
+unsigned long rsr64_3() {
+ return __builtin_arm_rsr64("0:1:2"); //expected-error {{invalid special register for builtin}}
+}
Added: cfe/trunk/test/Sema/arm-special-register.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/arm-special-register.c?rev=239737&view=auto
==============================================================================
--- cfe/trunk/test/Sema/arm-special-register.c (added)
+++ cfe/trunk/test/Sema/arm-special-register.c Mon Jun 15 12:51:01 2015
@@ -0,0 +1,89 @@
+// RUN: %clang_cc1 -ffreestanding -fsyntax-only -verify -triple arm %s
+
+void string_literal(unsigned v) {
+ __builtin_arm_wsr(0, v); // expected-error {{expression is not a string literal}}
+}
+
+void wsr_1(unsigned v) {
+ __builtin_arm_wsr("sysreg", v);
+}
+
+void wsrp_1(void *v) {
+ __builtin_arm_wsrp("sysreg", v);
+}
+
+void wsr64_1(unsigned long v) {
+ __builtin_arm_wsr64("sysreg", v); //expected-error {{invalid special register for builtin}}
+}
+
+unsigned rsr_1() {
+ return __builtin_arm_rsr("sysreg");
+}
+
+void *rsrp_1() {
+ return __builtin_arm_rsrp("sysreg");
+}
+
+unsigned long rsr64_1() {
+ return __builtin_arm_rsr64("sysreg"); //expected-error {{invalid special register for builtin}}
+}
+
+void wsr_2(unsigned v) {
+ __builtin_arm_wsr("cp0:1:c2:c3:4", v);
+}
+
+void wsrp_2(void *v) {
+ __builtin_arm_wsrp("cp0:1:c2:c3:4", v);
+}
+
+void wsr64_2(unsigned long v) {
+ __builtin_arm_wsr64("cp0:1:c2:c3:4", v); //expected-error {{invalid special register for builtin}}
+}
+
+unsigned rsr_2() {
+ return __builtin_arm_rsr("cp0:1:c2:c3:4");
+}
+
+void *rsrp_2() {
+ return __builtin_arm_rsrp("cp0:1:c2:c3:4");
+}
+
+unsigned long rsr64_2() {
+ return __builtin_arm_rsr64("cp0:1:c2:c3:4"); //expected-error {{invalid special register for builtin}}
+}
+
+void wsr_3(unsigned v) {
+ __builtin_arm_wsr("cp0:1:c2", v); //expected-error {{invalid special register for builtin}}
+}
+
+void wsrp_3(void *v) {
+ __builtin_arm_wsrp("cp0:1:c2", v); //expected-error {{invalid special register for builtin}}
+}
+
+void wsr64_3(unsigned long v) {
+ __builtin_arm_wsr64("cp0:1:c2", v);
+}
+
+unsigned rsr_3() {
+ return __builtin_arm_rsr("cp0:1:c2"); //expected-error {{invalid special register for builtin}}
+}
+
+void *rsrp_3() {
+ return __builtin_arm_rsrp("cp0:1:c2"); //expected-error {{invalid special register for builtin}}
+}
+
+unsigned long rsr64_3() {
+ return __builtin_arm_rsr64("cp0:1:c2");
+}
+
+unsigned rsr_4() {
+ return __builtin_arm_rsr("0:1:2:3:4"); //expected-error {{invalid special register for builtin}}
+}
+
+void *rsrp_4() {
+ return __builtin_arm_rsrp("0:1:2:3:4"); //expected-error {{invalid special register for builtin}}
+}
+
+unsigned long rsr64_4() {
+ return __builtin_arm_rsr64("0:1:2"); //expected-error {{invalid special register for builtin}}
+}
More information about the cfe-commits
mailing list