clang: lib/AST/ByteCode/InterpFrame.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

21

22using namespace clang;

24

27 ArgSize(0), Args(nullptr), FrameOffset(0) {}

28

32 RetPC(RetPC), ArgSize(ArgSize), Args(static_cast<char *>(S.Stk.top())),

33 FrameOffset(S.Stk.size()) {

34 if (!Func)

35 return;

36

37 unsigned FrameSize = Func->getFrameSize();

38 if (FrameSize == 0)

39 return;

40

41 Locals = std::make_unique<char[]>(FrameSize);

42 for (auto &Scope : Func->scopes()) {

44 new (localBlock(Local.Offset)) Block(S.Ctx.getEvalID(), Local.Desc);

45

46

47 new (localInlineDesc(Local.Offset)) InlineDescriptor(Local.Desc);

48 }

49 }

50}

51

53 unsigned VarArgSize)

54 : InterpFrame(S, Func, S.Current, RetPC, Func->getArgSize() + VarArgSize) {

55

56

57

58

59

60

61 if (Func->hasRVO()) {

62

63 }

64

65 if (Func->hasThisPointer())

66 ThisPointerOffset = Func->hasRVO() ? sizeof(Pointer) : 0;

67}

68

70 for (auto &Param : Params)

71 S.deallocate(reinterpret_cast<Block *>(Param.second.get()));

72

73

74

75

77}

78

80 if (!Func)

81 return;

82 for (auto &Scope : Func->scopes()) {

84 S.deallocate(localBlock(Local.Offset));

85 }

86 }

87}

88

90 if (!Func)

91 return;

92

93 for (auto &Local : Func->getScope(Idx).locals()) {

94 localBlock(Local.Offset)->invokeCtor();

95 }

96}

97

99 assert(Func);

100

101

102

103

104

105

106 localInlineDesc(Idx)->IsActive = true;

107}

108

110 for (auto &Local : Func->getScope(Idx).locals_reverse()) {

111 S.deallocate(localBlock(Local.Offset));

112 }

113}

114

115template

118 if constexpr (std::is_same_v<Pointer, T>) {

120 V.toAPValue(ASTCtx).printPretty(OS, ASTCtx, Ty);

121 else {

122 if (std::optional RValue = V.toRValue(ASTCtx, Ty))

123 RValue->printPretty(OS, ASTCtx, Ty);

124 else

125 OS << "...";

126 }

127 } else {

128 V.toAPValue(ASTCtx).printPretty(OS, ASTCtx, Ty);

129 }

130}

131

133 if (F->isLambdaStaticInvoker())

134 return true;

135

139 return true;

140

141 if (const auto *MD = dyn_cast(FD);

142 MD && MD->getParent()->isAnonymousStructOrUnion())

143 return true;

144

145 if (const auto *Ctor = dyn_cast(FD);

146 Ctor && Ctor->isDefaulted() && Ctor->isTrivial() &&

147 Ctor->isCopyOrMoveConstructor() && Ctor->inits().empty())

148 return true;

149

150 return false;

151}

152

154

156 return;

157

162 if (Func->hasThisPointer() && IsMemberCall) {

163 if (const auto *MCE = dyn_cast_if_present(CallExpr)) {

164 const Expr *Object = MCE->getImplicitObjectArgument();

165 Object->printPretty(OS, nullptr,

166 S.getASTContext().getPrintingPolicy(),

167 0);

168 if (Object->getType()->isPointerType())

169 OS << "->";

170 else

171 OS << ".";

172 } else if (const auto *OCE =

173 dyn_cast_if_present(CallExpr)) {

174 OCE->getArg(0)->printPretty(OS, nullptr,

175 S.getASTContext().getPrintingPolicy(),

176 0);

177 OS << ".";

178 } else if (const auto *M = dyn_cast(F)) {

180 S.getASTContext().getLValueReferenceType(

181 S.getASTContext().getCanonicalTagType(M->getParent())));

182 OS << ".";

183 }

184 }

185

187 false);

188 OS << '(';

189 unsigned Off = 0;

190

192 Off += Func->hasThisPointer() ? primSize(PT_Ptr) : 0;

193

194 for (unsigned I = 0, N = F->getNumParams(); I < N; ++I) {

196

197 PrimType PrimTy = S.Ctx.classify(Ty).value_or(PT_Ptr);

198

199 TYPE_SWITCH(PrimTy, print(OS, stackRef(Off), S.getASTContext(), Ty));

201 if (I + 1 != N)

202 OS << ", ";

203 }

204 OS << ")";

205}

206

209 if (SourceRange NullRange = S.getRange(nullptr, {}); NullRange.isValid())

210 return NullRange;

211 return S.EvalLocation;

212 }

213

214

216 if (C->RetPC)

217 continue;

219 S.getRange(C->Caller->Func, C->RetPC - sizeof(uintptr_t));

221 return CallRange;

222 }

223 return S.EvalLocation;

224}

225

227 if (!Func)

228 return nullptr;

229 return Func->getDecl();

230}

231

233 assert(Offset < Func->getFrameSize() && "Invalid local offset.");

234 return Pointer(localBlock(Offset));

235}

236

238 return localBlock(Offset);

239}

240

242

243 if (auto Pt = Params.find(Off); Pt != Params.end())

244 return Pointer(reinterpret_cast<Block *>(Pt->second.get()));

245

247

248

