@@ -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,
@@ -11820,47 +11833,93 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
1182011833 BuiltinID == AArch64::BI__writex18word ||
1182111834 BuiltinID == AArch64::BI__writex18dword ||
1182211835 BuiltinID == AArch64::BI__writex18qword) {
11836+ // Process the args first
11837+ Value *OffsetArg = EmitScalarExpr(E->getArg(0));
11838+ Value *DataArg = EmitScalarExpr(E->getArg(1));
11839+
1182311840 // Read x18 as i8*
11824- LLVMContext &Context = CGM.getLLVMContext();
11825- llvm::Metadata *Ops[] = {llvm::MDString::get(Context, "x18")};
11826- llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops);
11827- llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName);
11828- llvm::Function *F =
11829- CGM.getIntrinsic(llvm::Intrinsic::read_register, {Int64Ty});
11830- llvm::Value *X18 = Builder.CreateCall(F, Metadata);
11831- X18 = Builder.CreateIntToPtr(X18, Int8PtrTy);
11841+ llvm::Value *X18 = readX18AsPtr(*this);
1183211842
1183311843 // Store val at x18 + offset
11834- Value *Offset = Builder.CreateZExt(EmitScalarExpr(E->getArg(0)) , Int64Ty);
11844+ Value *Offset = Builder.CreateZExt(OffsetArg , Int64Ty);
1183511845 Value *Ptr = Builder.CreateGEP(Int8Ty, X18, Offset);
11836- Value *Val = EmitScalarExpr(E->getArg(1));
11837- StoreInst *Store = Builder.CreateAlignedStore(Val , Ptr, CharUnits::One());
11846+ StoreInst *Store =
11847+ Builder.CreateAlignedStore(DataArg , Ptr, CharUnits::One());
1183811848 return Store;
1183911849 }
1184011850
1184111851 if (BuiltinID == AArch64::BI__readx18byte ||
1184211852 BuiltinID == AArch64::BI__readx18word ||
1184311853 BuiltinID == AArch64::BI__readx18dword ||
1184411854 BuiltinID == AArch64::BI__readx18qword) {
11845- llvm::Type *IntTy = ConvertType(E->getType());
11855+ // Process the args first
11856+ Value *OffsetArg = EmitScalarExpr(E->getArg(0));
1184611857
1184711858 // Read x18 as i8*
11848- LLVMContext &Context = CGM.getLLVMContext();
11849- llvm::Metadata *Ops[] = {llvm::MDString::get(Context, "x18")};
11850- llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops);
11851- llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName);
11852- llvm::Function *F =
11853- CGM.getIntrinsic(llvm::Intrinsic::read_register, {Int64Ty});
11854- llvm::Value *X18 = Builder.CreateCall(F, Metadata);
11855- X18 = Builder.CreateIntToPtr(X18, Int8PtrTy);
11859+ llvm::Value *X18 = readX18AsPtr(*this);
1185611860
1185711861 // Load x18 + offset
11858- Value *Offset = Builder.CreateZExt(EmitScalarExpr(E->getArg(0)) , Int64Ty);
11862+ Value *Offset = Builder.CreateZExt(OffsetArg , Int64Ty);
1185911863 Value *Ptr = Builder.CreateGEP(Int8Ty, X18, Offset);
11864+ llvm::Type *IntTy = ConvertType(E->getType());
1186011865 LoadInst *Load = Builder.CreateAlignedLoad(IntTy, Ptr, CharUnits::One());
1186111866 return Load;
1186211867 }
1186311868
11869+ if (BuiltinID == AArch64::BI__addx18byte ||
11870+ BuiltinID == AArch64::BI__addx18word ||
11871+ BuiltinID == AArch64::BI__addx18dword ||
11872+ BuiltinID == AArch64::BI__addx18qword ||
11873+ BuiltinID == AArch64::BI__incx18byte ||
11874+ BuiltinID == AArch64::BI__incx18word ||
11875+ BuiltinID == AArch64::BI__incx18dword ||
11876+ BuiltinID == AArch64::BI__incx18qword) {
11877+ llvm::Type *IntTy;
11878+ bool isIncrement;
11879+ switch (BuiltinID) {
11880+ case AArch64::BI__incx18byte:
11881+ IntTy = Int8Ty;
11882+ isIncrement = true;
11883+ break;
11884+ case AArch64::BI__incx18word:
11885+ IntTy = Int16Ty;
11886+ isIncrement = true;
11887+ break;
11888+ case AArch64::BI__incx18dword:
11889+ IntTy = Int32Ty;
11890+ isIncrement = true;
11891+ break;
11892+ case AArch64::BI__incx18qword:
11893+ IntTy = Int64Ty;
11894+ isIncrement = true;
11895+ break;
11896+ default:
11897+ IntTy = ConvertType(E->getArg(1)->getType());
11898+ isIncrement = false;
11899+ break;
11900+ }
11901+ // Process the args first
11902+ Value *OffsetArg = EmitScalarExpr(E->getArg(0));
11903+ Value *ValToAdd =
11904+ isIncrement ? ConstantInt::get(IntTy, 1) : EmitScalarExpr(E->getArg(1));
11905+
11906+ // Read x18 as i8*
11907+ llvm::Value *X18 = readX18AsPtr(*this);
11908+
11909+ // Load x18 + offset
11910+ Value *Offset = Builder.CreateZExt(OffsetArg, Int64Ty);
11911+ Value *Ptr = Builder.CreateGEP(Int8Ty, X18, Offset);
11912+ LoadInst *Load = Builder.CreateAlignedLoad(IntTy, Ptr, CharUnits::One());
11913+
11914+ // Add values
11915+ Value *AddResult = Builder.CreateAdd(Load, ValToAdd);
11916+
11917+ // Store val at x18 + offset
11918+ StoreInst *Store =
11919+ Builder.CreateAlignedStore(AddResult, Ptr, CharUnits::One());
11920+ return Store;
11921+ }
11922+
1186411923 if (BuiltinID == AArch64::BI_CopyDoubleFromInt64 ||
1186511924 BuiltinID == AArch64::BI_CopyFloatFromInt32 ||
1186611925 BuiltinID == AArch64::BI_CopyInt32FromFloat ||
0 commit comments