@@ -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,
@@ -11836,47 +11849,93 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
11836
11849
BuiltinID == AArch64::BI__writex18word ||
11837
11850
BuiltinID == AArch64::BI__writex18dword ||
11838
11851
BuiltinID == AArch64::BI__writex18qword) {
11852
+ // Process the args first
11853
+ Value *OffsetArg = EmitScalarExpr(E->getArg(0));
11854
+ Value *DataArg = EmitScalarExpr(E->getArg(1));
11855
+
11839
11856
// 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);
11848
11858
11849
11859
// Store val at x18 + offset
11850
- Value *Offset = Builder.CreateZExt(EmitScalarExpr(E->getArg(0)) , Int64Ty);
11860
+ Value *Offset = Builder.CreateZExt(OffsetArg , Int64Ty);
11851
11861
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());
11854
11864
return Store;
11855
11865
}
11856
11866
11857
11867
if (BuiltinID == AArch64::BI__readx18byte ||
11858
11868
BuiltinID == AArch64::BI__readx18word ||
11859
11869
BuiltinID == AArch64::BI__readx18dword ||
11860
11870
BuiltinID == AArch64::BI__readx18qword) {
11861
- llvm::Type *IntTy = ConvertType(E->getType());
11871
+ // Process the args first
11872
+ Value *OffsetArg = EmitScalarExpr(E->getArg(0));
11862
11873
11863
11874
// 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);
11872
11876
11873
11877
// Load x18 + offset
11874
- Value *Offset = Builder.CreateZExt(EmitScalarExpr(E->getArg(0)) , Int64Ty);
11878
+ Value *Offset = Builder.CreateZExt(OffsetArg , Int64Ty);
11875
11879
Value *Ptr = Builder.CreateGEP(Int8Ty, X18, Offset);
11880
+ llvm::Type *IntTy = ConvertType(E->getType());
11876
11881
LoadInst *Load = Builder.CreateAlignedLoad(IntTy, Ptr, CharUnits::One());
11877
11882
return Load;
11878
11883
}
11879
11884
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
+
11880
11939
if (BuiltinID == AArch64::BI_CopyDoubleFromInt64 ||
11881
11940
BuiltinID == AArch64::BI_CopyFloatFromInt32 ||
11882
11941
BuiltinID == AArch64::BI_CopyInt32FromFloat ||
0 commit comments