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

1

2

3

4

5

6

7

8

9

10

11

12

30#include "llvm/Support/Compiler.h"

31#include "llvm/Support/Format.h"

32

33using namespace clang;

35

37 if constexpr (std::is_pointer_v) {

38 uint32_t ID = OpPC.read<uint32_t>();

39 return reinterpret_cast<T>(P.getNativePointer(ID));

40 } else {

41 return OpPC.read<T>();

42 }

43}

44

48 return F;

49}

50

51template <>

55 return I;

56}

57

58template <>

62 return I;

63}

64

68 return I;

69}

70

71LLVM_DUMP_METHOD void Function::dump() const { dump(llvm::errs()); }

72

73LLVM_DUMP_METHOD void Function::dump(llvm::raw_ostream &OS) const {

74 {

75 ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_GREEN, true});

76 OS << getName() << " " << (const void *)this << "\n";

77 }

78 OS << "frame size: " << getFrameSize() << "\n";

79 OS << "arg size: " << getArgSize() << "\n";

80 OS << "rvo: " << hasRVO() << "\n";

81 OS << "this arg: " << hasThisPointer() << "\n";

82

83 auto PrintName = [&OS](const char *Name) {

84 OS << Name;

85 long N = 30 - strlen(Name);

86 if (N > 0)

87 OS.indent(N);

88 };

89

90 for (CodePtr Start = getCodeBegin(), PC = Start; PC != getCodeEnd();) {

91 size_t Addr = PC - Start;

92 auto Op = PC.read<Opcode>();

93 OS << llvm::format("%8d", Addr) << " ";

94 switch (Op) {

95#define GET_DISASM

96#include "Opcodes.inc"

97#undef GET_DISASM

98 }

99 }

100}

101

103

105 switch (T) {

107 return "Sint8";

109 return "Uint8";

111 return "Sint16";

113 return "Uint16";

115 return "Sint32";

117 return "Uint32";

119 return "Sint64";

121 return "Uint64";

123 return "IntAP";

125 return "IntAPS";

127 return "Bool";

129 return "Float";

131 return "Ptr";

133 return "FnPtr";

135 return "MemberPtr";

137 return "FixedPoint";

138 }

139 llvm_unreachable("Unhandled PrimType");

140}

141

142LLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream &OS) const {

143 {

144 ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_RED, true});

145 OS << "\n:: Program\n";

146 }

147

148 {

149 ColorScope SC(OS, true, {llvm::raw_ostream::WHITE, true});

150 OS << "Total memory : " << Allocator.getTotalMemory() << " bytes\n";

151 OS << "Global Variables: " << Globals.size() << "\n";

152 }

153 unsigned GI = 0;

154 for (const Global *G : Globals) {

155 const Descriptor *Desc = G->block()->getDescriptor();

157

158 OS << GI << ": " << (const void *)G->block() << " ";

159 {

164 OS << (GP.isInitialized() ? "initialized " : "uninitialized ");

165 }

166 Desc->dump(OS);

167

169 if (const auto *MTE =

170 dyn_cast_if_present(Desc->asExpr());

171 MTE && MTE->getLifetimeExtendedTemporaryDecl()) {

173 MTE->getLifetimeExtendedTemporaryDecl()->getValue()) {

174 OS << " (global temporary value: ";

175 {

176 ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_MAGENTA, true});

177 std::string VStr;

178 llvm::raw_string_ostream SS(VStr);

180

181 for (unsigned I = 0; I != VStr.size(); ++I) {

182 if (VStr[I] == '\n')

183 VStr[I] = ' ';

184 }

185 VStr.pop_back();

186 OS << VStr;

187 }

188 OS << ')';

189 }

190 }

191 }

192

193 OS << "\n";

195 OS << " ";

196 {

197 ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_CYAN, false});

199 }

201 OS << "\n";

202 }

203 ++GI;

204 }

205

206 {

207 ColorScope SC(OS, true, {llvm::raw_ostream::WHITE, true});

208 OS << "Functions: " << Funcs.size() << "\n";

209 }

210 for (const auto &Func : Funcs) {

211 Func.second->dump();

212 }

213 for (const auto &Anon : AnonFuncs) {

214 Anon->dump();

215 }

216}

217

219 dump(llvm::errs());

220 llvm::errs() << '\n';

