Example #1
0
bool
Program::emitBinary(struct nv50_ir_prog_info *info)
{
   CodeEmitter *emit = target->getCodeEmitter(progType);

   emit->prepareEmission(this);

   if (dbgFlags & NV50_IR_DEBUG_BASIC)
      this->print();

   if (!binSize) {
      code = NULL;
      return false;
   }
   code = reinterpret_cast<uint32_t *>(MALLOC(binSize));
   if (!code)
      return false;
   emit->setCodeLocation(code, binSize);

   for (ArrayList::Iterator fi = allFuncs.iterator(); !fi.end(); fi.next()) {
      Function *fn = reinterpret_cast<Function *>(fi.get());

      assert(emit->getCodeSize() == fn->binPos);

      for (int b = 0; b < fn->bbCount; ++b)
         for (Instruction *i = fn->bbArray[b]->getEntry(); i; i = i->next)
            emit->emitInstruction(i);
   }
   info->bin.relocData = emit->getRelocInfo();

   delete emit;
   return true;
}
Example #2
0
bool
Program::emitBinary(struct nv50_ir_prog_info *info)
{
   CodeEmitter *emit = target->getCodeEmitter(progType);

   emit->prepareEmission(this);

   if (dbgFlags & NV50_IR_DEBUG_BASIC)
      this->print();

   if (!binSize) {
      code = NULL;
      return false;
   }
   code = reinterpret_cast<uint32_t *>(MALLOC(binSize));
   if (!code)
      return false;
   emit->setCodeLocation(code, binSize);
   info->bin.instructions = 0;

   for (ArrayList::Iterator fi = allFuncs.iterator(); !fi.end(); fi.next()) {
      Function *fn = reinterpret_cast<Function *>(fi.get());

      assert(emit->getCodeSize() == fn->binPos);

      for (int b = 0; b < fn->bbCount; ++b) {
         for (Instruction *i = fn->bbArray[b]->getEntry(); i; i = i->next) {
            emit->emitInstruction(i);
            info->bin.instructions++;
            if (i->sType == TYPE_F64 || i->dType == TYPE_F64)
               info->io.fp64 = true;
         }
      }
   }
   info->bin.relocData = emit->getRelocInfo();
   info->bin.interpData = emit->getInterpInfo();

   emitSymbolTable(info);

   // the nvc0 driver will print the binary iself together with the header
   if ((dbgFlags & NV50_IR_DEBUG_BASIC) && getTarget()->getChipset() < 0xc0)
      emit->printBinary();

   delete emit;
   return true;
}
Example #3
0
// This function is called for the LHS of an assignment
// assume that ac contains the value to be stored
void ExpressionNode::GenAssignLHS(CodeEmitter &e, int virtualRegister, int toff) {
	int localToff;	

	localToff = toff;
	// Assign virtual register to 'real' register
	int actualRegister = virtualRegister%MAX_EXP_REGISTERS+FIRST_REG_OFFSET;
	int nextRegister = (virtualRegister+1)%MAX_EXP_REGISTERS+FIRST_REG_OFFSET;

    // find out if this is an array or not
	if (dPtr->isArray) {
		// save RHS side
		e.emitRM("ST", actualRegister, toff--, fp, "Store RHS of assignment");

		// genCode for index and then find location to store value
		if (this->child[0] == NULL) 
			throw "There is no index in the LHS of an array assingment";
		else
            this->child[0]->GenCode(e, true, virtualRegister, toff); 
			// array index will be in actualRegister

        if (dPtr->theScope == Parameter)
			e.emitRM("LD", rt, dPtr->offset, (dPtr->theScope == TreeNode::Global)?gp:fp, "array base");
		else {			
			e.emitRM("LDA", rt, dPtr->offset, (dPtr->theScope == TreeNode::Global)?gp:fp, "array base");
		}			
		// array base will be in rt
		
		e.emitRO("SUB", actualRegister, rt, actualRegister, "index off of the base");
		// correct reference will now be in actualRegister

		e.emitRM("LD", rt, ++toff, fp, "Load RHS value");
		// RHS value will be in rt 
		
		e.emitRM("ST", rt, 0, actualRegister, "store indexed variable " + dPtr->name);
		e.emitRM("LDA", actualRegister, 0, rt, "adjust current accumulator");		
	}
	else {
		// retrieve variable offset and scope to emit instruction
		e.emitRM("ST", ac, dPtr->offset, (dPtr->theScope == TreeNode::Global)?gp:fp, "store variable " + dPtr->name); 
	}	
}
Example #4
0
void StatementNode::GenCode(CodeEmitter &e, bool travSib, int virtualRegister, int toff) {
	int currLoc, skipLoc;

	// Assign virtual register to 'real' register
	int actualRegister = virtualRegister%MAX_EXP_REGISTERS+FIRST_REG_OFFSET;
	
	switch (subKind) {
		case IfK:
			e.emitComment("IF");
			
			// Test Condition
			if (child[0] != NULL)
				child[0]->GenCode(e, true, virtualRegister, toff);
			e.emitRM("LDC", rt, 1, 0, "load constant 1");
			e.emitRO("SUB", actualRegister, actualRegister, rt, "if condition check");
			skipLoc = e.emitSkip(1);

			e.emitComment("THEN");
			// Then part
			if (child[1] != NULL)
				child[1]->GenCode(e, true, virtualRegister, toff);

			// Else part
			if (child[2] != NULL) {
				currLoc = e.emitSkip(1);
				e.emitBackup(skipLoc);
				e.emitRMAbs("JLT", actualRegister, currLoc+1, "jump to else if false");
				e.emitRestore();
				skipLoc = currLoc;

				child[2]->GenCode(e, true, virtualRegister, toff);
				currLoc = e.emitSkip(0);
				e.emitBackup(skipLoc);
				e.emitRMAbs("LDA", pc, currLoc, "jump past else part");
				e.emitRestore();
			}
			else {
				currLoc = e.emitSkip(0);
				e.emitBackup(skipLoc);
				e.emitRMAbs("JLT", actualRegister, currLoc, "jump past then if false");
				e.emitRestore();			
			}
			e.emitComment("END IF");
			break;

		case CompK:
			e.emitComment("BEGIN");
			if (child[1] != NULL)
				child[1]->GenCode(e, true, virtualRegister, toff);
			e.emitComment("END");
			break;
		case WhileK:
			e.emitComment("WHILE");
			currLoc = e.emitSkip(0);
			
			// Test Condition
			if (child[0] != NULL)
				child[0]->GenCode(e, true, virtualRegister, toff);
			e.emitRM("LDC", rt, 1, 0, "load constant 1");
			e.emitRO("SUB", actualRegister, actualRegister, rt, "while condition check");
			skipLoc = e.emitSkip(1);

			e.emitComment("WHILE BODY");
			// While Body
			if (child[1] != NULL)
				child[1]->GenCode(e, true, virtualRegister, toff);
			e.emitRMAbs("LDA", pc, currLoc, "go to beginning of loop");
			
			// Save current location to jump when While cond. is false
			currLoc = e.emitSkip(0);
			e.emitBackup(skipLoc);
			e.emitRMAbs("JLT", actualRegister, currLoc, "break out of loop if false");
			e.emitRestore();
			e.emitComment("END WHILE");
			break;

		case ReturnK:
			e.emitComment("RETURN");
			if (child[0] != NULL)
				child[0]->GenCode(e, true, virtualRegister, toff);

			e.emitRM("LDA", rt, 0, actualRegister, "copy result to rt register");
			e.emitRM("LD", actualRegister, -1, fp, "load return address"); // Return address is one off from frame pointer
			e.emitRM("LD", fp, 0, fp, "adjust fp");
			e.emitRM("LDA", pc, 0, actualRegister, "Return");
			break;
	}

	if (sibling != NULL) {
		e.emitComment(NO_COMMENT);
		sibling->GenCode(e, true, virtualRegister, toff);
	}
}
Example #5
0
void TreeNode::GenIOFunctions(CodeEmitter &e) const {
	e.emitComment("Being Generating IO Functions");
	
	e.emitComment("Begin function input");
	e.emitRM("ST", ac, -1, fp, "store return address");
	e.emitRO("IN", rt, rt, rt, "input integer");
	e.emitRM("LD", ac, -1, fp, "load return address");
	e.emitRM("LD", fp, 0, fp, "adjust fp");
	e.emitRM("LDA", pc, 0, ac, "jump to return address");
	e.emitComment("End function input");

	e.emitComment("Begin function output");
	e.emitRM("ST", ac, -1, fp, "store return address");
	e.emitRM("LD", ac, -2, fp, "load parameter");
	e.emitRO("OUT", ac, ac, ac, "output integer");
	e.emitRM("LDC", rt, 0, rt, "set return to 0");
	e.emitRM("LD", ac, -1, fp, "load return address");
	e.emitRM("LD", fp, 0, fp, "adjust fp");
	e.emitRM("LDA", pc, 0, ac, "jump to return address");
	e.emitComment("End function output");

	e.emitComment("Begin function inputb");
	e.emitRM("ST", ac, -1, fp, "store return address");
	e.emitRO("INB", rt, rt, rt, "input boolean");
	e.emitRM("LD", ac, -1, fp, "load return address");
	e.emitRM("LD", fp, 0, fp, "adjust fp");
	e.emitRM("LDA", pc, 0, ac, "jump to return address");
	e.emitComment("End function inputb");

	e.emitComment("Begin function outputb");
	e.emitRM("ST", ac, -1, fp, "store return address");
	e.emitRM("LD", ac, -2, fp, "load parameter");
	e.emitRO("OUTB", ac, ac, ac, "output boolean");
	e.emitRM("LDC", rt, 0, rt, "set return to 0");
	e.emitRM("LD", ac, -1, fp, "load return address");
	e.emitRM("LD", fp, 0, fp, "adjust fp");
	e.emitRM("LDA", pc, 0, ac, "jump to return address");
	e.emitComment("End function outputb");

	e.emitComment("End Generating IO Functions");
}
Example #6
0
void TreeNode::GenProlog(int &jumpMain, CodeEmitter &e) const {
	
	e.emitComment("C- compiler version 1.0");
	e.emitComment("Author: Cody Permann");
	e.emitComment("May 13, 2004");
	e.emitComment("Begin Prolog code");
	e.emitRM("LD", gp, 0, 0, "load global poiniter with end of memory");
	e.emitRM("LDA", fp, goff, gp, "load fp");
	e.emitRM("ST", fp, 0, fp, "store old fp");
	e.emitRM("LDA", ac, 1, pc, "return address in ac");
	jumpMain = e.emitSkip(1);	// save this address into the static variable for later
	e.emitRO("HALT", 0, 0, 0, "DONE!");
	e.emitComment("End Prolog code");
}
Example #7
0
void ExpressionNode::GenCode(CodeEmitter &e, bool travSib, int virtualRegister, int toff) {
	DeclarationNode *dPtr;
	ExpressionNode *argPtr;
	int localToff, boolSkipLoc, currentLoc, currentReg;
	bool isUnary = true;
	
	// Assign virtual register to 'real' register
	int actualRegister = virtualRegister%MAX_EXP_REGISTERS+FIRST_REG_OFFSET;
	int nextRegister = (virtualRegister+1)%MAX_EXP_REGISTERS+FIRST_REG_OFFSET;

	localToff = toff;
	switch (subKind) {
		case OpK:
			// process left child
			if (child[0] != NULL)
				child[0]->GenCode(e, true, virtualRegister, toff);

			// mark location for short circuit jump
			if (op == "&&" || op == "||")
                boolSkipLoc = e.emitSkip(1);
			
			if (child[1] != NULL) {
				isUnary = false;
				
				// see if all of our registers are full...
				if (virtualRegister+1 >= MAX_EXP_REGISTERS) {
					// push value from "next" register 					
					e.emitRM("ST", nextRegister, toff--, fp, "dump register"); // push 
				}
				else
					e.emitComment("Left side will remain in register");

				/*
				// save left side
				localToff = toff--;
				e.emitRM("ST", ac, localToff, fp, "save left side");
				*/
				
				// process right child
				child[1]->GenCode(e, true, virtualRegister+1, toff);

				/*
				// load left back into the accumulator
				toff = localToff;
				e.emitRM("LD", ac1, localToff, fp, "load left into ac1");
				*/
			}
			
			// process operators
			// arithmetic operators
			if (op == "+")
				e.emitRO("ADD", actualRegister, actualRegister, nextRegister, "op +");
			else if (op == "-" && !isUnary) 
                e.emitRO("SUB", actualRegister, actualRegister, nextRegister, "op -");
			else if (op == "*")
				e.emitRO("MUL", actualRegister, actualRegister, nextRegister, "op *");
			else if (op == "/")
				e.emitRO("DIV", actualRegister, actualRegister, nextRegister, "op /");
			else if (op == "%") {
				e.emitRO("DIV", rt, actualRegister, nextRegister, "begin op %");
				e.emitRO("MUL", nextRegister, rt, nextRegister, "");
				e.emitRO("SUB", actualRegister, actualRegister, nextRegister, "end op %");
			}
			else if (op == "&&") {
				/**** Code for the non short circuit case ****
				e.emitRO("ADD", actualRegister, actualRegister, nextRegister, "prepare for && op");
				e.emitRM("LDC", nextRegister, 2, 0, "load constant for &&");
				e.emitRO("SUB", actualRegister, nextRegister, actualRegister, "compute value");
				e.emitRM("JEQ", actualRegister, 2, pc, "op &&");

				e.emitRM("LDC", actualRegister, 0, 0, "load false into ac");
				e.emitRM("LDA", pc, 1, pc, "jump past true case");
				e.emitRM("LDC", actualRegister, 1, 0, "load true into ac");
				**** Code for the non short circuit case *****/
				
				e.emitRM("JGT", nextRegister, 2, pc, "op && (right side)");
                
				// special case: If left side of && is false then whole expression is false
				currentLoc = e.emitSkip(0);
				e.emitBackup(boolSkipLoc);
				e.emitRMAbs("JEQ", actualRegister, currentLoc, "Skip right child of && if left is false");
				e.emitRestore();

				e.emitRM("LDC", actualRegister, 0, 0, "load false into ac");
				e.emitRM("LDA", pc, 1, pc, "jump past true case");
				e.emitRM("LDC", actualRegister, 1, 0, "load true into ac");				
			}
			else if (op == "||") {
				/**** Code for the non short circuit case ****
				e.emitRO("ADD", actualRegister, actualRegister, nextRegister, "prepare for || op");
				e.emitRM("JGT", actualRegister, 2, pc, "op ||");

				e.emitRM("LDC", actualRegister, 0, 0, "load false into ac");
				e.emitRM("LDA", pc, 1, pc, "jump past true case");
				e.emitRM("LDC", actualRegister, 1, 0, "load true into ac");
				**** Code for the non short circuit case *****/
				
				//e.emitRM("JEQ", nextRegister, 2, pc, "op || (right side)");
				
				/* Since the left side is short circuited the right side alone will determine 
				whether the expression is true or false. Just make sure the RHS is int the right
				register */
				e.emitRM("LDA", actualRegister, 0, nextRegister, "Move RHS to current accumulator");
				
				// special case: If left side of || is true then whole expression is true
				currentLoc = e.emitSkip(0);
				e.emitBackup(boolSkipLoc);
				e.emitRMAbs("JGT", actualRegister, currentLoc, "Skip right child of || if left is true");
				e.emitRestore();

				//e.emitRM("LDC", actualRegister, 1, 0, "load true into ac");
				//e.emitRM("LDA", pc, 1, pc, "jump past false case");
				//e.emitRM("LDC", actualRegister, 0, 0, "load false into ac");			
			}
			else if (op == "!") {
				e.emitRM("JEQ", actualRegister, 2, pc, "op !");
				e.emitRM("LDC", actualRegister, 0, 0, "load false into ac");
				e.emitRM("LDA", pc, 1, pc, "jump past true case");
				e.emitRM("LDC", actualRegister, 1, 0, "load true into ac");
			}
			else if (op == "-" and isUnary) {
				e.emitRM("LDC", rt, 0, 0, "Load zero in rt for unary -");
				e.emitRO("SUB", actualRegister, rt, actualRegister, "op unary -");
			}
			else { // comparison operators
				e.emitRO("SUB", actualRegister, actualRegister, nextRegister, "prepare for comparison op");
				
				if (op == "==") 
					e.emitRM("JEQ", actualRegister, 2, pc, "op ==");
				else if (op == "!=")
					e.emitRM("JNE", actualRegister, 2, pc, "op !=");
				else if (op == "<")
					e.emitRM("JLT", actualRegister, 2, pc, "op <");					
				else if (op == "<=")
					e.emitRM("JLE", actualRegister, 2, pc, "op <=");				
				else if (op == ">")
					e.emitRM("JGT", actualRegister, 2, pc, "op >");
				else if (op == ">=")
					e.emitRM("JGE", actualRegister, 2, pc, "op >=");

				e.emitRM("LDC", actualRegister, 0, 0, "load false into ac");
				e.emitRM("LDA", pc, 1, pc, "jump past true case");
				e.emitRM("LDC", actualRegister, 1, 0, "load true into ac");
			}

			// if we dumped a register earlier we need to restore it here
			if (virtualRegister+1 >= MAX_EXP_REGISTERS) {
				// pop value from stack back into next register 
				e.emitRM("LD", nextRegister, ++toff, fp, "restore register"); // pop
			}			
			break;
		case AssignK:
			// process RHS of assignment
			if (child[1] != NULL)
				child[1]->GenCode(e, true, virtualRegister, toff);

			// call function to store in LHS
			((ExpressionNode *)child[0])->GenAssignLHS(e, virtualRegister, toff);			
			break;

		case ConstK:
			e.emitRM("LDC", actualRegister, val, 0, "load constant");
			break;

		case IdK:
			if (this->dPtr->isArray) {
				// is this array indexed?
				if (child[0] == NULL) {  // must be a parameter
					if (this->dPtr->theScope == TreeNode::Parameter)
						e.emitRM("LD", actualRegister, this->dPtr->offset, (this->dPtr->theScope == TreeNode::Global)?gp:fp, "Load address of base of array " + this->name);
					else
						e.emitRM("LDA", actualRegister, this->dPtr->offset, (this->dPtr->theScope == TreeNode::Global)?gp:fp, "Load address of base of array " + this->name);
				}
				else { 
					child[0]->GenCode(e, true, virtualRegister, toff);
					
					if (this->dPtr->theScope == TreeNode::Parameter)
						e.emitRM("LD", rt, this->dPtr->offset, (this->dPtr->theScope == TreeNode::Global)?gp:fp, "Load address of base of array " + this->name);
					else
						e.emitRM("LDA", rt, this->dPtr->offset, (this->dPtr->theScope == TreeNode::Global)?gp:fp, "Load address of base of array " + this->name);

					e.emitRO("SUB", actualRegister, rt, actualRegister, "index off of the base");
					e.emitRM("LD", actualRegister, 0, actualRegister, "load the value");
				}
			}
			else {
				e.emitRM("LD", actualRegister, this->dPtr->offset, (this->dPtr->theScope == TreeNode::Global)?gp:fp, "load variable " + name);
			}
			break;
		case CallK:
			// dump any used registers to temps before calling a function
			currentReg = actualRegister;
			if (currentReg > FIRST_REG_OFFSET)
				e.emitComment("Need to dump Registers before call");
			
			while (currentReg > FIRST_REG_OFFSET)
				e.emitRM("ST", --currentReg, toff--, fp, "Save register to temporaries");

			dPtr = (DeclarationNode *)symtab->lookup(name.c_str());
			currentLoc = toff--;
			e.emitRM("ST", fp, currentLoc, fp, "Store old fp in ghost frame");

			// leave room for return param
			--toff;

			// process function parameters
			argPtr = (ExpressionNode *)this->child[0];	// set the parameter pointer to the function declaration parameters
			//localToff = toff;
			while (argPtr != NULL) {
				//localToff--;
				//toff--;
				argPtr->GenCode(e, false, 0, toff);
				// store expression result
				e.emitRM("ST", FIRST_REG_OFFSET, toff-- , fp, "Save parameter");
				argPtr = (ExpressionNode *)argPtr->sibling;
			}		

			// prepare for jump
			e.emitRM("LDA", fp, currentLoc, fp, "Load address of new frame");
			e.emitRM("LDA", FIRST_REG_OFFSET, 1, pc, "Put return address in ac");
			e.emitRMAbs("LDA", pc, dPtr->offset, "Call " + dPtr->name);
			
			// save return value
			e.emitRM("LDA", actualRegister, 0, rt, "Save the result in current accumulator");

			// restore temps back to registers
			if (currentReg < actualRegister)
				e.emitComment("Need to restore registers after call");

			toff = currentLoc;
			while (currentReg < actualRegister)
				e.emitRM("LD", currentReg++, ++toff, fp, "Load Register from Temporaries");

			// restore toff
			//toff = localToff;
			break;
	}

	if (sibling != NULL && travSib) {
		e.emitComment(NO_COMMENT);	
		sibling->GenCode(e, true, 0, localToff);
	}
}
Example #8
0
void DeclarationNode::GenCode(CodeEmitter &e, bool travSib, int virtualRegister, int toff) {
	DeclarationNode *dPtr;

	// Assign virtual register to 'real' register
	int actualRegister = virtualRegister%MAX_EXP_REGISTERS+FIRST_REG_OFFSET;

	// Don't generate code for IO functions
	if (subKind == FuncK && name != "input" && name != "output" && name != "inputb" && name != "outputb") {
		// Lookup in symbol table - we'll need to set the "offset" variable
		dPtr = (DeclarationNode *)this;
		dPtr->offset = e.emitSkip(0); // save the current location for calls later
			
		// If this function is main, we need to backpatch in the jump from the prolog
		if (name == "main") {
			e.emitBackup(jumpMain);
			e.emitRMAbs("LDA", pc, dPtr->offset, "jump to main");
			e.emitRestore();
		}

		e.emitComment("Function " + name + " returns " + PrintType(type));
		e.emitRM("ST", FIRST_REG_OFFSET, -1, fp, "store return address"); // return address is always -1 away from current frame

		// Load up the foff variable with the function size
		foff = size;

		// Function Body
		if (child[1] != NULL) {
			child[1]->GenCode(e, true, virtualRegister, foff);
		}

		// Add Return Statement if the function doesn't return from all branches
		if (!allPathsReturn) {
			e.emitComment("This function requires a catch all return");
			e.emitRM("LDC", rt, 0, 0, "Set return value to 0");
			e.emitRM("LD", actualRegister, -1, fp, "Load return address");
			e.emitRM("LD", fp, 0, fp, "Adjust fp");
			e.emitRM("LDA", pc, 0, actualRegister, "Return");					
		}
		else
			e.emitComment("This function returns from all paths, no catch all return required");
		e.emitComment("End Function " + name);
	}

	if (sibling != NULL)
		sibling->GenCode(e, true, virtualRegister, toff);
}