@@ -244,6 +244,19 @@ static Value *handleAsDoubleBuiltin(CodeGenFunction &CGF, const CallExpr *E) {
244
244
return CGF.Builder.CreateBitCast(BitVec, ResultType);
245
245
}
246
246
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
+
247
260
/// getBuiltinLibFunction - Given a builtin id for a function like
248
261
/// "__builtin_fabsf", return a Function* for "fabsf".
249
262
llvm::Constant *CodeGenModule::getBuiltinLibFunction(const FunctionDecl *FD,
@@ -11820,47 +11833,93 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
11820
11833
BuiltinID == AArch64::BI__writex18word ||
11821
11834
BuiltinID == AArch64::BI__writex18dword ||
11822
11835
BuiltinID == AArch64::BI__writex18qword) {
11836
+ // Process the args first
11837
+ Value *OffsetArg = EmitScalarExpr(E->getArg(0));
11838
+ Value *DataArg = EmitScalarExpr(E->getArg(1));
11839
+
11823
11840
// 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);
11832
11842
11833
11843
// Store val at x18 + offset
11834
- Value *Offset = Builder.CreateZExt(EmitScalarExpr(E->getArg(0)) , Int64Ty);
11844
+ Value *Offset = Builder.CreateZExt(OffsetArg , Int64Ty);
11835
11845
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());
11838
11848
return Store;
11839
11849
}
11840
11850
11841
11851
if (BuiltinID == AArch64::BI__readx18byte ||
11842
11852
BuiltinID == AArch64::BI__readx18word ||
11843
11853
BuiltinID == AArch64::BI__readx18dword ||
11844
11854
BuiltinID == AArch64::BI__readx18qword) {
11845
- llvm::Type *IntTy = ConvertType(E->getType());
11855
+ // Process the args first
11856
+ Value *OffsetArg = EmitScalarExpr(E->getArg(0));
11846
11857
11847
11858
// 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);
11856
11860
11857
11861
// Load x18 + offset
11858
- Value *Offset = Builder.CreateZExt(EmitScalarExpr(E->getArg(0)) , Int64Ty);
11862
+ Value *Offset = Builder.CreateZExt(OffsetArg , Int64Ty);
11859
11863
Value *Ptr = Builder.CreateGEP(Int8Ty, X18, Offset);
11864
+ llvm::Type *IntTy = ConvertType(E->getType());
11860
11865
LoadInst *Load = Builder.CreateAlignedLoad(IntTy, Ptr, CharUnits::One());
11861
11866
return Load;
11862
11867
}
11863
11868
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
+
11864
11923
if (BuiltinID == AArch64::BI_CopyDoubleFromInt64 ||
11865
11924
BuiltinID == AArch64::BI_CopyFloatFromInt32 ||
11866
11925
BuiltinID == AArch64::BI_CopyInt32FromFloat ||
0 commit comments