221}

222

224

225 {

226 ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});

227 if (const auto *ND = dyn_cast_if_present(asDecl()))

228 ND->printQualifiedName(OS);

230 OS << "Expr " << (const void *)asExpr();

231 }

232

233

235 OS << " primitive-array";

237 OS << " composite-array";

239 OS << " union";

241 OS << " record";

243 OS << " primitive";

244

246 OS << " zero-size-array";

248 OS << " unknown-size-array";

249

251 OS << " dummy";

252}

253

255 {

256 ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});

257 OS << "InlineDescriptor " << (const void *)this << "\n";

258 }

259 OS << "Offset: " << Offset << "\n";

260 OS << "IsConst: " << IsConst << "\n";

261 OS << "IsInitialized: " << IsInitialized << "\n";

262 OS << "IsBase: " << IsBase << "\n";

263 OS << "IsActive: " << IsActive << "\n";

264 OS << "InUnion: " << InUnion << "\n";

266 OS << "Desc: ";

269 else

270 OS << "nullptr";

271 OS << "\n";

272}

273

275 unsigned Indent) const {

276 unsigned Spaces = Indent * 2;

277 {

278 ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});

279 OS.indent(Spaces);

282 else

283 OS << "Frame (Depth: " << getDepth() << ")";

284 OS << "\n";

285 }

286 OS.indent(Spaces) << "Function: " << getFunction();

288 OS << " (" << F->getName() << ")";

289 }

290 OS << "\n";

291 OS.indent(Spaces) << "This: " << getThis() << "\n";

292 OS.indent(Spaces) << "RVO: " << getRVOPtr() << "\n";

293 OS.indent(Spaces) << "Depth: " << Depth << "\n";

294 OS.indent(Spaces) << "ArgSize: " << ArgSize << "\n";

295 OS.indent(Spaces) << "Args: " << (void *)Args << "\n";

296 OS.indent(Spaces) << "FrameOffset: " << FrameOffset << "\n";

297 OS.indent(Spaces) << "FrameSize: " << (Func ? Func->getFrameSize() : 0)

298 << "\n";

299

301 F->dump(OS, Indent + 1);

302 }

303}

304

305LLVM_DUMP_METHOD void Record::dump(llvm::raw_ostream &OS, unsigned Indentation,

306 unsigned Offset) const {

307 unsigned Indent = Indentation * 2;

308 OS.indent(Indent);

309 {

310 ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});

312 }

313

314 unsigned I = 0;

315 for (const Record::Base &B : bases()) {

316 OS.indent(Indent) << "- Base " << I << ". Offset " << (Offset + B.Offset)

317 << "\n";

318 B.R->dump(OS, Indentation + 1, Offset + B.Offset);

319 ++I;

320 }

321

322 I = 0;

323 for (const Record::Field &F : fields()) {

324 OS.indent(Indent) << "- Field " << I << ": ";

325 {

326 ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_RED, true});

327 OS << F.Decl->getName();

328 }

329 OS << ". Offset " << (Offset + F.Offset) << "\n";

330 ++I;

331 }

332

333 I = 0;

335 OS.indent(Indent) << "- Virtual Base " << I << ". Offset "

336 << (Offset + B.Offset) << "\n";

337 B.R->dump(OS, Indentation + 1, Offset + B.Offset);

338 ++I;

339 }

340}

341

342LLVM_DUMP_METHOD void Block::dump(llvm::raw_ostream &OS) const {

343 {

344 ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_BLUE, true});

345 OS << "Block " << (const void *)this;

346 }

347 OS << " (";

348 Desc->dump(OS);

349 OS << ")\n";

350 unsigned NPointers = 0;

351 for (const Pointer *P = Pointers; P; P = P->Next) {

352 ++NPointers;

353 }

354 OS << " Pointers: " << NPointers << "\n";

355 OS << " Dead: " << IsDead << "\n";

356 OS << " Static: " << IsStatic << "\n";

357 OS << " Extern: " << IsExtern << "\n";

358 OS << " Initialized: " << IsInitialized << "\n";

359}

360

362 assert(Ctx);

363 auto &OS = llvm::errs();

365

