@@ -38,6 +38,15 @@ static T getParam(const InterpFrame *Frame, unsigned Index) {
3838 return Frame->getParam <T>(Offset);
3939}
4040
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+
4150PrimType getIntPrimType (const InterpState &S) {
4251 const TargetInfo &TI = S.getASTContext ().getTargetInfo ();
4352 unsigned IntWidth = TI.getIntWidth ();
@@ -1273,6 +1282,39 @@ static bool interp__builtin_ia32_pext(InterpState &S, CodePtr OpPC,
12731282 return true ;
12741283}
12751284
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+
12761318static bool interp__builtin_os_log_format_buffer_size (InterpState &S,
12771319 CodePtr OpPC,
12781320 const InterpFrame *Frame,
@@ -1898,6 +1940,14 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
18981940 return false ;
18991941 break ;
19001942
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+
19011951 case Builtin::BI__builtin_os_log_format_buffer_size:
19021952 if (!interp__builtin_os_log_format_buffer_size (S, OpPC, Frame, F, Call))
19031953 return false ;
0 commit comments