Arquivos
hhvm/hphp/runtime/vm/verifier/pretty.cpp
T

167 linhas
5.7 KiB
C++

/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/runtime/vm/verifier/pretty.h"
#include <iostream>
#include <iomanip>
#include <stdio.h>
#include "folly/Format.h"
#include "hphp/runtime/vm/repo.h"
#include "hphp/runtime/vm/verifier/util.h"
#include "hphp/runtime/vm/verifier/cfg.h"
namespace HPHP {
namespace Verifier {
void printInstr(const Unit* unit, PC pc) {
Opcode* op = (Opcode*)pc;
std::cout << " " << std::setw(4) << (pc - unit->entry()) << ":" <<
(isCF(pc) ? "C":" ") <<
(isTF(pc) ? "T":" ") <<
(isFF(pc) ? "F":" ") <<
std::setw(3) << instrLen(op) <<
" " << instrToString(op, unit) << std::endl;
}
std::string blockToString(const Block* b, const Graph* g, const Unit* u) {
std::stringstream out;
out << "B" << b->id << ":" << u->offsetOf((Opcode*)b->start) <<
"-" << u->offsetOf((Opcode*)b->last) <<
" rpo=" << b->rpo_id <<
" succ=";
for (BlockPtrRange j = succBlocks(b); !j.empty(); ) {
const Block* s = j.popFront();
out << "B" << s->id << (j.empty() ? "" : ",");
}
if (g->exn_cap) {
out << " exns=";
for (BlockPtrRange j = exnBlocks(g, b); !j.empty(); ) {
const Block* s = j.popFront();
out << "B" << s->id << (j.empty() ? "" : ",");
}
}
return out.str();
}
void printFPI(const Func* func) {
const Unit* unit = func->unit();
PC bc = unit->entry();
for (Range<FixedVector<FPIEnt> > i(func->fpitab()); !i.empty(); ) {
const FPIEnt& fpi = i.popFront();
printf(" FPI[%d:%d] fpoff=%d parent=%d fpiDepth=%d\n",
fpiBase(fpi, bc), fpiPast(fpi, bc), fpi.m_fpOff, fpi.m_parentIndex,
fpi.m_fpiDepth);
}
}
void printBlocks(const Func* func, const Graph* g) {
const Unit* unit = func->unit();
func->prettyPrint(std::cout);
printFPI(func);
for (LinearBlocks i(g->first_linear, 0); !i.empty(); i.popFront()) {
const Block* b = i.front();
std::cout << blockToString(b, g, unit) << std::endl;
for (InstrRange j(b->start, b->end); !j.empty(); ) {
printInstr(unit, j.popFront());
}
}
std::cout << std::endl;
}
void printGml(const Unit* unit) {
string filename = unit->md5().toString() + ".gml";
FILE* file = fopen(filename.c_str(), "w");
if (!file) {
std::cerr << "Couldn't open GML output file " << filename << std::endl;
return;
}
int nextid = 1;
fprintf(file, "graph [\n"
" hierarchic 1\n"
" directed 1\n");
for (AllFuncs i(unit); !i.empty(); ) {
const Func* func = i.popFront();
Arena scratch;
GraphBuilder builder(scratch, func);
const Graph* g = builder.build();
int gid = nextid++;
fprintf(file, "node [ isGroup 1 id %d ]\n", gid);
// nodes
for (LinearBlocks j = linearBlocks(g); !j.empty();) {
const Block* b = j.popFront();
std::stringstream strbuf;
unit->prettyPrint(strbuf,
Unit::PrintOpts().range(unit->offsetOf(b->start),
unit->offsetOf(b->end)));
std::string code = strbuf.str();
for (int i = 0, n = code.size(); i < n; ++i) {
if (code[i] == '"') code[i] = '\'';
}
fprintf(file, " node [ id %d gid %d\n"
" graphics [ type \"roundrectangle\" ]"
" LabelGraphics ["
" anchor \"e\""
" alignment \"left\""
" fontName \"Consolas\"\n"
" text \"%s\"\n"
" ]\n"
" ]\n",
nextid + b->id, gid, code.c_str());
}
// edges
for (LinearBlocks j = linearBlocks(g); !j.empty();) {
const Block* b = j.popFront();
for (BlockPtrRange k = succBlocks(b); !k.empty();) {
const Block* s = k.popFront();
fprintf(file, " edge [ source %d target %d ]\n",
nextid + b->id, nextid + s->id);
}
for (BlockPtrRange k = exnBlocks(g, b); !k.empty();) {
const Block* s = k.popFront();
fprintf(file, " edge [ source %d target %d"
" graphics [ style \"dotted\" ]"
" ]\n",
nextid + b->id, nextid + s->id);
}
}
nextid += g->block_count + 1;
}
fprintf(file, "]\n");
fclose(file);
}
void verify_error(const Unit* unit,
const Func* func,
const char* fmt,
...) {
char buf[1024];
va_list args;
va_start(args, fmt);
vsnprintf(buf, sizeof buf, fmt, args);
va_end(args);
fprintf(stderr,
"Verification Error (unit %s%s): %s",
unit->filepath()->data(),
func != nullptr
? folly::format(" func {}", func->fullName()->data()).str().c_str()
: "",
buf);
}
}} // namespace HPHP::VM