366 switch (Kind) {

368 OS << "Empty\n";

369 break;

371 OS << "RValue: ";

372 std::get(Value).dump(OS, ASTCtx);

373 break;

375 assert(Source);

377 if (const auto *D = dyn_cast<const Decl *>(Source)) {

378 if (const auto *VD = dyn_cast(D))

379 SourceType = VD->getType();

380 } else if (const auto *E = dyn_cast<const Expr *>(Source)) {

382 }

383

384 OS << "LValue: ";

385 if (const auto *P = std::get_if(&Value))

386 P->toAPValue(ASTCtx).printPretty(OS, ASTCtx, SourceType);

387 else if (const auto *FP = std::get_if(&Value))

388 FP->toAPValue(ASTCtx).printPretty(OS, ASTCtx, SourceType);

389 OS << "\n";

390 break;

391 }

393 OS << "Invalid\n";

394 break;

396 OS << "Valid\n";

397 break;

398 }

399}

static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)

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

static const char * primTypeToString(PrimType T)

FixedPoint ReadArg< FixedPoint >(Program &P, CodePtr &OpPC)

Floating ReadArg< Floating >(Program &P, CodePtr &OpPC)

static T ReadArg(Program &P, CodePtr &OpPC)

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

#define TYPE_SWITCH(Expr, B)

static std::string getName(const CallEvent &Call)

APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...

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

A (possibly-)qualified type.

Pointer into the code segment.

std::enable_if_t<!std::is_pointer< T >::value, T > read()

Reads data and advances the pointer.

ASTContext & getASTContext() const

Returns the AST context.

void dump() const

Dump to stderr.

Wrapper around fixed point types.

static FixedPoint deserialize(const std::byte *Buff)

size_t bytesToSerialize() const

static Floating deserialize(const std::byte *Buff)

size_t bytesToSerialize() const

unsigned getFrameSize() const

Returns the size of the function's local stack.

static IntegralAP< Signed > deserialize(const std::byte *Buff)

size_t bytesToSerialize() const

Frame storing local variables.

InterpFrame * Caller

The frame of the previous function.

const Pointer & getThis() const

Returns the 'this' pointer.

const Function * getFunction() const

Returns the current function.

unsigned getDepth() const

const Pointer & getRVOPtr() const

Returns the RVO pointer, if the Function has one.

const FunctionDecl * getCallee() const override

Returns the caller.

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

Describes the frame with arguments for diagnostic purposes.

A pointer to a memory block, live or dead.

bool isInitialized() const

Checks if an object was initialized.

The program contains and links the bytecode for all functions.

Pointer getPtrGlobal(unsigned Idx) const

Returns a pointer to a global.

void dump() const

Dumps the disassembled bytecode to llvm::errs().

const std::string getName() const

Returns the name of the underlying declaration.

llvm::iterator_range< const_virtual_iter > virtual_bases() const

llvm::iterator_range< const_base_iter > bases() const

llvm::iterator_range< const_field_iter > fields() const

constexpr size_t align(size_t Size)

Aligns a size to the pointer alignment.

PrimType

Enumeration of the primitive types of the VM.

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

const FunctionProtoType * T

Describes a memory block created by an allocation site.

bool isPrimitive() const

Checks if the descriptor is of a primitive.

bool isCompositeArray() const

Checks if the descriptor is of an array of composites.

const Decl * asDecl() const

bool isDummy() const

Checks if this is a dummy descriptor.

bool isUnknownSizeArray() const

Checks if the descriptor is of an array of unknown size.

bool isPrimitiveArray() const

Checks if the descriptor is of an array of primitives.

bool isZeroSizeArray() const

Checks if the descriptor is of an array of zero size.

PrimType getPrimType() const

bool isRecord() const

Checks if the descriptor is of a record.

const bool IsTemporary

Flag indicating if the block is a temporary.

bool isUnion() const

Checks if the descriptor is of a union.

const Expr * asExpr() const

unsigned IsActive

Flag indicating if the field is the active member of a union.

unsigned IsBase

Flag indicating if the field is an embedded base class.

unsigned InUnion

Flat indicating if this field is in a union (even if nested).

unsigned Offset

Offset inside the structure/array.

unsigned IsInitialized

For primitive fields, it indicates if the field was initialized.

unsigned IsConst

Flag indicating if the storage is constant or not.

unsigned IsFieldMutable

Flag indicating if the field is mutable (if in a record).