Skip to content

Commit

Permalink
[clang][Interp] Pass CallExpr to builtin functions
Browse files Browse the repository at this point in the history
For some builtins, we need to do quite a bit of type checking ourselves,
so pass the call expression along. This way we can inspect arguments,
expected return value, etc.

Differential Revision: https://reviews.llvm.org/D155545
  • Loading branch information
tbaederr committed Aug 17, 2023
1 parent 2829486 commit 8a25145
Show file tree
Hide file tree
Showing 4 changed files with 14 additions and 11 deletions.
2 changes: 1 addition & 1 deletion clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1824,7 +1824,7 @@ bool ByteCodeExprGen<Emitter>::VisitBuiltinCallExpr(const CallExpr *E) {
return false;
}

if (!this->emitCallBI(Func, E))
if (!this->emitCallBI(Func, E, E))
return false;

QualType ReturnType = E->getCallReturnType(Ctx.getASTContext());
Expand Down
8 changes: 5 additions & 3 deletions clang/lib/AST/Interp/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,8 @@ bool CheckFloatResult(InterpState &S, CodePtr OpPC, APFloat::opStatus Status);
bool Interpret(InterpState &S, APValue &Result);

/// Interpret a builtin function.
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F);
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
const CallExpr *Call);

enum class ArithOp { Add, Sub };

Expand Down Expand Up @@ -1741,13 +1742,14 @@ inline bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func) {
return Call(S, OpPC, Func);
}

inline bool CallBI(InterpState &S, CodePtr &PC, const Function *Func) {
inline bool CallBI(InterpState &S, CodePtr &PC, const Function *Func,
const CallExpr *CE) {
auto NewFrame = std::make_unique<InterpFrame>(S, Func, PC);

InterpFrame *FrameBefore = S.Current;
S.Current = NewFrame.get();

if (InterpretBuiltin(S, PC, Func)) {
if (InterpretBuiltin(S, PC, Func, CE)) {
NewFrame.release();
return true;
}
Expand Down
12 changes: 6 additions & 6 deletions clang/lib/AST/Interp/InterpBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,10 +240,9 @@ static bool interp__builtin_isnormal(InterpState &S, CodePtr OpPC,
/// second one is an integral value.
static bool interp__builtin_isfpclass(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const Function *Func) {
const Expr *E = S.Current->getExpr(OpPC);
const CallExpr *CE = cast<CallExpr>(E);
PrimType FPClassArgT = *S.getContext().classify(CE->getArgs()[1]->getType());
const Function *Func,
const CallExpr *Call) {
PrimType FPClassArgT = *S.getContext().classify(Call->getArg(1)->getType());
APSInt FPClassArg = peekToAPSInt(S.Stk, FPClassArgT);
const Floating &F =
S.Stk.peek<Floating>(align(primSize(FPClassArgT) + primSize(PT_Float)));
Expand Down Expand Up @@ -300,7 +299,8 @@ static bool interp__builtin_fabs(InterpState &S, CodePtr OpPC,
return true;
}

bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F) {
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
const CallExpr *Call) {
InterpFrame *Frame = S.Current;
APValue Dummy;

Expand Down Expand Up @@ -394,7 +394,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F) {
return Ret<PT_Sint32>(S, OpPC, Dummy);
break;
case Builtin::BI__builtin_isfpclass:
if (interp__builtin_isfpclass(S, OpPC, Frame, F))
if (interp__builtin_isfpclass(S, OpPC, Frame, F, Call))
return Ret<PT_Sint32>(S, OpPC, Dummy);
break;
case Builtin::BI__builtin_fpclassify:
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/AST/Interp/Opcodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ def ArgFltSemantics : ArgType { let Name = "const llvm::fltSemantics *"; }
def ArgRoundingMode : ArgType { let Name = "llvm::RoundingMode"; }
def ArgLETD: ArgType { let Name = "const LifetimeExtendedTemporaryDecl *"; }
def ArgCastKind : ArgType { let Name = "CastKind"; }
def ArgCallExpr : ArgType { let Name = "const CallExpr *"; }

//===----------------------------------------------------------------------===//
// Classes of types instructions operate on.
Expand Down Expand Up @@ -188,7 +189,7 @@ def CallVirt : Opcode {
}

def CallBI : Opcode {
let Args = [ArgFunction];
let Args = [ArgFunction, ArgCallExpr];
let Types = [];
}

Expand Down

0 comments on commit 8a25145

Please sign in to comment.