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