Changeset View
Standalone View
clang/lib/AST/Interp/Interp.h
Show First 20 Lines • Show All 134 Lines • ▼ Show 20 Lines | if (LHS.isSigned() && LHS.isMin() && RHS.isNegative() && RHS.isMinusOne()) { | ||||
return false; | return false; | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
/// Interpreter entry point. | /// Interpreter entry point. | ||||
bool Interpret(InterpState &S, APValue &Result); | bool Interpret(InterpState &S, APValue &Result); | ||||
bool InterpretBuiltin(InterpState &S, CodePtr PC, unsigned BuiltinID); | |||||
enum class ArithOp { Add, Sub }; | enum class ArithOp { Add, Sub }; | ||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||
// Add, Sub, Mul | // Add, Sub, Mul | ||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||
template <typename T, bool (*OpFW)(T, T, unsigned, T *), | template <typename T, bool (*OpFW)(T, T, unsigned, T *), | ||||
template <typename U> class OpAP> | template <typename U> class OpAP> | ||||
▲ Show 20 Lines • Show All 1,151 Lines • ▼ Show 20 Lines | inline bool Call(InterpState &S, CodePtr &PC, const Function *Func) { | ||||
APValue CallResult; | APValue CallResult; | ||||
// Note that we cannot assert(CallResult.hasValue()) here since | // Note that we cannot assert(CallResult.hasValue()) here since | ||||
// Ret() above only sets the APValue if the curent frame doesn't | // Ret() above only sets the APValue if the curent frame doesn't | ||||
// have a caller set. | // have a caller set. | ||||
if (Interpret(S, CallResult)) { | if (Interpret(S, CallResult)) { | ||||
NewFrame.release(); // Frame was delete'd already. | NewFrame.release(); // Frame was delete'd already. | ||||
assert(S.Current == FrameBefore); | assert(S.Current == FrameBefore); | ||||
// For constructors, check that all fields have been initialized. | // For constructors, check that all fields have been initialized. | ||||
if (Func->isConstructor() && !CheckCtorCall(S, PC, ThisPtr)) | if (Func->isConstructor() && !CheckCtorCall(S, PC, ThisPtr)) | ||||
erichkeane: `directly` reads oddly here? Do you mean the 'immediately' definition of this? | |||||
Yes, that was the purpose. I can reword it. tbaeder: Yes, that was the purpose. I can reword it. | |||||
Not Done ReplyInline ActionsRather than the 'if'/'else' pair, do we just want to immediately return on the failed builtin? erichkeane: Rather than the 'if'/'else' pair, do we just want to immediately return on the failed builtin? | |||||
Sure, that's possible. I guess this ties into the question of whether to use a different opcode for builtin functions; but so far I have found builtin calls to be too similar to regular ones, esp. since they don't have a special AST node. tbaeder: Sure, that's possible. I guess this ties into the question of whether to use a different opcode… | |||||
return false; | return false; | ||||
Not Done ReplyInline ActionsWhat is going on here? Why is this not a leak? erichkeane: What is going on here? Why is this not a leak? | |||||
The current frame is deleted when successfully returning the value of the function, this happens in the Ret (and RetVoid) function in Interp.cpp. No opinion on whether that's the best way to do it though. tbaeder: The current frame is `delete`d when successfully returning the value of the function, this… | |||||
Not Done ReplyInline ActionsI really dont like doing it this way, I see we're doing it the same in 1366, but if we're expecting someone else to delete a unique-ptr, we should give them ownership of the whole unique-ptr. This mechanism is just obscuring the ownership semantics that unique_ptr is supposed to imply. erichkeane: I really dont like doing it this way, I see we're doing it the same in 1366, but if we're… | |||||
I blame @aaron.ballman :) I'm gonna write it on my list and create a follow-up patch. tbaeder: I blame @aaron.ballman :)
I'm gonna write it on my list and create a follow-up patch. | |||||
return true; | return true; | ||||
} | } | ||||
// Interpreting the function failed somehow. Reset to | // Interpreting the function failed somehow. Reset to | ||||
// previous state. | // previous state. | ||||
S.Current = FrameBefore; | S.Current = FrameBefore; | ||||
return false; | return false; | ||||
} | } | ||||
inline bool CallBI(InterpState &S, CodePtr &PC, const Function *Func) { | |||||
auto NewFrame = std::make_unique<InterpFrame>(S, Func, PC); | |||||
InterpFrame *FrameBefore = S.Current; | |||||
S.Current = NewFrame.get(); | |||||
if (InterpretBuiltin(S, PC, Func->getBuiltinID())) { | |||||
NewFrame.release(); | |||||
We don't have to update S.Current? shafik: We don't have to update `S.Current`? | |||||
Nope, Ret does that. tbaeder: Nope, `Ret` does that. | |||||
return true; | |||||
} | |||||
S.Current = FrameBefore; | |||||
return false; | |||||
} | |||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||
// Read opcode arguments | // Read opcode arguments | ||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||
template <typename T> inline T ReadArg(InterpState &S, CodePtr &OpPC) { | template <typename T> inline T ReadArg(InterpState &S, CodePtr &OpPC) { | ||||
if constexpr (std::is_pointer<T>::value) { | if constexpr (std::is_pointer<T>::value) { | ||||
uint32_t ID = OpPC.read<uint32_t>(); | uint32_t ID = OpPC.read<uint32_t>(); | ||||
return reinterpret_cast<T>(S.P.getNativePointer(ID)); | return reinterpret_cast<T>(S.P.getNativePointer(ID)); | ||||
Show All 9 Lines |
directly reads oddly here? Do you mean the 'immediately' definition of this?