Index: include/clang/Basic/BuiltinsAArch64.def =================================================================== --- include/clang/Basic/BuiltinsAArch64.def +++ include/clang/Basic/BuiltinsAArch64.def @@ -104,6 +104,7 @@ TARGET_HEADER_BUILTIN(_InterlockedXor64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_ReadWriteBarrier, "v", "nh", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__getReg, "ULLii", "nh", "intrin.h", ALL_MS_LANGUAGES, "") #undef BUILTIN #undef LANGBUILTIN Index: lib/CodeGen/CGBuiltin.cpp =================================================================== --- lib/CodeGen/CGBuiltin.cpp +++ lib/CodeGen/CGBuiltin.cpp @@ -6582,6 +6582,30 @@ return Builder.CreateCall(F, {StoreVal, StoreAddr}, "stxr"); } + if (BuiltinID == AArch64::BI__getReg) { + APSInt Value; + if (!E->getArg(0)->EvaluateAsInt(Value, CGM.getContext())) + CGM.Error(E->getArg(0)->getBeginLoc(), + "__getReg expects a constant input parameter"); + + if (Value < 0 || Value > 31) + CGM.Error(E->getArg(0)->getBeginLoc(), + "__getReg expects an input parameter between 0 and 31"); + + LLVMContext &Context = CGM.getLLVMContext(); + SmallString<8> StrVal; + Value.toString(StrVal); + std::string Reg = "x" + std::string(StrVal.c_str()); + + llvm::Metadata *Ops[] = {llvm::MDString::get(Context, Reg)}; + llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops); + llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName); + + llvm::Value *F = + CGM.getIntrinsic(llvm::Intrinsic::read_register, {Int64Ty}); + return Builder.CreateCall(F, Metadata); + } + if (BuiltinID == AArch64::BI__builtin_arm_clrex) { Function *F = CGM.getIntrinsic(Intrinsic::aarch64_clrex); return Builder.CreateCall(F); Index: lib/Headers/intrin.h =================================================================== --- lib/Headers/intrin.h +++ lib/Headers/intrin.h @@ -865,6 +865,13 @@ #endif /*----------------------------------------------------------------------------*\ +|* MS AArch64 specific +\*----------------------------------------------------------------------------*/ +#if defined(__aarch64__) +unsigned __int64 __getReg(int); +#endif + +/*----------------------------------------------------------------------------*\ |* Privileged intrinsics \*----------------------------------------------------------------------------*/ #if defined(__i386__) || defined(__x86_64__) Index: test/CodeGen/arm64-microsoft-intrinsics.c =================================================================== --- test/CodeGen/arm64-microsoft-intrinsics.c +++ test/CodeGen/arm64-microsoft-intrinsics.c @@ -66,3 +66,42 @@ // CHECK-MSVC: fence syncscope("singlethread") // CHECK-LINUX: error: implicit declaration of function '_ReadWriteBarrier' + +unsigned __int64 check_getReg() { + unsigned volatile __int64 reg; + reg = __getReg(0); + reg = __getReg(1); + reg = __getReg(2); + reg = __getReg(3); + reg = __getReg(4); + reg = __getReg(5); + reg = __getReg(6); + reg = __getReg(7); + reg = __getReg(8); + reg = __getReg(9); + reg = __getReg(10); + reg = __getReg(11); + reg = __getReg(12); + reg = __getReg(13); + reg = __getReg(14); + reg = __getReg(15); + reg = __getReg(16); + reg = __getReg(17); + reg = __getReg(18); + reg = __getReg(19); + reg = __getReg(20); + reg = __getReg(21); + reg = __getReg(22); + reg = __getReg(23); + reg = __getReg(24); + reg = __getReg(25); + reg = __getReg(26); + reg = __getReg(27); + reg = __getReg(28); + reg = __getReg(29); + reg = __getReg(30); + reg = __getReg(31); + return reg; +} + +// CHECK-MSVC: llvm.read_register.i64