Ejemplo n.º 1
0
    def __init__(self, ir):

        # Create a flow graph
        flowGraph = FlowGraph(ir.tac)
        blockNodes = flowGraph._blockNodes
        countNodes = len(blockNodes)

        # Create the Register and Address Descriptor for all available register and variables.
        # The Address Descriptor table, contains information about all the non local variables's value location
        self._addrDis = AddrDis()
        # The Register Descriptor table, contains information about allocation of all the registers
        self._regDis = RegDis()

        # self._tr = Translator()

        self._st = ir.symbolTable

        self._regAlloc = RegAlloc(self._st, self._regDis, self._addrDis)

        # a set of empty registers
        self._freeRs = AvalRegs

        self._codeBlocks = []

        self._globalVars = {}
        self._newBlockIns = []
        # Holds register which stores constant for a instruction.
        # There registers must be free after execution of that instruction
        self._toFreeRs = []

        # For each node in blockNode of flow graph as node:
        for node in blockNodes:
            blockIns = node._block
            if blockIns == "entry" or blockIns == "exit":
                # entry and exit nodes, continue
                continue

            # Generate the Next-Use-Live for `blockIns`.
            nextUseLiveST, nonTempVars = NextUseLive(blockIns, ir.symbolTable)
            # check if the key exists in address discriptor
            self._addrDis.add(nonTempVars)

            # add the nonTemp variables into global data region
            for var in nonTempVars:
                self._globalVars[var] = ""

            #- For each Instruction `Ins` in `blockIns`:
            i = 0
            self._newBlockIns = []
            jumpIns = []
            countBlock = len(blockIns)
            while i < countBlock:
                tac = blockIns[i]
                self._toFreeRs = []
                # get the next use info about the current line
                nextUse = nextUseLiveST[i + 1]

                # Get the type of `Ins`
                # if `Ins` isOfType "Operations" (dest = src1 op src2):
                if tac.type == InstrType.assgn:
                    #  handle to operation type and return generated instructions
                    self.handleOps(tac, nextUse)

                # else if `Ins` isOfType "Copy Statement"(dest = src):
                elif tac.type == InstrType.copy:
                    self.handleCopy(tac, nextUse)

                # else if `Ins` isOfType "cond_jump"
                elif tac.type == InstrType.cjump:
                    jumpIns += self.handleCondJump(tac, nextUse)

                # else if `Ins` is of type "uncond_jump"
                elif tac.type == InstrType.ujump:
                    jumpIns.append("j " + str(tac.target))

                # else if `Ins` is of type "func_call"
                elif tac.type == InstrType.call or tac.type == InstrType.libFn:
                    jumpIns += self.handleFnsCalls(tac, nextUse)

                # else if `Ins` is of type "func_label"
                elif tac.type == InstrType.label:
                    self._newBlockIns.append("addi $sp, $sp, -4")
                    self._newBlockIns.append("sw $ra, 0($sp)")
                # the return type
                elif tac.type == InstrType.ret:
                    jumpIns += self.handleReturns(tac, nextUse)

                # Handle the parametes, Handle the parameters right here as
                # we need other parameters here too
                elif tac.type == InstrType.params:
                    # get all the parameters
                    # do a loop and get all the parameters
                    allocatedRs = {}
                    j = 0
                    while tac.type == InstrType.params:
                        param = tac.src
                        attrs = self._st.getAttrs(param)
                        if attrs["type"] == "const_int":
                            self._newBlockIns.append("li $a" + str(j) + ", " +
                                                     str(attrs["val"]))
                        else:
                            rParam = self._regAlloc.getReg(
                                param, tac, nextUse, allocatedRs)
                            allocatedRs[param] = rParam
                            self._regAlloc.removeFromFree(rParam)
                            # If src=Ins.srcOperand is not in 'Register':
                            # get it from memory and store in the register
                            self.lwInR(param, rParam)

                            self._newBlockIns.append("move $a" + str(j) +
                                                     ", " + str(rParam))

                            # # Change the Addr_Des[dest] so that it holds only location `R_dest`.
                            # self._addrDis.setR(param, rParam)
                        if i < countBlock - 1:
                            i += 1
                            nextUse = nextUseLiveST[i + 1]
                            tac = blockIns[i]
                        else:
                            break
                        j += 1
                    continue

                else:
                    print "code:142:: Unhandled instruction at " + tac.lineNumber
                    self._newBlockIns.append("tac")

                # For register to be free, Free them
                self._regAlloc.addToFree(self._toFreeRs)
                i += 1
            # we done with the block, now time to restore the lost values
            self.restoreAtEnd(nonTempVars)
            self._newBlockIns += jumpIns
            ##### End of for loop for this block
            self._codeBlocks.append(self._newBlockIns)
            self._regAlloc.addToFree(self._toFreeRs)