249 const auto &Desc = Func->getParamDescriptor(Off);

250 size_t BlockSize = sizeof(Block) + Desc.second->getAllocSize();

251 auto Memory = std::make_unique<char[]>(BlockSize);

252 auto *B = new (Memory.get()) Block(S.Ctx.getEvalID(), Desc.second);

253 B->invokeCtor();

254

255

256 TYPE_SWITCH(Desc.first, new (B->data()) T(stackRef(Off)));

257

258

259 Params.insert({Off, std::move(Memory)});

261}

262

264 assert(F);

265

266 if (F->isConstructor() || F->isDestructor())

267 return true;

268

269 return !F->getDecl()->isImplicit();

270}

271

273

274

276 return Caller->getSource(RetPC);

277

278

279

282 return Caller->getSource(RetPC);

284}

285

288 return Caller->getExpr(RetPC);

289

290 return S.getExpr(Func, PC);

291}

292

295 return Caller->getLocation(RetPC);

296

297 return S.getLocation(Func, PC);

298}

299

302 return Caller->getRange(RetPC);

303

304 return S.getRange(Func, PC);

305}

306

308 if (!Func)

309 return false;

311 if (DC->isStdNamespace())

312 return true;

313

314 return false;

315}

Defines the clang::ASTContext interface.

Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....

Defines the clang::Expr interface and subclasses for C++ expressions.

static void print(llvm::raw_ostream &OS, const T &V, ASTContext &ASTCtx, QualType Ty)

Definition InterpFrame.cpp:116

static bool shouldSkipInBacktrace(const Function *F)

Definition InterpFrame.cpp:132

static bool funcHasUsableBody(const Function *F)

Definition InterpFrame.cpp:263

#define TYPE_SWITCH(Expr, B)

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).

DeclContext - This is used only as base class of specific decl types that can act as declaration cont...

DeclContext * getParent()

getParent - Returns the containing DeclContext.

OverloadedOperatorKind getCXXOverloadedOperator() const

If this name is the name of an overloadable operator in C++ (e.g., operator+), retrieve the kind of o...

This represents one expression.

Represents a function declaration or definition.

const ParmVarDecl * getParamDecl(unsigned i) const

unsigned getNumParams() const

Return the number of parameters this function must have based on its FunctionType.

void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const override

Appends a human-readable name for this declaration into the given stream.

DeclarationName getDeclName() const

Get the actual, stored name of the declaration, which may be a special name.

A (possibly-)qualified type.

Encodes a location in the source.

A trivial tuple used to represent a source range.

bool isPointerOrReferenceType() const

A memory block, either on the stack or in the heap.

Pointer into the code segment.

InterpFrame(InterpState &S)

Bottom Frame.

Definition InterpFrame.cpp:25

const Expr * getExpr(CodePtr PC) const

Definition InterpFrame.cpp:286

void destroyScopes()

Definition InterpFrame.cpp:79

InterpFrame * Caller

The frame of the previous function.

SourceInfo getSource(CodePtr PC) const

Map a location to a source.

Definition InterpFrame.cpp:272

CodePtr getRetPC() const

Returns the return address of the frame.

void enableLocal(unsigned Idx)

Definition InterpFrame.cpp:98

Block * getLocalBlock(unsigned Offset) const

Definition InterpFrame.cpp:237

SourceLocation getLocation(CodePtr PC) const

Definition InterpFrame.cpp:293

~InterpFrame()

Destroys the frame, killing all live pointers to stack slots.

Definition InterpFrame.cpp:69

const Pointer & getThis() const

Returns the 'this' pointer.

const Function * getFunction() const

Returns the current function.

SourceRange getRange(CodePtr PC) const

Definition InterpFrame.cpp:300

bool isBottomFrame() const

Pointer getLocalPointer(unsigned Offset) const

Returns a pointer to a local variables.

Definition InterpFrame.cpp:232

void destroy(unsigned Idx)

Invokes the destructors for a scope.

Definition InterpFrame.cpp:109

Pointer getParamPointer(unsigned Offset)

Returns a pointer to an argument - lazily creates a block.

Definition InterpFrame.cpp:241

const FunctionDecl * getCallee() const override

Returns the caller.

Definition InterpFrame.cpp:226

bool isStdFunction() const

Definition InterpFrame.cpp:307

void initScope(unsigned Idx)

Definition InterpFrame.cpp:89

SourceRange getCallRange() const override

Returns the location of the call to the frame.

Definition InterpFrame.cpp:207

void describe(llvm::raw_ostream &OS) const override

Describes the frame with arguments for diagnostic purposes.

Definition InterpFrame.cpp:153

A pointer to a memory block, live or dead.

llvm::iterator_range< LocalVectorTy::const_iterator > locals() const

Describes the statement/declaration an opcode was generated from.

constexpr size_t align(size_t Size)

Aligns a size to the pointer alignment.

PrimType

Enumeration of the primitive types of the VM.

size_t primSize(PrimType Type)

Returns the size of a primitive type in bytes.

The JSON file list parser is used to communicate input to InstallAPI.

bool isa(CodeGen::Address addr)

if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))

nullptr

This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...

@ Result

The result type of a method or function.

const FunctionProtoType * T

U cast(CodeGen::Address addr)

__UINTPTR_TYPE__ uintptr_t

An unsigned integer type with the property that any valid pointer to void can be converted to this ty...

Inline descriptor embedded in structures and arrays.