/* -*- 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.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/NPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): */ // CodeGenerator.cpp // // Scott M. Silver // Peter Desantis // // A code generator is a loose organization of code which // finds roots in a given control node of BURG-labellable expression // trees. The trees are labelled, and an emit routine is called // for each labelled tree. #define INCLUDE_EMITTER #include "CpuInfo.h" #include "Vector.h" #include "Primitives.h" #include "CodeGenerator.h" #include "Burg.h" #include "Scheduler.h" #include "ControlNodes.h" #include "InstructionEmitter.h" #ifdef USE_VISUALIZER #include "IGVisualizer.h" #endif // sFakeRegPrimitives // // A table of primitives which are used as the children // of primitives which are defined to be leaves in a // control node. They are indexed by DataKind, ie // vkInt, etc... //Primitive sFakeReg_V(coReg_V); // no such register Primitive sFakeReg_I(coReg_I, 0); Primitive sFakeReg_L(coReg_L, 0); Primitive sFakeReg_F(coReg_F, 0); Primitive sFakeReg_D(coReg_D, 0); Primitive sFakeReg_P(coReg_A, 0); Primitive sFakeReg_C(coReg_C, 0); Primitive sFakeReg_M(coReg_M, 0); // no such register //Primitive sFakeReg_T(coReg_T); // no such register Primitive* sFakeRegPrimitives[nValueKinds] = { NULL, // no such register &sFakeReg_I, &sFakeReg_L, &sFakeReg_F, &sFakeReg_D, &sFakeReg_P, &sFakeReg_C, &sFakeReg_M, NULL // no such register }; // This needs to be here because of header include problems. CodeGenerator::CodeGenerator(Pool& inPool, MdEmitter& inEmitter) : mPool(inPool), mEmitter(inEmitter) #ifdef USE_VISUALIZER ,mVisualizer(*(new IGVisualizer())) #endif { } // generate // // Emit argumetns for the begin node. // Find all roots of trees in inControlNode // Label each root // Call the emitter to emit for each root void CodeGenerator:: generate(ControlNode& inControlNode) { Vector roots; // First find all the roots in this control node findRoots(inControlNode, roots); if (inControlNode.hasControlKind(ckBegin)) mEmitter.emitArguments(inControlNode.getBeginExtra()); else { // for each root label, and emit code RootPair* curRoot; for (curRoot = roots.begin(); curRoot < roots.end(); curRoot++) { label(*(curRoot->root)); emit(curRoot->root, 1); } } // schedule and output instructions LinearInstructionScheduler scheduler; scheduler.schedule(roots, inControlNode); #ifdef IGVISUALIZE mVisualizer.addRoots(roots); #endif } #ifdef IGVISUALIZE void CodeGenerator:: visualize() { mVisualizer.visualize(); } #endif // label // // Label the treee rooted at inPrimitive void CodeGenerator:: label(Primitive& inPrimitive) { burm_label(&inPrimitive); } // emit // // Actually traverse the primitives and emit instructions // once labelled. void CodeGenerator:: emit(Primitive* p, int goalnt) { int eruleno = burm_rule(p->getBurgState(), goalnt); short* nts = burm_nts[eruleno]; Primitive* kids[10]; int i; if (eruleno == 0) { trespass("BURG matching -- no cover"); } burm_kids(p, eruleno, kids); for (i = 0; nts[i]; i++) emit(kids[i], nts[i]); mEmitter.emitPrimitive(*p, eruleno); } // instructionUseToInstruction // // Move to the definer of this use. // // There are three cases. // // 1. If there is a defining Instruction // in the Use, then that is the defining Instruction. // // 2. If the Use is Store or Cond Use, then if there is a // defining Instruction then it will be attached to the // DP at ID 0. // // 3. If the Use is a Register Use, then there must be some // VR associated with the Use. The Instruction which defines // the VR is the defining Instruction for this Use. // // It is possible that the result of 2 or 3 could be NULL after // emitting for a given ControlNode. This means that the resource // (outgoing edge) has not been defined, and is in another ControlNode. // (or there was a programmer error, how do we detect which one) Instruction* CodeGenerator:: instructionUseToInstruction(InstructionUse& inIUse) { Instruction* nextInsn; if (inIUse.src != NULL) nextInsn = inIUse.src; else { switch (inIUse.kind) { case udStore: case udCond: if (inIUse.name.dp != NULL) { if (inIUse.name.dp->getInstructionAnnotation() != NULL) nextInsn = inIUse.name.dp->getInstructionAnnotation(); else nextInsn = NULL; } else nextInsn = NULL; break; case udRegister: //assert(inIUse.name.vr); can't check this because it's a VR Pointer nextInsn = inIUse.name.vr.getVirtualRegister().getDefiningInstruction(); break; case udNone: nextInsn = NULL; break; case udOrder: nextInsn = inIUse.name.instruction; break; case udUninitialized: assert(false); default: assert(false); } } return (nextInsn); } // getExpressionLeftChild // // The BURG implementation of LEFT_CHILD Primitive* CodeGenerator:: getExpressionLeftChild(Primitive* inPrimitive) { assert(inPrimitive); bool hasIncomingStore = inPrimitive->hasCategory(pcLd) || inPrimitive->hasCategory(pcSt) || inPrimitive->hasCategory(pcCall); DataConsumer* leftConsumer = &inPrimitive->nthInput(hasIncomingStore); return (consumerToPrimitive(inPrimitive, leftConsumer)); } // getExpressionRightChild // // Grab the right child of inPrimitive, skip over store edges // [The BURG implementation of RIGHT_CHILD] Primitive* CodeGenerator:: getExpressionRightChild(Primitive* inPrimitive) { assert(inPrimitive); DataConsumer* rightConsumer; bool hasIncomingStore = inPrimitive->hasCategory(pcLd) || inPrimitive->hasCategory(pcSt) || inPrimitive->hasCategory(pcCall); rightConsumer = &inPrimitive->nthInput(1 + hasIncomingStore); return (consumerToPrimitive(inPrimitive, rightConsumer)); } // consumerToPrimitive // // Takes a consumer of a value and finds the primitive which produces // the value that is consumed. // // an example: // // isLeaf // // child parent // P2 pr <-> co P1 // // co: inConsumer // P1: inPrimitive // // co is a leaf edge if // // 1. co and pr (or P1 and P2) are in different control nodes -> return fake reg primitive // 2. P2 is a root -> return fake reg primitive // // else // // return P2 Primitive* CodeGenerator:: consumerToPrimitive(Primitive* inPrimitive, DataConsumer* inConsumer) { // if it's already a fake reg primitive it has no children if (inPrimitive->getOperation() >= coReg_V && inPrimitive->getOperation() <= coReg_I) return NULL; else if (inConsumer->isConstant()) return (sFakeRegPrimitives[inConsumer->getKind()]); DataNode& consumerChildNode = inConsumer->getVariable(); Primitive* consumerChildPrimitive; // extract P2 as above if (!consumerChildNode.hasCategory(pcPhi)) consumerChildPrimitive = &Primitive::cast(consumerChildNode); else return (sFakeRegPrimitives[inConsumer->getKind()]); // phi node // now perform the check to see if this edge connects to a "leaf" edge if (consumerChildPrimitive->getContainer() != inPrimitive->getContainer() || isRoot(*consumerChildPrimitive)) { return (sFakeRegPrimitives[inConsumer->getKind()]); } else return (consumerChildPrimitive); } // search through all primitives in a control node // return a vector of all the roots of expression trees void CodeGenerator:: findRoots(ControlNode& inControlNode, Vector& outRoots) { DoublyLinkedList& primitives = inControlNode.getPrimitives(); for (DoublyLinkedList::iterator i = primitives.begin(); !primitives.done(i); i = primitives.advance(i)) { Primitive& prim = primitives.get(i); RootKind root = isRoot(prim); if ((root == rkRoot) || (root == rkPrimary)) { RootPair newRoot; newRoot.root = &prim; //prim.setRoot(true); if(root == rkPrimary) newRoot.isPrimary = true; else newRoot.isPrimary = false; outRoots.append(newRoot); } // root member of prim defaults to false } } // 1. is a primitive which is a pcIfCond (if or switch) OR // 2. is a primitive which is a pcResult OR // 3. is a primitive all of whose outputs are in a different control node from its own OR // 4. is an interior primitive whose inputs are shared by two primitives in the same (cse) // 5. is a primitive connected to another pcCall/pcSysCall primitive // In cases 1 2 3 the root is primary RootKind CodeGenerator:: isRoot(Primitive& inPrimitive) { bool isAtleastRoot = false; // 1 or 2 if (inPrimitive.hasCategory(pcIfCond) || inPrimitive.hasCategory(pcResult) || inPrimitive.hasCategory(pcSwitch)) goto isRoot_rkPrimary; // 3 DataNode* curEdge; isAtleastRoot = inPrimitive.hasCategory(pcSt) || inPrimitive.hasCategory(pcCall) || inPrimitive.hasCategory(pcSysCall); // all dp's primitive's containers hooked to curEdge must not be in same control node as inPrimitive's container for (curEdge = inPrimitive.getOutgoingEdgesBegin(); curEdge < inPrimitive.getOutgoingEdgesEnd(); curEdge++) { const DoublyLinkedList& consumers = curEdge->getConsumers(); for ( DoublyLinkedList::iterator curConsumer = consumers.begin(); !consumers.done(curConsumer); curConsumer = consumers.advance(curConsumer)) { ControlNode* curConsumerContainer; // container of parentNode DataNode* node; // parentNode (node which consume's inPrimitive's input) node = &consumers.get(curConsumer).getNode(); // can ignore LdV because it has another incoming edge isAtleastRoot |= ((node->getOutgoingEdgesEnd() - node->getOutgoingEdgesBegin() > 1) || (node->hasCategory(pcCall) || node->hasCategory(pcSysCall))); if (node->hasCategory(pcCall)) { DataNode* calleeAddress = &node->nthInput(1).getVariable(); if (&inPrimitive == calleeAddress) { isAtleastRoot = false; goto isRoot_rkNotRoot; } } curConsumerContainer = node->getContainer(); if (!node->hasCategory(pcPhi) && curConsumerContainer == inPrimitive.getContainer()) { // If there are any consumers in the current container, then the primitive is a root // iff it produces a cse----look for another consumer in the primitive's container // Continue looking through the curEdge curConsumer = consumers.advance(curConsumer); for ( ; !consumers.done(curConsumer); curConsumer = consumers.advance(curConsumer)) { node = &consumers.get(curConsumer).getNode(); if (node->hasCategory(pcCall) || node->hasCategory(pcSysCall)) goto isRoot_rkRoot; curConsumerContainer = node->getContainer(); if (curConsumerContainer == inPrimitive.getContainer()) // cse found. goto isRoot_rkRoot; } curEdge++; // Now continue looking through the other edges for (;curEdge < inPrimitive.getOutgoingEdgesEnd(); curEdge++) { const DoublyLinkedList& consumers = curEdge->getConsumers(); for ( DoublyLinkedList::iterator thisConsumer = consumers.begin(); !consumers.done(thisConsumer); thisConsumer = consumers.advance(thisConsumer)) { node = &consumers.get(thisConsumer).getNode(); if (node->hasCategory(pcCall) || node->hasCategory(pcSysCall)) goto isRoot_rkRoot; curConsumerContainer = node->getContainer(); if (curConsumerContainer == inPrimitive.getContainer()) // cse found goto isRoot_rkRoot; } } // We did not find a cse => not a root goto isRoot_rkNotRoot; } } } // if we passed through the above loop, 3. must have been met (fall through to rkPrimary) isRoot_rkPrimary: return (rkPrimary); isRoot_rkRoot: return (rkRoot); isRoot_rkNotRoot: return (isAtleastRoot ? rkRoot : rkNotRoot); }