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
class CodeGen():
    """Code Generator"""
    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)
        # self._flowGraph = flowGraph

    # Handler for operation type instructions
    def handleOps(self, tac, nextUse):

        operands = tac.operands
        dest = tac.dest
        srcs = tac.srcs

        # Get Registers for all operands (using GetReg(Ins) method). Say R_dest, R_src1, R_src2.
        allocatedRs = {}
        ## selection of registers for sources:
        srcInt = False
        bothInt = False
        for src in srcs:
            # if source is an integer, don't assign a real register. Make a fake register with the same value
            # but if both the srcs are integers, then we must store one of them in register
            if srcInt:
                bothInt = True

            attrs = self._st.getAttrs(src)
            srcInt = attrs["type"] == "const_int"
            if not srcInt:
                rSrc = self._regAlloc.getReg(src, tac, nextUse, allocatedRs)
                self.storeSpilled(rSrc)
                allocatedRs[src] = rSrc
                self._regAlloc.removeFromFree(rSrc)  # remove from free list
                # if `src` not in 'Register' (according to Reg_Des for R_src):
                # get it from memory and store it in a register
                self.lwInR(src, rSrc)

            else:
                intVal = attrs["val"]
                # check if the source is already alloted. This will be case
                # when both operands are same
                if src in allocatedRs.keys():
                    continue
                if tac.operator == "+" and (not bothInt):
                    allocatedRs[src] = str(intVal)
                else:
                    rSrc = self._regAlloc.getReg(src, tac, nextUse,
                                                 allocatedRs)
                    allocatedRs[src] = rSrc
                    self.storeSpilled(rSrc)
                    # if op is addition and src is int, then we know, we added a fake register. so no need
                    # to for a load or change in addr and register discriptor tables. else
                    # load that contant
                    self.genLiInstr(rSrc, src)
                    # set the register to be free after execution of this instruction
                    self._toFreeRs.append(rSrc)

        ## selection of registers for destination:
        # issues are the same as for srcs, just a minor differences
        # select a register that only holds value for x, if there is one.
        found = False
        reg = self._regDis.onlyVarReg(dest)
        if reg != None:
            allocatedRs[dest] = reg
            self._regAlloc.removeFromFree(
                reg)  # remove the register from free list
            found = True
        if not found:
            # for all srcs:
            for src in srcs:
                attrs = self._st.getAttrs(src)
                if attrs["type"] == "const_int":
                    continue
                # if src has not next-use and not live and R_src holds only src, after being loaded, then R_src can be use as R_dest. "OK".
                if nextUse[src][0] == 0 and nextUse[src][1] == -1:
                    # get all the locations that src is present in
                    for location in self._addrDis.fetchR(src):
                        if self._regDis.isIn(location):
                            # a register location
                            # Now check if R_src holds only src. if so, return it
                            if self._regDis.isOnlyVar(location, src):
                                allocatedRs[dest] = location
                                self._regAlloc.removeFromFree(
                                    location
                                )  # remove the location (register) from free list
                                found = True
                                break
                # check if found, else loop for other sources
                if found:
                    break

            # if still not found, get from regs
            if not found:
                rDest = self._regAlloc.getReg(dest, tac, nextUse, allocatedRs)
                self.storeSpilled(rDest)
                allocatedRs[dest] = rDest
                self._regAlloc.removeFromFree(
                    rDest)  # remove from free registers

        # create instruction for addi if operator is "+" and srcs are int
        # Issue The Instruction `op R_dest, R_src1, R_src2`
        if srcInt and tac.operator == "+":
            consts = None
            regs = []
            for src in operands:
                try:
                    c = int(allocatedRs[src])
                except Exception, e:
                    # raise e
                    regs.append(str(allocatedRs[src]))
                else:
                    consts = c
            # consts will be none when both of them are same intergers
            if consts != None:
                self._newBlockIns.append("addi " + ', '.join(regs) + ', ' +
                                         str(consts))
            else:
                self._newBlockIns.append("addi " + ', '.join(regs))
        else:
