Skip to content

Commit 6f8e855

Browse files
authored
[clang][bytecode] Implement __builtin_ai32_addcarryx* (#111671)
1 parent 390943f commit 6f8e855

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

clang/lib/AST/ByteCode/Function.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,10 @@ class Function final {
222222
return ParamOffsets[ParamIndex];
223223
}
224224

225+
PrimType getParamType(unsigned ParamIndex) const {
226+
return ParamTypes[ParamIndex];
227+
}
228+
225229
private:
226230
/// Construct a function representing an actual function.
227231
Function(Program &P, FunctionDeclTy Source, unsigned ArgSize,

clang/lib/AST/ByteCode/InterpBuiltin.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
4150
PrimType 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+
12761318
static 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

Comments
 (0)