Ejemplo n.º 2
0
    def __init__(self, ir, stm):

        # Create a flow graph
        flowGraph = FlowGraph(ir.tac)
        blockNodes = flowGraph._blockNodes
        countNodes = len(blockNodes)

        # To hold the constant string with there key name
        self._strs = {}

        self._st = stm

        self._fns = flowGraph._fns

        self._codeBlocks = []

        self._globalVars = {}
        self._newBlockIns = []
        # Holds register which stores constant for a instruction.
        # There registers must be free after execution of that instruction
        self._toFreeRs = []

        # For each node in blockNode of flow graph as node:
        nodeNumber = -1
        for node in blockNodes:
            # Create the Register and Address Descriptor for all available register and variables.
            # The Address Descriptor table, contains information about all the non local variables's value location
            self._addrDis = AddrDis()
            # The Register Descriptor table, contains information about allocation of all the registers
            self._regDis = RegDis()
            # self._tr = Translator()

            self._regAlloc = RegAlloc(self._st, self._regDis, self._addrDis)
            self._newBlockIns = []

            blockIns = node._block
            if blockIns == "entry" or blockIns == "exit":
                # entry and exit nodes, continue
                continue

            # Some dead code elimination if a node don't have link to it's parents
            if (len(node._parentNodes) == 0):
                # remove me from my children's parent as they also won't be accessible by me
                # for child in node._nextNodes:
                #     child._parentNodes.remove(node)
                self._codeBlocks.append(self._newBlockIns)
                nodeNumber += 1
                continue

            # Generate the Next-Use-Live for `blockIns`.
            nextUseLiveST, nonTempVars = NextUseLive(blockIns)
            # print nonTempVars
            # check if the key exists in address discriptor
            self._addrDis.add(nonTempVars)

            # add the nonTemp variables into global data region
            # for var in nonTempVars:
            #     self._globalVars[var] = ""

            #- For each Instruction `Ins` in `blockIns`:
            i = 0
            jumpIns = []
            paramIns = []
            countBlock = len(blockIns)
            nodeNumber += 1
            if nodeNumber in self._fns.keys():
                self._newBlockIns.append("addi $sp, -8")
                self._newBlockIns.append("sw $ra, 0($sp)")
                self._newBlockIns.append("sw $fp, 4($sp)")
                self._newBlockIns.append("move $fp, $sp")
                self._newBlockIns.append(
                    "addi $sp, -" +
                    str(self._st.ftable[self._fns[nodeNumber]]["st"].width))
            while i < countBlock:
                tac = blockIns[i]
                self._toFreeRs = []
                # get the next use info about the current line
                nextUse = nextUseLiveST[i + 1]

                # Get the type of `Ins`
                # if `Ins` isOfType "Operations" (dest = src1 op src2):
                if tac.type == InstrType.assgn:
                    #  handle to operation type and return generated instructions
                    self.handleOps(tac, nextUse)

                # else if `Ins` isOfType "Copy Statement"(dest = src):
                elif tac.type == InstrType.copy:
                    self.handleCopy(tac, nextUse)

                # else if `Ins` isOfType "cond_jump"
                elif tac.type == InstrType.cjump:
                    jumpIns += self.handleCondJump(tac, nextUse)

                # else if `Ins` is of type "uncond_jump"
                elif tac.type == InstrType.ujump:
                    jumpIns.append("j " + str(tac.target))

                # else if `Ins` is of type "func_call"
                elif tac.type == InstrType.call or tac.type == InstrType.libFn:
                    paramIns.reverse()
                    jumpIns += paramIns
                    jumpIns += self.handleFnsCalls(tac, nextUse)

                # else if `Ins` is of type "func_label"
                elif tac.type == InstrType.label:
                    self._newBlockIns.append("addi $sp, $sp, -4")
                    self._newBlockIns.append("sw $ra, 0($sp)")
                # the return type
                elif tac.type == InstrType.ret:
                    jumpIns += self.handleReturns(tac, nextUse)

                # Handle the parametes, Handle the parameters right here as
                # we need other parameters here too
                elif tac.type == InstrType.params:
                    # handle the parameters
                    # push them onto the stack
                    paramIns += self.handleParams(tac, nextUse)

                else:
                    print "code:142:: Unhandled instruction at " + tac.lineNumber
                    self._newBlockIns.append("tac")

                # For register to be free, Free them
                self._regAlloc.addToFree(self._toFreeRs)
                i += 1
            # we done with the block, now time to restore the lost values
            self.restoreAtEnd(nonTempVars)
            self._newBlockIns += jumpIns
            ##### End of for loop for this block
            self._codeBlocks.append(self._newBlockIns)
            self._regAlloc.addToFree(self._toFreeRs)