@@ -38,6 +38,15 @@ static T getParam(const InterpFrame *Frame, unsigned Index) {
38
38
return Frame->getParam <T>(Offset);
39
39
}
40
40
41
+ // static APSInt getAPSIntParam(InterpStack &Stk, size_t Offset = 0) {
42
+ static APSInt getAPSIntParam (const InterpFrame *Frame, unsigned Index) {
43
+ APSInt R;
44
+ unsigned Offset = Frame->getFunction ()->getParamOffset (Index);
45
+ INT_TYPE_SWITCH (Frame->getFunction ()->getParamType (Index),
46
+ R = Frame->getParam <T>(Offset).toAPSInt ());
47
+ return R;
48
+ }
49
+
41
50
PrimType getIntPrimType (const InterpState &S) {
42
51
const TargetInfo &TI = S.getASTContext ().getTargetInfo ();
43
52
unsigned IntWidth = TI.getIntWidth ();
@@ -1273,6 +1282,39 @@ static bool interp__builtin_ia32_pext(InterpState &S, CodePtr OpPC,
1273
1282
return true ;
1274
1283
}
1275
1284
1285
+ static bool interp__builtin_ia32_addcarry_subborrow (InterpState &S,
1286
+ CodePtr OpPC,
1287
+ const InterpFrame *Frame,
1288
+ const Function *Func,
1289
+ const CallExpr *Call) {
1290
+ unsigned BuiltinOp = Func->getBuiltinID ();
1291
+ APSInt CarryIn = getAPSIntParam (Frame, 0 );
1292
+ APSInt LHS = getAPSIntParam (Frame, 1 );
1293
+ APSInt RHS = getAPSIntParam (Frame, 2 );
1294
+
1295
+ bool IsAdd = BuiltinOp == clang::X86::BI__builtin_ia32_addcarryx_u32 ||
1296
+ BuiltinOp == clang::X86::BI__builtin_ia32_addcarryx_u64;
1297
+
1298
+ unsigned BitWidth = LHS.getBitWidth ();
1299
+ unsigned CarryInBit = CarryIn.ugt (0 ) ? 1 : 0 ;
1300
+ APInt ExResult =
1301
+ IsAdd ? (LHS.zext (BitWidth + 1 ) + (RHS.zext (BitWidth + 1 ) + CarryInBit))
1302
+ : (LHS.zext (BitWidth + 1 ) - (RHS.zext (BitWidth + 1 ) + CarryInBit));
1303
+
1304
+ APInt Result = ExResult.extractBits (BitWidth, 0 );
1305
+ APSInt CarryOut =
1306
+ APSInt (ExResult.extractBits (1 , BitWidth), /* IsUnsigned=*/ true );
1307
+
1308
+ Pointer &CarryOutPtr = S.Stk .peek <Pointer>();
1309
+ QualType CarryOutType = Call->getArg (3 )->getType ()->getPointeeType ();
1310
+ PrimType CarryOutT = *S.getContext ().classify (CarryOutType);
1311
+ assignInteger (CarryOutPtr, CarryOutT, APSInt (Result, true ));
1312
+
1313
+ pushInteger (S, CarryOut, Call->getType ());
1314
+
1315
+ return true ;
1316
+ }
1317
+
1276
1318
static bool interp__builtin_os_log_format_buffer_size (InterpState &S,
1277
1319
CodePtr OpPC,
1278
1320
const InterpFrame *Frame,
@@ -1898,6 +1940,14 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
1898
1940
return false ;
1899
1941
break ;
1900
1942
1943
+ case clang::X86::BI__builtin_ia32_addcarryx_u32:
1944
+ case clang::X86::BI__builtin_ia32_addcarryx_u64:
1945
+ case clang::X86::BI__builtin_ia32_subborrow_u32:
1946
+ case clang::X86::BI__builtin_ia32_subborrow_u64:
1947
+ if (!interp__builtin_ia32_addcarry_subborrow (S, OpPC, Frame, F, Call))
1948
+ return false ;
1949
+ break ;
1950
+
1901
1951
case Builtin::BI__builtin_os_log_format_buffer_size:
1902
1952
if (!interp__builtin_os_log_format_buffer_size (S, OpPC, Frame, F, Call))
1903
1953
return false ;
0 commit comments