@@ -244,6 +244,19 @@ static Value *handleAsDoubleBuiltin(CodeGenFunction &CGF, const CallExpr *E) {
244244 return CGF.Builder.CreateBitCast(BitVec, ResultType);
245245}
246246
247+ /// Helper for the read/write/add/inc X18 builtins: read the X18 register and
248+ /// return it as an i8 pointer.
249+ Value *readX18AsPtr(CodeGenFunction &CGF) {
250+ LLVMContext &Context = CGF.CGM.getLLVMContext();
251+ llvm::Metadata *Ops[] = {llvm::MDString::get(Context, "x18")};
252+ llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops);
253+ llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName);
254+ llvm::Function *F =
255+ CGF.CGM.getIntrinsic(llvm::Intrinsic::read_register, {CGF.Int64Ty});
256+ llvm::Value *X18 = CGF.Builder.CreateCall(F, Metadata);
257+ return CGF.Builder.CreateIntToPtr(X18, CGF.Int8PtrTy);
258+ }
259+
247260/// getBuiltinLibFunction - Given a builtin id for a function like
248261/// "__builtin_fabsf", return a Function* for "fabsf".
249262llvm::Constant *CodeGenModule::getBuiltinLibFunction(const FunctionDecl *FD,
@@ -11836,47 +11849,93 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
1183611849 BuiltinID == AArch64::BI__writex18word ||
1183711850 BuiltinID == AArch64::BI__writex18dword ||
1183811851 BuiltinID == AArch64::BI__writex18qword) {
11852+ // Process the args first
11853+ Value *OffsetArg = EmitScalarExpr(E->getArg(0));
11854+ Value *DataArg = EmitScalarExpr(E->getArg(1));
11855+
1183911856 // Read x18 as i8*
11840- LLVMContext &Context = CGM.getLLVMContext();
11841- llvm::Metadata *Ops[] = {llvm::MDString::get(Context, "x18")};
11842- llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops);
11843- llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName);
11844- llvm::Function *F =
11845- CGM.getIntrinsic(llvm::Intrinsic::read_register, {Int64Ty});
11846- llvm::Value *X18 = Builder.CreateCall(F, Metadata);
11847- X18 = Builder.CreateIntToPtr(X18, Int8PtrTy);
11857+ llvm::Value *X18 = readX18AsPtr(*this);
1184811858
1184911859 // Store val at x18 + offset
11850- Value *Offset = Builder.CreateZExt(EmitScalarExpr(E->getArg(0)) , Int64Ty);
11860+ Value *Offset = Builder.CreateZExt(OffsetArg , Int64Ty);
1185111861 Value *Ptr = Builder.CreateGEP(Int8Ty, X18, Offset);
11852- Value *Val = EmitScalarExpr(E->getArg(1));
11853- StoreInst *Store = Builder.CreateAlignedStore(Val , Ptr, CharUnits::One());
11862+ StoreInst *Store =
11863+ Builder.CreateAlignedStore(DataArg , Ptr, CharUnits::One());
1185411864 return Store;
1185511865 }
1185611866
1185711867 if (BuiltinID == AArch64::BI__readx18byte ||
1185811868 BuiltinID == AArch64::BI__readx18word ||
1185911869 BuiltinID == AArch64::BI__readx18dword ||
1186011870 BuiltinID == AArch64::BI__readx18qword) {
11861- llvm::Type *IntTy = ConvertType(E->getType());
11871+ // Process the args first
11872+ Value *OffsetArg = EmitScalarExpr(E->getArg(0));
1186211873
1186311874 // Read x18 as i8*
11864- LLVMContext &Context = CGM.getLLVMContext();
11865- llvm::Metadata *Ops[] = {llvm::MDString::get(Context, "x18")};
11866- llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops);
11867- llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName);
11868- llvm::Function *F =
11869- CGM.getIntrinsic(llvm::Intrinsic::read_register, {Int64Ty});
11870- llvm::Value *X18 = Builder.CreateCall(F, Metadata);
11871- X18 = Builder.CreateIntToPtr(X18, Int8PtrTy);
11875+ llvm::Value *X18 = readX18AsPtr(*this);
1187211876
1187311877 // Load x18 + offset
11874- Value *Offset = Builder.CreateZExt(EmitScalarExpr(E->getArg(0)) , Int64Ty);
11878+ Value *Offset = Builder.CreateZExt(OffsetArg , Int64Ty);
1187511879 Value *Ptr = Builder.CreateGEP(Int8Ty, X18, Offset);
11880+ llvm::Type *IntTy = ConvertType(E->getType());
1187611881 LoadInst *Load = Builder.CreateAlignedLoad(IntTy, Ptr, CharUnits::One());
1187711882 return Load;
1187811883 }
1187911884
11885+ if (BuiltinID == AArch64::BI__addx18byte ||
11886+ BuiltinID == AArch64::BI__addx18word ||
11887+ BuiltinID == AArch64::BI__addx18dword ||
11888+ BuiltinID == AArch64::BI__addx18qword ||
11889+ BuiltinID == AArch64::BI__incx18byte ||
11890+ BuiltinID == AArch64::BI__incx18word ||
11891+ BuiltinID == AArch64::BI__incx18dword ||
11892+ BuiltinID == AArch64::BI__incx18qword) {
11893+ llvm::Type *IntTy;
11894+ bool isIncrement;
11895+ switch (BuiltinID) {
11896+ case AArch64::BI__incx18byte:
11897+ IntTy = Int8Ty;
11898+ isIncrement = true;
11899+ break;
11900+ case AArch64::BI__incx18word:
11901+ IntTy = Int16Ty;
11902+ isIncrement = true;
11903+ break;
11904+ case AArch64::BI__incx18dword:
11905+ IntTy = Int32Ty;
11906+ isIncrement = true;
11907+ break;
11908+ case AArch64::BI__incx18qword:
11909+ IntTy = Int64Ty;
11910+ isIncrement = true;
11911+ break;
11912+ default:
11913+ IntTy = ConvertType(E->getArg(1)->getType());
11914+ isIncrement = false;
11915+ break;
11916+ }
11917+ // Process the args first
11918+ Value *OffsetArg = EmitScalarExpr(E->getArg(0));
11919+ Value *ValToAdd =
11920+ isIncrement ? ConstantInt::get(IntTy, 1) : EmitScalarExpr(E->getArg(1));
11921+
11922+ // Read x18 as i8*
11923+ llvm::Value *X18 = readX18AsPtr(*this);
11924+
11925+ // Load x18 + offset
11926+ Value *Offset = Builder.CreateZExt(OffsetArg, Int64Ty);
11927+ Value *Ptr = Builder.CreateGEP(Int8Ty, X18, Offset);
11928+ LoadInst *Load = Builder.CreateAlignedLoad(IntTy, Ptr, CharUnits::One());
11929+
11930+ // Add values
11931+ Value *AddResult = Builder.CreateAdd(Load, ValToAdd);
11932+
11933+ // Store val at x18 + offset
11934+ StoreInst *Store =
11935+ Builder.CreateAlignedStore(AddResult, Ptr, CharUnits::One());
11936+ return Store;
11937+ }
11938+
1188011939 if (BuiltinID == AArch64::BI_CopyDoubleFromInt64 ||
1188111940 BuiltinID == AArch64::BI_CopyFloatFromInt32 ||
1188211941 BuiltinID == AArch64::BI_CopyInt32FromFloat ||
0 commit comments