mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-08 12:37:37 +00:00
195 lines
5.3 KiB
C++
195 lines
5.3 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
// Backend.cpp
|
|
//
|
|
// Scott M. Silver
|
|
//
|
|
// Translate a ControlGraph into native code
|
|
|
|
|
|
#if defined(DEBUG) && (defined(WIN32) || defined(USE_MESA)) && defined(IGVISUALIZE)
|
|
#define USE_VISUALIZER
|
|
#endif
|
|
|
|
#ifdef USE_VISUALIZER
|
|
#define IGVISUALIZE_ONLY(x) x
|
|
#include "IGVisualizer.h"
|
|
#else
|
|
#define IGVISUALIZE_ONLY(x)
|
|
#endif
|
|
|
|
#include "Backend.h"
|
|
#include "ControlGraph.h"
|
|
#include "JavaVM.h"
|
|
|
|
#define INCLUDE_EMITTER
|
|
#include "CpuInfo.h"
|
|
#include "RegisterAllocator.h"
|
|
#include "CodeGenerator.h"
|
|
#include "CGScheduler.h"
|
|
#include "NativeFormatter.h"
|
|
|
|
#include "FieldOrMethod.h"
|
|
#include "LogModule.h"
|
|
|
|
#if DEBUG_laurentm
|
|
#include "ControlNodeScheduler.h"
|
|
#endif
|
|
|
|
static void
|
|
explodeImmediatePrimitives(ControlGraph &cg);
|
|
|
|
#ifdef DEBUG_LOG
|
|
static void
|
|
printInstructions(LogModuleObject inLogObject, ControlNode& inControlNode);
|
|
|
|
static void
|
|
printInstructions(LogModuleObject inLogObject, ControlNode& inControlNode)
|
|
{
|
|
InstructionList& instructions = inControlNode.getInstructions();
|
|
|
|
for(InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i))
|
|
{
|
|
instructions.get(i).printDebug(inLogObject);
|
|
UT_OBJECTLOG(inLogObject, PR_LOG_ALWAYS, ("\n"));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
UT_DEFINE_LOG_MODULE(Backend);
|
|
|
|
void*
|
|
translateControlGraphToNative(ControlGraph& inControlGraph, Method& inMethod)
|
|
{
|
|
VirtualRegisterManager vrMan(inControlGraph.pool);
|
|
MdEmitter emitter(inControlGraph.pool, vrMan);
|
|
CodeGenerator codeGenerator(inControlGraph.pool, emitter);
|
|
|
|
// break out constants
|
|
explodeImmediatePrimitives(inControlGraph);
|
|
|
|
// * generate code
|
|
DoublyLinkedList<ControlNode>::iterator j;
|
|
for (j = inControlGraph.controlNodes.begin(); !inControlGraph.controlNodes.done(j); j = inControlGraph.controlNodes.advance(j))
|
|
{
|
|
ControlNode &cn = inControlGraph.controlNodes.get(j);
|
|
|
|
codeGenerator.generate(cn);
|
|
|
|
#ifdef PRINT_INSTRUCTIONS_BEFORE_REGALLOC
|
|
cn.printRef(UT_LOG_MODULE(Backend));
|
|
|
|
UT_SET_LOG_LEVEL(Backend, PR_LOG_DEBUG);
|
|
printInstructions(UT_LOG_MODULE(Backend), cn);
|
|
#endif
|
|
}
|
|
|
|
// If the debugger is enabled, generate pc2bci table
|
|
if (VM::debugger.getEnabled()) {
|
|
// Use an arbitrary number - needs to be set appropriately later
|
|
inMethod.getPC2Bci().setSize(1000);
|
|
}
|
|
|
|
// * register allocation
|
|
if (!inControlGraph.dfsListIsValid())
|
|
inControlGraph.dfsSearch();
|
|
if (!inControlGraph.lndListIsValid())
|
|
inControlGraph.lndSearch();
|
|
|
|
RegisterAllocator registerAllocator(inControlGraph.pool, inControlGraph.dfsList, inControlGraph.lndList, inControlGraph.nNodes, vrMan, emitter);
|
|
registerAllocator.allocateRegisters();
|
|
|
|
#ifdef PRINT_INSTRUCTIONS_AFTER_REGALLOC
|
|
for (j = inControlGraph.controlNodes.begin(); !inControlGraph.controlNodes.done(j); j = inControlGraph.controlNodes.advance(j))
|
|
{
|
|
ControlNode &cn = inControlGraph.controlNodes.get(j);
|
|
|
|
printInstructions(UT_LOG_MODULE(Backend), cn);
|
|
}
|
|
#endif
|
|
|
|
|
|
#ifdef NEW_CG_SCHEDULER
|
|
ControlNodeScheduler cns(inControlGraph.pool, inControlGraph.dfsList, inControlGraph.nNodes);
|
|
ControlNode** scheduledNodes = cns.getScheduledNodes();
|
|
#else // NEW_CG_SCHEDULER
|
|
ControlGraphScheduler cgs(inControlGraph, emitter);
|
|
ControlNode** scheduledNodes = cgs.scheduleNodes();
|
|
#endif // NEW_CG_SCHEDULER
|
|
|
|
// * output to memory
|
|
NativeFormatter formatter(emitter, scheduledNodes, inControlGraph.nNodes);
|
|
|
|
void* func = formatter.format(inMethod);
|
|
|
|
IGVISUALIZE_ONLY(codeGenerator.visualize();)
|
|
return (func);
|
|
}
|
|
|
|
|
|
//
|
|
// Transform all immediate operations into
|
|
// operations which no longer intern a constant
|
|
//
|
|
// For example:
|
|
//
|
|
// vi2 = AddI_I 6, vi1
|
|
//
|
|
// becomes
|
|
//
|
|
// vi1 = Const_I 6
|
|
// vi3 = Add_I vi1, vi2
|
|
//
|
|
static void
|
|
explodeImmediatePrimitives(ControlGraph &cg)
|
|
{
|
|
cg.dfsSearch();
|
|
ControlNode **dfsList = cg.dfsList;
|
|
ControlNode **pcn = dfsList + cg.nNodes;
|
|
|
|
while (pcn != dfsList)
|
|
{
|
|
ControlNode &cn = **--pcn;
|
|
|
|
// Search the primitives backwards; explode primitives as necessary
|
|
DoublyLinkedList<Primitive> &primitives = cn.getPrimitives();
|
|
DoublyLinkedList<Primitive>::iterator primIter = primitives.end();
|
|
while (!primitives.done(primIter))
|
|
{
|
|
Primitive &p = primitives.get(primIter);
|
|
primIter = primitives.retreat(primIter);
|
|
|
|
// loop through all consumers of p; if a consumer is constant create
|
|
// a new PrimConst node, and attach it to p
|
|
DataConsumer* input;
|
|
for (input = p.getInputsBegin(); input < p.getInputsEnd(); input++)
|
|
{
|
|
if (input->isConstant() && isRegOrMemKind(input->getKind()))
|
|
{
|
|
PrimConst *prim = new(cn.getPrimitivePool())
|
|
PrimConst(input->getKind(), input->getConstant(),
|
|
p.getBytecodeIndex());
|
|
|
|
input->setVariable(*prim);
|
|
cn.appendPrimitive(*prim);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|