blob: eb3d72823a5eda5a1efe9b9e77631786d9bc115b [file] [log] [blame]
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifdef DEBUG
#include <stdarg.h>
#include <time.h>
#include "IonBuilder.h"
#include "Ion.h"
#include "C1Spewer.h"
#include "MIRGraph.h"
#include "LIR.h"
#include "LinearScan.h"
#include "jsscriptinlines.h"
using namespace js;
using namespace js::jit;
bool
C1Spewer::init(const char *path)
{
spewout_ = fopen(path, "w");
return (spewout_ != NULL);
}
void
C1Spewer::beginFunction(MIRGraph *graph, HandleScript script)
{
if (!spewout_)
return;
this->graph = graph;
this->script = script;
fprintf(spewout_, "begin_compilation\n");
if (script) {
fprintf(spewout_, " name \"%s:%d\"\n", script->filename(), script->lineno);
fprintf(spewout_, " method \"%s:%d\"\n", script->filename(), script->lineno);
} else {
fprintf(spewout_, " name \"asm.js compilation\"\n");
fprintf(spewout_, " method \"asm.js compilation\"\n");
}
fprintf(spewout_, " date %d\n", (int)time(NULL));
fprintf(spewout_, "end_compilation\n");
}
void
C1Spewer::spewPass(const char *pass)
{
if (!spewout_)
return;
fprintf(spewout_, "begin_cfg\n");
fprintf(spewout_, " name \"%s\"\n", pass);
for (MBasicBlockIterator block(graph->begin()); block != graph->end(); block++)
spewPass(spewout_, *block);
fprintf(spewout_, "end_cfg\n");
fflush(spewout_);
}
void
C1Spewer::spewIntervals(const char *pass, LinearScanAllocator *regalloc)
{
if (!spewout_)
return;
fprintf(spewout_, "begin_intervals\n");
fprintf(spewout_, " name \"%s\"\n", pass);
size_t nextId = 0x4000;
for (MBasicBlockIterator block(graph->begin()); block != graph->end(); block++)
spewIntervals(spewout_, *block, regalloc, nextId);
fprintf(spewout_, "end_intervals\n");
fflush(spewout_);
}
void
C1Spewer::endFunction()
{
}
void
C1Spewer::finish()
{
if (spewout_)
fclose(spewout_);
}
static void
DumpDefinition(FILE *fp, MDefinition *def)
{
fprintf(fp, " ");
fprintf(fp, "%u %u ", def->id(), unsigned(def->useCount()));
def->printName(fp);
fprintf(fp, " ");
def->printOpcode(fp);
fprintf(fp, " <|@\n");
}
static void
DumpLIR(FILE *fp, LInstruction *ins)
{
fprintf(fp, " ");
fprintf(fp, "%d ", ins->id());
ins->print(fp);
fprintf(fp, " <|@\n");
}
void
C1Spewer::spewIntervals(FILE *fp, LinearScanAllocator *regalloc, LInstruction *ins, size_t &nextId)
{
for (size_t k = 0; k < ins->numDefs(); k++) {
VirtualRegister *vreg = &regalloc->vregs[ins->getDef(k)->virtualRegister()];
for (size_t i = 0; i < vreg->numIntervals(); i++) {
LiveInterval *live = vreg->getInterval(i);
if (live->numRanges()) {
fprintf(fp, "%d object \"", (i == 0) ? vreg->id() : int32_t(nextId++));
fprintf(fp, "%s", live->getAllocation()->toString());
fprintf(fp, "\" %d -1", vreg->id());
for (size_t j = 0; j < live->numRanges(); j++) {
fprintf(fp, " [%d, %d[", live->getRange(j)->from.pos(),
live->getRange(j)->to.pos());
}
for (UsePositionIterator usePos(live->usesBegin()); usePos != live->usesEnd(); usePos++)
fprintf(fp, " %d M", usePos->pos.pos());
fprintf(fp, " \"\"\n");
}
}
}
}
void
C1Spewer::spewIntervals(FILE *fp, MBasicBlock *block, LinearScanAllocator *regalloc, size_t &nextId)
{
LBlock *lir = block->lir();
if (!lir)
return;
for (size_t i = 0; i < lir->numPhis(); i++)
spewIntervals(fp, regalloc, lir->getPhi(i), nextId);
for (LInstructionIterator ins = lir->begin(); ins != lir->end(); ins++)
spewIntervals(fp, regalloc, *ins, nextId);
}
void
C1Spewer::spewPass(FILE *fp, MBasicBlock *block)
{
fprintf(fp, " begin_block\n");
fprintf(fp, " name \"B%d\"\n", block->id());
fprintf(fp, " from_bci -1\n");
fprintf(fp, " to_bci -1\n");
fprintf(fp, " predecessors");
for (uint32_t i = 0; i < block->numPredecessors(); i++) {
MBasicBlock *pred = block->getPredecessor(i);
fprintf(fp, " \"B%d\"", pred->id());
}
fprintf(fp, "\n");
fprintf(fp, " successors");
for (uint32_t i = 0; i < block->numSuccessors(); i++) {
MBasicBlock *successor = block->getSuccessor(i);
fprintf(fp, " \"B%d\"", successor->id());
}
fprintf(fp, "\n");
fprintf(fp, " xhandlers\n");
fprintf(fp, " flags\n");
if (block->lir() && block->lir()->begin() != block->lir()->end()) {
fprintf(fp, " first_lir_id %d\n", block->lir()->firstId());
fprintf(fp, " last_lir_id %d\n", block->lir()->lastId());
}
fprintf(fp, " begin_states\n");
if (block->entryResumePoint()) {
fprintf(fp, " begin_locals\n");
fprintf(fp, " size %d\n", (int)block->numEntrySlots());
fprintf(fp, " method \"None\"\n");
for (uint32_t i = 0; i < block->numEntrySlots(); i++) {
MDefinition *ins = block->getEntrySlot(i);
fprintf(fp, " ");
fprintf(fp, "%d ", i);
if (ins->isUnused())
fprintf(fp, "unused");
else
ins->printName(fp);
fprintf(fp, "\n");
}
fprintf(fp, " end_locals\n");
}
fprintf(fp, " end_states\n");
fprintf(fp, " begin_HIR\n");
for (MPhiIterator phi(block->phisBegin()); phi != block->phisEnd(); phi++)
DumpDefinition(fp, *phi);
for (MInstructionIterator i(block->begin()); i != block->end(); i++)
DumpDefinition(fp, *i);
fprintf(fp, " end_HIR\n");
if (block->lir()) {
fprintf(fp, " begin_LIR\n");
for (size_t i = 0; i < block->lir()->numPhis(); i++)
DumpLIR(fp, block->lir()->getPhi(i));
for (LInstructionIterator i(block->lir()->begin()); i != block->lir()->end(); i++)
DumpLIR(fp, *i);
fprintf(fp, " end_LIR\n");
}
fprintf(fp, " end_block\n");
}
#endif /* DEBUG */