Пример #1
0
    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)}")
Пример #2
0
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
Пример #3
0
    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)
Пример #4
0
 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)
Пример #5
0
    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)
Пример #6
0
    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))
Пример #7
0
 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")
Пример #8
0
def reserveTempVars(maxIndex):
    return "".join(
        reserve(labelname.getTempName(i), 2) for i in range(maxIndex + 1))