Ejemplo n.º 3
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)
Ejemplo n.º 4
0
class CodeGen():
    """Code Generator"""
    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)
        # self._flowGraph = flowGraph

    # Handler for operation type instructions
    def handleOps(self, tac, nextUse):

        operands = tac.operands
        dest = tac.dest
        srcs = tac.srcs

        # Get Registers for all operands (using GetReg(Ins) method). Say R_dest, R_src1, R_src2.
        allocatedRs = {}
        ## selection of registers for sources:
        srcInt = False
        bothInt = False
        for src in srcs:
            # if source is an integer, don't assign a real register. Make a fake register with the same value
            # but if both the srcs are integers, then we must store one of them in register
            if srcInt:
                bothInt = True

            srcInt = True if "const_" in src["type"] else False
            if not srcInt:
                rSrc = self._regAlloc.getReg(src, tac, nextUse, allocatedRs)
                self.storeSpilled(rSrc)
                allocatedRs[src["place"]] = rSrc
                self._regAlloc.removeFromFree(rSrc)     # remove from free list
                # if `src` not in 'Register' (according to Reg_Des for R_src):
                # get it from memory and store it in a register
                self.lwInR(src, rSrc)

            else: 
                # get the int value
                intVal = src["place"]
                # check if the source is already alloted. This will be case 
                # when both operands are same
                if src in allocatedRs.keys():
                    continue
                if tac.operator == "+" and (not bothInt):
                    allocatedRs[src["place"]] = str(intVal)
                else:
                    rSrc = self._regAlloc.getReg(src, tac, nextUse, allocatedRs)
                    allocatedRs[src["place"]] = rSrc
                    self.storeSpilled(rSrc)
                    # if op is addition and src is int, then we know, we added a fake register. so no need
                    # to for a load or change in addr and register discriptor tables. else
                    # load that contant
                    self.genLiInstr(rSrc, src)
                    # set the register to be free after execution of this instruction
                    self._toFreeRs.append(rSrc)

        ## selection of registers for destination:
        # issues are the same as for srcs, just a minor differences
        # select a register that only holds value for x, if there is one.
        found = False
        reg = self._regDis.onlyVarReg(dest)
        if reg != None:
            rDest = reg
            self._regAlloc.removeFromFree(reg)      # remove the register from free list
            found = True
        if not found:
            # for all srcs:
            for src in srcs:
                if "const_" in src["type"]:
                    continue    
                # if src has not next-use and not live and R_src holds only src, after being loaded, then R_src can be use as R_dest. "OK".
                if nextUse[src["place"]][0] == 0 and nextUse[src["place"]][1] == -1:
                    # get all the locations that src is present in
                    for location in self._addrDis.fetchR(src):
                        if self._regDis.isIn(location):
                            # a register location
                            # Now check if R_src holds only src. if so, return it
                            if self._regDis.isOnlyVar(location, src):
                                rDest = location
                                self._regAlloc.removeFromFree(location)     # remove the location (register) from free list
                                found = True
                                break
                # check if found, else loop for other sources
                if found:
                    break

            # if still not found, get from regs
            if not found:
                rDest = self._regAlloc.spill(tac, nextUse, allocatedRs)
                self.storeSpilled(rDest)
                self._regAlloc.removeFromFree(rDest)        # remove from free registers

        # create instruction for addi if operator is "+" and srcs are int
        # Issue The Instruction `op R_dest, R_src1, R_src2`
        if srcInt and  tac.operator == "+":
            consts = None
            regs = []
            for src in srcs:
                try:
                    c = int(allocatedRs[src["place"]])
                except Exception, e:
                    # raise e
                    regs.append(str(allocatedRs[src["place"]]))
                else:
                    consts = c
            # consts will be none when both of them are same intergers
            if consts != None:
                self._newBlockIns.append("addi "+ str(rDest) +", " +', '.join(regs) + ', '+str(consts))
            else:
                self._newBlockIns.append("addi "+ str(rDest) +", "+  ', '.join(regs))    
        else:
Ejemplo n.º 5
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.º 6
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)