def generateFunctionStackFrame(self, fn): if fn.isImported: return "" outside = [] inside = [] inside += [(labelname.getReturnAddressLabel(fn.name), 2)] outside += [(None, 2)] inside += [(labelname.getArgumentName(fn.name, i, False), fn.args[i].getReserveSize()) for i in range(len(fn.args))] outside += [(labelname.getArgumentName(fn.name, i, True), fn.args[i].getReserveSize()) for i in range(len(fn.args))] inside += [(labelname.getReturnName(fn.name, False), fn.retType.getReserveSize())] outside += [(labelname.getReturnName(fn.name, True), fn.retType.getReserveSize())] inside += [(labelname.getLocalName(fn.name, v), fn.localVars[v].getReserveSize()) for v in fn.localVars] inside += [(labelname.getTempName(i, fn.name), self.backend.MAX_INT_SIZE) for i in range(fn.maxTempVarIndex + 1)] try: return self.backend.reserveStackFrames(inside, outside) except ValueError as e: raise ValueError(f"{fn.name}: {str(e)}")
def reserveTempVars(maxIndices, uniqueId, subsections): maxIndex = max(m for _, m in maxIndices) result = "" for i in range(maxIndex + 1): labels = [labelname.getTempName(i, n) for n, m in maxIndices if i <= m] result += reserve(labels, MAX_INT_SIZE, "bss", uniqueId, subsections) return result
def generateWhile(self, cond, body, curFn): labelBegin = self.allocLabel("while_begin") labelEnd = self.allocLabel("while_end") self.maxTempVarIndex = max(self.maxTempVarIndex, 0) rvCond, codeCond = self.generateExpression( cond, 0, Value.variable(Position.fromAny(cond), labelname.getTempName(0, curFn), BoolType()), curFn) self.breakLabel = [labelEnd] + self.breakLabel self.continueLabel = [labelBegin] + self.continueLabel codeBody = self.generateStatement(body, curFn) self.breakLabel = self.breakLabel[1:] self.continueLabel = self.continueLabel[1:] return self.backend.genLabel(labelBegin) + codeCond + self.backend.genInvCondJump(rvCond, labelEnd)\ + codeBody + self.backend.genJump(labelBegin) + self.backend.genLabel(labelEnd)
def generateConditional(self, cond, ifBody, elseBody, curFn): labelEnd = self.allocLabel("if_end") if elseBody is not None: labelElse = self.allocLabel("if_else") self.maxTempVarIndex = max(self.maxTempVarIndex, 0) rvCond, codeCond = self.generateExpression( cond, 0, Value.variable(Position.fromAny(cond), labelname.getTempName(0, curFn), BoolType()), curFn) codeIf = self.generateStatement(ifBody, curFn) if elseBody is not None: codeElse = self.generateStatement(elseBody, curFn) if elseBody is None: return codeCond + self.backend.genInvCondJump( rvCond, labelEnd) + codeIf + self.backend.genLabel(labelEnd) else: return codeCond + self.backend.genInvCondJump(rvCond, labelElse)\ + codeIf + self.backend.genJump(labelEnd) + self.backend.genLabel(labelElse) + codeElse + self.backend.genLabel(labelEnd)
def generateFor(self, prolog, cond, iteration, body, curFn): if prolog.data != 'for_prolog': codeProlog = self.generateStatement(prolog, curFn) else: codeProlog = "" hasIterationCode = iteration.data != "for_iteration" labelBegin = self.allocLabel("for_begin") labelEnd = self.allocLabel("for_end") if hasIterationCode: labelContinue = self.allocLabel("for_continue") else: labelContinue = labelBegin if isinstance(cond, Value) or cond.data != 'for_condition': self.maxTempVarIndex = max(self.maxTempVarIndex, 0) rvCond, codeCond = self.generateExpression( cond, 0, Value.variable(Position.fromAny(cond), labelname.getTempName(0, curFn), BoolType()), curFn) codeCond += self.backend.genInvCondJump(rvCond, labelEnd) else: codeCond = "" self.breakLabel = [labelEnd] + self.breakLabel self.continueLabel = [labelContinue] + self.continueLabel codeBody = self.generateStatement(body, curFn) self.breakLabel = self.breakLabel[1:] self.continueLabel = self.continueLabel[1:] if hasIterationCode: codeIter = self.backend.genLabel(labelContinue) codeIter += self.generateStatement(iteration, curFn) codeIter += self.backend.genJump(labelBegin) else: codeIter = self.backend.genJump(labelBegin) return codeProlog + self.backend.genLabel(labelBegin) + codeCond\ + codeBody + codeIter + self.backend.genLabel(labelEnd)
def generateExpression(self, t, minTempVarIndex, resultLoc, curFn): ''' Generate code to compute the expression. :param t: the expression tree :param minTempVarIndex: minimum index of a temp variable to use :param resultLoc: where to place the result. The result can be placed somewhere else (TODO). :param curFn: name of the current function. :return: the actual location of the result ''' try: if isinstance(t, Value): return self.backend.genMove(resultLoc, t, True) else: ch = t.children if len(ch) == 1: if isinstance(ch[0], Value): argCode = "" rv = ch[0] else: self.maxTempVarIndex = max(self.maxTempVarIndex, minTempVarIndex) rv, argCode = self.generateExpression( ch[0], minTempVarIndex, Value.variable( Position.fromAny(ch[0]), labelname.getTempName(minTempVarIndex, curFn)), curFn) resultLoc, myCode = self.backend.genUnary( t.data, resultLoc, rv) return resultLoc, argCode + myCode elif t.data == "type_cast": if isinstance(ch[1], Value): argCode = "" rv = ch[1] else: self.maxTempVarIndex = max(self.maxTempVarIndex, minTempVarIndex) rv, argCode = self.generateExpression( ch[1], minTempVarIndex, Value.variable( Position.fromAny(ch[1]), labelname.getTempName(minTempVarIndex, curFn)), curFn) resultLoc, myCode = self.backend.genCast( resultLoc, ch[0], rv) return resultLoc, argCode + myCode elif t.data == "arrow": ptr = ch[0] fields = ch[1:] self.maxTempVarIndex = max(self.maxTempVarIndex, minTempVarIndex) rv, argCode = self.generateExpression( ptr, minTempVarIndex, Value.variable( Position.fromAny(ptr), labelname.getTempName(minTempVarIndex, curFn)), curFn) offset, type = structure.getField(rv.getType().deref(), fields) if type.getIndirectionOffset() == 0: resultLoc, derefCode = self.backend.genDeref( resultLoc.withType(type), rv, offset) return resultLoc, argCode + derefCode elif type.getIndirectionOffset() == -1: rv, offsetCode = self.backend.genAddPointerOffset( resultLoc.withType(type), rv.withType(type), offset) return rv, argCode + offsetCode else: raise RuntimeError("Wrong indirection offset") elif t.data == "p_arrow": ptr = ch[0] fields = ch[1:] self.maxTempVarIndex = max(self.maxTempVarIndex, minTempVarIndex) rv, argCode = self.generateExpression( ptr, minTempVarIndex, resultLoc.withType(UnknownType()), curFn) offset, type = structure.getField(rv.getType().deref(), fields) if type.getIndirectionOffset() < 0: raise SemanticError(Position.fromAny(t), "Cannot get address") rv, offsetCode = self.backend.genAddPointerOffset( resultLoc.withType(PtrType(type)), rv.withType(PtrType(type)), offset) return rv, argCode + offsetCode elif len(ch) == 2: hasFirstArg = False if isinstance(ch[0], Value): rv1 = ch[0] argCode1 = "" else: self.maxTempVarIndex = max(self.maxTempVarIndex, minTempVarIndex) tmp0 = Value.variable( Position.fromAny(ch[0]), labelname.getTempName(minTempVarIndex, curFn)) rv1, argCode1 = self.generateExpression( ch[0], minTempVarIndex, tmp0, curFn) hasFirstArg = True if isinstance(ch[1], Value): rv2 = ch[1] argCode2 = "" else: indexIncrement = 1 if hasFirstArg else 0 self.maxTempVarIndex = max( self.maxTempVarIndex, minTempVarIndex + indexIncrement) tmp1 = Value.variable( Position.fromAny(ch[1]), labelname.getTempName( minTempVarIndex + indexIncrement, curFn)) rv2, argCode2 = self.generateExpression( ch[1], minTempVarIndex + indexIncrement, tmp1, curFn) if rv1.getSource().isRegister(): rv1, moveCode = self.backend.genMove( tmp0, rv1, False) argCode1 += moveCode try: resultLoc, myCode = self.backend.genBinary( t.data, resultLoc, rv1, rv2, self) except RegisterNotSupportedError as e: if e.argNumber == 0: rv1, moveCode = self.backend.genMove( tmp0, rv1, False) argCode1 += moveCode elif e.argNumber == 1: rv2, moveCode = self.backend.genMove( tmp1, rv2, False) argCode2 += moveCode else: raise resultLoc, myCode = self.backend.genBinary( t.data, resultLoc, rv1, rv2, self) return resultLoc, argCode1 + argCode2 + myCode else: raise RuntimeError("Too many children") except LookupError as e: raise SemanticError(Position.fromAny(t), str(e)) except ValueError as e: raise SemanticError(Position.fromAny(t), str(e))
def generateAssignment(self, l, r, curFn): ''' Assignment. Possible cases: 1. var = expression simply generate the expression into var 2. *(e1) = e2 generate e1 into tmp0 (address) generate e2 into tmp1 put indirect tmp1 at tmp0 3. (*var).field = expression ''' if isinstance(l, Value): # case 1: simple variable if not l.isLValue(): raise SemanticError(l.getPosition(), "Cannot assign to an r-value") dest = l resultLoc, codeExpr = self.generateExpression(r, 0, dest, curFn) if resultLoc == dest: # already assigned where needed return codeExpr else: # need to copy _, codeMove = self.backend.genMove(dest, resultLoc, False) return codeExpr + codeMove elif l.data == 'deref': # case 2: dereferenced expression ptr = l.children[0] self.maxTempVarIndex = max(self.maxTempVarIndex, 1) rvPtr, codePtr = self.generateExpression( ptr, 0, Value.variable(Position.fromAny(ptr), labelname.getTempName(0, curFn)), curFn) assert (not rvPtr.getSource().isRegister()) rvR, codeR = self.generateExpression( r, 1, Value.variable(Position.fromAny(r), labelname.getTempName(1, curFn)), curFn) codePutIndirect = self.backend.genPutIndirect(rvPtr, rvR) return codePtr + codeR + codePutIndirect elif l.data == 'arrow': # case 3: member of a derefed struct ptr = l.children[0] fields = l.children[1:] self.maxTempVarIndex = max(self.maxTempVarIndex, 1) rvPtr, codePtr = self.generateExpression( ptr, 0, Value.variable(Position.fromAny(ptr), labelname.getTempName(0, curFn)), curFn) assert (not rvPtr.getSource().isRegister()) try: offset, type = structure.getField(rvPtr.getType().deref(), fields) except LookupError as e: raise SemanticError(Position.fromAny(r), str(e)) except ValueError as e: raise SemanticError(Position.fromAny(r), str(e)) if type.getIndirectionOffset() < 0: raise SemanticError(Position.fromAny(l), "Cannot assign to an r-value") rvR, codeR = self.generateExpression( r, 1, Value.variable(Position.fromAny(r), labelname.getTempName(1, curFn)), curFn) codePutIndirect = self.backend.genPutIndirect( rvPtr.withType(PtrType(type)), rvR, offset) return codePtr + codeR + codePutIndirect else: raise RuntimeError("Unknown assignment case")
def reserveTempVars(maxIndex): return "".join( reserve(labelname.getTempName(i), 2) for i in range(maxIndex + 1))