def codeGen(x, nextUseTable): start = x[0] end = x[1] # print "heya" flag = 0 if ir[end].type == 'ifgoto' or ir[end].type == 'printint' or ir[ end].type == 'printstr' or ir[end].type == 'scan' or ir[ end].type == 'retint' or ir[end].type == 'retvoid' or ir[ end].type == 'goto' or ir[end].type == 'callint' or ir[ end].type == 'callvoid': flag = 1 for lineNo in range(start, end + 1 - flag): genAsm.genInstr("# " + ir[lineNo].instr) # print "hee heya" codeGeneratorPerLine(lineNo, nextUseTable) ## Write all the registers back to Memory for reg, symbol in regDes.iteritems(): if symbol is not None and addrDes[symbol]['memory'] is False: genAsm.genInstr('movl %' + reg + ', ' + symbol) # regDes[reg] = None # addrDes[symbol]['register'] = None addrDes[symbol]['memory'] = True addrDes[symbol]['register'] = None regDes[reg] = None elif symbol is not None: addrDes[symbol]['register'] = None regDes[reg] = None if flag: genAsm.genInstr("# " + ir[end].instr) codeGeneratorPerLine(end, nextUseTable)
def genCompare(symbolType): if symbolType == '<=' or symbolType == '<': genAsm.genInstr("setle %al") elif symbolType == '!=': genAsm.genInstr("setne %al") elif symbolType == '>' or symbolType == '>=': genAsm.genInstr("setg %al") elif symbolType == '==': genAsm.genInstr("sete %al")
def getreg(instrNum, nextUseTable): if ir[instrNum].type in type_4: # x = y Op z x = ir[instrNum].dst y = ir[instrNum].src1 z = ir[instrNum].src2 if (addrDes[y]['register'] != None) and (nextUseTable[instrNum][y]['nextUse'] is None): reg = addrDes[y]['register'] if addrDes[y]['memory'] is False: genAsm.genInstr("movl %" + reg + ", " + y) addrDes[y]['memory'] = True addrDes[y]['register'] = None return reg elif emptyReg() != None: return emptyReg() else: if nextUseTable[instrNum][x]['nextUse'] is not None or regImp( instrNum): return regAlloc(instrNum, nextUseTable) else: return None # Use it's default memory location defined in .data section elif ir[instrNum].type in type_3: # x Op= y x = ir[instrNum].dst y = ir[instrNum].src1 if check_int(y) and ir[instrNum].type != 'pload': return int(y, 10) if ir[instrNum].type == 'callint': if regDes['eax']: var = regDes['eax'] splitReg('eax', var) return 'eax' else: # shifting case if ir[instrNum].type == '<<=' or ir[instrNum].type == '>>=': if addrDes[x]['register'] != 'ecx': return addrDes[x]['register'] elif emptyReg() != None: if addrDes[x]['register'] == 'ecx': genAsm.genInstr('movl %ecx, ' + x) addrDes[x]['memory'] = True return emptyReg() else: if addrDes[x]['register'] == 'ecx': genAsm.genInstr('movl %ecx, ' + x) addrDes[x]['memory'] = True if nextUseTable[instrNum][x][ 'nextUse'] is not None or regImp(instrNum): return regAlloc(instrNum, nextUseTable, True) else: return None # Use it's default memory location defined in .data section # x Op= y ~ x = x Op y, so same rule as above # If already in register, return it if addrDes[x]['register']: return addrDes[x]['register'] elif emptyReg() != None: return emptyReg() else: if nextUseTable[instrNum][x]['nextUse'] is not None or regImp( instrNum): return regAlloc(instrNum, nextUseTable) else: return None # Use it's default memory location defined in .data section elif ir[instrNum].type in type_2: # x++ or retint x x = ir[instrNum].dst if ir[instrNum].type == 'retint': if regDes['eax']: var = regDes['eax'] splitReg('eax', var) return 'eax' else: # x Op= y ~ x = x Op y, so same rule as above # If already in register, return it if addrDes[x]['register']: return addrDes[x]['register'] elif emptyReg() != None: return emptyReg() else: if nextUseTable[instrNum][x]['nextUse'] is None or regImp( instrNum): return regAlloc(instrNum, nextUseTable) else: return None # Use it's default memory location defined in .data section
def splitReg(reg, var): if addrDes[var]['memory'] is False: genAsm.genInstr("movl %" + reg + ", " + var) addrDes[var]['memory'] = True addrDes[var]['register'] = None regDes[reg] = None
def codeGeneratorPerLine(lineNo, nextUseTable): instrType = "heya" ## need to segregate instrType on the basis of immediate? ## long switch case for deciphering the kind of instruction store that in instrType def instrTypeFunc(x): return { '+': "addl", '-': "subl", 'x': "imul", '/': "idivl", '%': "mod", '&': "and", '|': "or", '^': "xor", '==': "cmp", '<': "cmp", '>': "cmp", '!=': "cmp", '<=': "cmp", '>=': "cmp", '=': "movl", '!': "notl", '+=': "addl", '-=': "subl", 'x=': "imul", '&=': "and", '|=': "or", '^=': "xor", '<<=': 'shl', '>>=': 'shr', '++': "incl", '--': "decl", 'label': "label", 'printint': "call printf", 'printstr': "call printf", 'scan': "call scanf", 'ifgoto': "jne", 'callint': "call", 'load': 'movl', 'store': 'movl', 'array': 'sub', 'pload': 'movl', 'addr': 'lea', 'callvoid': "call", 'goto': "jmp", 'retint': "ret", 'push': "pushl", 'pop': 'popl', 'retvoid': "ret" }.get(x, "not defined instruction") instrType = instrTypeFunc(ir[lineNo].type) if instrType == "not defined instruction": raise ValueError('Instruction ' + instrType + ' not defined in x86') if ir[lineNo].type in type_4: # For shitty divide and mod if ir[lineNo].type == '/' or ir[lineNo].type == '%': edx = regDes['edx'] eax = regDes['eax'] if edx is not None: genAsm.genInstr("movl %edx, " + edx) addrDes[edx]['memory'] = True addrDes[edx]['register'] = None if eax is not None: genAsm.genInstr("movl %eax, " + eax) addrDes[eax]['memory'] = True addrDes[eax]['register'] = None genAsm.genInstr("movl $0, %edx") if addrDes[ir[lineNo].src1]['register'] is not None: dividend = addrDes[ir[lineNo].src1]['register'] genAsm.genInstr("movl %" + dividend + ", %eax") else: dividend = ir[lineNo].src1 genAsm.genInstr("movl " + dividend + ", %eax") if addrDes[ir[lineNo].src2]['register'] is not None: divisor = addrDes[ir[lineNo].src2]['register'] genAsm.genInstr("idivl %" + divisor) else: divisor = ir[lineNo].src2 genAsm.genInstr("idivl " + divisor) if ir[lineNo].type == '/': if addrDes[ir[lineNo].dst]['register'] is None: genAsm.genInstr("movl %eax, " + ir[lineNo].dst) else: quet = addrDes[ir[lineNo].dst]['register'] genAsm.genInstr("movl %eax, %" + quet) addrDes[ir[lineNo].dst]['memory'] = False else: if addrDes[ir[lineNo].dst]['register'] is None: genAsm.genInstr("movl %edx, " + ir[lineNo].dst) else: quet = addrDes[ir[lineNo].dst]['register'] genAsm.genInstr("movl %edx, %" + quet) addrDes[ir[lineNo].dst]['memory'] = False if edx is not None: genAsm.genInstr("movl (" + edx + "), %edx") if eax is not None: genAsm.genInstr("movl (" + eax + "), %eax") return regSrc1 = addrDes[ir[lineNo].src1]['register'] locationDst = getreg.getreg(lineNo, nextUseTable) isInMemory = addrDes[ir[lineNo].dst]['memory'] #if isInMemory: # genAsm.genInstr('movl ('+ir[lineNo].dst+'), %'+locationDst) # print "heya" if regSrc1 is not None and regSrc1 != locationDst: genAsm.genInstr("movl %" + regSrc1 + ", %" + locationDst) elif regSrc1 is None and regSrc1 != locationDst: genAsm.genInstr("movl (" + ir[lineNo].src1 + "), %" + locationDst) else: if addrDes[ir[lineNo].src1]['memory'] is False: genAsm.genInstr("movl %" + regSrc1 + ", " + ir[lineNo].src1) regDes[regSrc1] = ir[lineNo].dst addrDes[ir[lineNo].src1]['register'] = None addrDes[ir[lineNo].src1]['memory'] = True regSrc2 = addrDes[ir[lineNo].src2]['register'] ## for compare types if ir[lineNo].type == '>=': genAsm.genInstr("addl $1, %" + locationDst) elif ir[lineNo].type == '<': genAsm.genInstr("addl $1, %" + locationDst) ## for all types if regSrc2 == None: genAsm.genInstr(instrType + " (" + ir[lineNo].src2 + "), %" + locationDst) else: genAsm.genInstr(instrType + " %" + regSrc2 + ", %" + locationDst) ## for compare types if ir[lineNo].type in comparators: var = regDes['eax'] if var is None: genCompare(ir[lineNo].type) genAsm.genInstr("movzbl %al, %" + locationDst) else: if locationDst != 'eax': genAsm.genInstr("movl %eax, " + var) genCompare(ir[lineNo].type) genAsm.genInstr("movzbl %al, %" + locationDst) if locationDst != 'eax': genAsm.genInstr("movl (" + var + "), %eax") addrDes[ir[lineNo].dst]['register'] = locationDst addrDes[ir[lineNo].dst]['memory'] = False for x in regDes: if regDes[x] == ir[lineNo].dst: regDes[x] = None regDes[locationDst] = ir[lineNo].dst # if nextUseTable[lineNo][ir[lineNo].src1]['nextUse'] is None: # for x in regDes: # if regDes[x] == ir[lineNo].src1: # regDes[x] = None # if nextUseTable[lineNo][ir[lineNo].src2]['nextUse'] is None: # for x in regDes: # if regDes[x] == ir[lineNo].src2: # regDes[x] = None elif ir[lineNo].type in type_3: ## ifgoto type ## Only dutta can do this if ir[lineNo].type == 'ifgoto': regDst = addrDes[ir[lineNo].dst]['register'] if regDst is None: genAsm.genInstr("cmp $0, (" + ir[lineNo].dst + ")") else: genAsm.genInstr("cmp $0, %" + regDst) genAsm.genInstr(instrType + " " + ir[lineNo].src1) ## immediate instructions a+=3 types, what about =,a,b and =,a,4 ???? LOST IT COMPLETELY! elif check_int(ir[lineNo].src1): locationDst = getreg.getreg(lineNo, nextUseTable) if ir[lineNo].type == 'pload': offset = 4 * int(ir[lineNo].src1) + 8 genAsm.genInstr("movl " + hex(offset) + "(%ebp)" + ", %" + locationDst) addrDes[ir[lineNo].dst]['register'] = locationDst addrDes[ir[lineNo].dst]['memory'] = False for x in regDes: if regDes[x] == ir[lineNo].dst: regDes[x] = None regDes[locationDst] = ir[lineNo].dst else: isRegDst = addrDes[ir[lineNo].dst]['register'] if isRegDst is None: genAsm.genInstr(instrType + " $" + str(locationDst) + ", " + ir[lineNo].dst) addrDes[ir[lineNo].dst]['memory'] = True else: genAsm.genInstr(instrType + " $" + str(locationDst) + ", %" + isRegDst) ## if destination is not used next # if nextUseTable[lineNo][ir[lineNo].dst]['nextUse'] is None: # for x in regDes: # if regDes[x] == ir[lineNo].dst: # regDes[x] = None else: locationDst = getreg.getreg(lineNo, nextUseTable) ## function call if ir[lineNo].type == 'callint': genAsm.genInstr(instrType + ' ' + ir[lineNo].src1) genAsm.genInstr('movl %eax, ' + ir[lineNo].dst) addrDes[ir[lineNo].dst]['register'] = None addrDes[ir[lineNo].dst]['memory'] = True ## in general a+=b type instructions and a=b ?? else: isRegSrc = addrDes[ir[lineNo].src1]['register'] ## added NOWW isInMemory = addrDes[ir[lineNo].dst]['memory'] #print "heya" #print isInMemory if isInMemory: genAsm.genInstr('movl (' + ir[lineNo].dst + '), %' + locationDst) ## ---------- ## if source variable is in memory if isRegSrc is None: if ir[lineNo].type == 'load': genAsm.genInstr("movl (" + ir[lineNo].src1 + "), %" + locationDst) genAsm.genInstr(instrType + " (%" + locationDst + "), %" + locationDst) addrDes[ir[lineNo].dst]['register'] = locationDst addrDes[ir[lineNo].dst]['memory'] = False # lol elif ir[lineNo].type == 'store': genAsm.genInstr("pushl (" + ir[lineNo].src1 + ")") genAsm.genInstr("popl (%" + locationDst + ")") elif ir[lineNo].type == 'array': genAsm.genInstr('subl $4, %esp') genAsm.genInstr('subl (' + ir[lineNo].src1 + '), %esp') genAsm.genInstr('movl %esp, %' + locationDst) addrDes[ir[lineNo].dst]['register'] = locationDst addrDes[ir[lineNo].dst]['memory'] = False elif ir[lineNo].type == 'addr': genAsm.genInstr('lea (' + ir[lineNo].src1 + '), %' + locationDst) addrDes[ir[lineNo].dst]['register'] = locationDst addrDes[ir[lineNo].dst]['memory'] = False elif ir[lineNo].type == '>>=' or ir[lineNo].type == '<<=': genAsm.genInstr('pushl %ecx') genAsm.genInstr('movl (' + ir[lineNo].src1 + '), %ecx') genAsm.genInstr(instrType + " %cl, %" + locationDst) genAsm.genInstr('popl %ecx') addrDes[ir[lineNo].dst]['register'] = locationDst addrDes[ir[lineNo].dst]['memory'] = False else: genAsm.genInstr(instrType + " (" + ir[lineNo].src1 + "), %" + locationDst) addrDes[ir[lineNo].dst]['register'] = locationDst addrDes[ir[lineNo].dst]['memory'] = False ## if source variable is in register already else: if ir[lineNo].type == 'load': genAsm.genInstr(instrType + " (%" + isRegSrc + "), %" + locationDst) addrDes[ir[lineNo].dst]['register'] = locationDst addrDes[ir[lineNo].dst]['memory'] = False elif ir[lineNo].type == 'store': genAsm.genInstr("movl %" + isRegSrc + ", (%" + locationDst + ")") elif ir[lineNo].type == 'array': genAsm.genInstr('subl $4, %esp') genAsm.genInstr('subl %' + isRegSrc + ', %esp') genAsm.genInstr('movl %esp, %' + locationDst) addrDes[ir[lineNo].dst]['register'] = locationDst addrDes[ir[lineNo].dst]['memory'] = False elif ir[lineNo].type == '>>=' or ir[lineNo].type == '<<=': genAsm.genInstr('pushl %ecx') genAsm.genInstr('movl %' + isRegSrc + ', %ecx') genAsm.genInstr(instrType + " %cl, %" + locationDst) genAsm.genInstr('popl %ecx') addrDes[ir[lineNo].dst]['register'] = locationDst addrDes[ir[lineNo].dst]['memory'] = False elif ir[lineNo].type == 'addr': genAsm.genInstr('lea (%' + isRegSrc + '), %' + locationDst) addrDes[ir[lineNo].dst]['register'] = locationDst addrDes[ir[lineNo].dst]['memory'] = False elif locationDst != isRegSrc: genAsm.genInstr(instrType + " %" + isRegSrc + ", %" + locationDst) addrDes[ir[lineNo].dst]['register'] = locationDst addrDes[ir[lineNo].dst]['memory'] = False else: genAsm.genInstr("movl %" + isRegSrc + ", " + ir[lineNo].src1) addrDes[ir[lineNo].src1]['register'] = None addrDes[ir[lineNo].src1]['memory'] = True ### DOUBT HERE ------------ where is the instruction ??? genAsm.genInstr(instrType + " %" + isRegSrc + ", %" + locationDst) ### ---- ADDED NOWW ---- addrDes[ir[lineNo].dst]['register'] = locationDst addrDes[ir[lineNo].dst]['memory'] = False for x in regDes: if regDes[x] == ir[lineNo].dst: regDes[x] = None regDes[locationDst] = ir[lineNo].dst ## delete register occurrences if source variable is not used again in bbl # if nextUseTable[lineNo][ir[lineNo].src1]['nextUse'] is None: # for x in regDes: # if regDes[x] == ir[lineNo].src1: # regDes[x] = None elif ir[lineNo].type in type_2: if ir[lineNo].type in ["++", "--", "!"]: isRegDst = addrDes[ir[lineNo].dst]['register'] ## if in memory directly use incr a. if isRegDst is None: genAsm.genInstr(instrType + " " + ir[lineNo].dst) ## else increment a in register else: genAsm.genInstr(instrType + " %" + isRegDst) addrDes[ir[lineNo].dst]['memory'] = False elif ir[lineNo].type == 'label': genAsm.genLabel(ir[lineNo].dst) if ST.table[ir[lineNo].dst]['type'] == "func": genAsm.genInstr("pushl %ebp") genAsm.genInstr("movl %esp, %ebp") elif ir[lineNo].type == 'printint': if addrDes[ir[lineNo].dst]['register'] is None: genAsm.genInstr("pushl " + ir[lineNo].dst) genAsm.genInstr("pushl $outFormatInt") genAsm.genInstr(instrType) else: genAsm.genInstr("pushl %" + addrDes[ir[lineNo].dst]['register']) genAsm.genInstr("pushl $outFormatInt") genAsm.genInstr(instrType) elif ir[lineNo].type == 'printstr': if addrDes[ir[lineNo].dst]['register'] is None: genAsm.genInstr("pushl " + ir[lineNo].dst) genAsm.genInstr("pushl $outFormatStr") genAsm.genInstr(instrType) else: genAsm.genInstr("pushl %" + addrDes[ir[lineNo].dst]['register']) genAsm.genInstr("pushl $outFormatStr") genAsm.genInstr(instrType) elif ir[lineNo].type == 'scan': if addrDes[ir[lineNo].dst]['register'] is None: genAsm.genInstr("pushl $" + ir[lineNo].dst) genAsm.genInstr("pushl $inFormat") genAsm.genInstr(instrType) else: genAsm.genInstr("pushl $" + regDes[addrDes[ir[lineNo].dst]['register']]) genAsm.genInstr("pushl $inFormat") genAsm.genInstr(instrType) addrDes[ir[lineNo].dst]["memory"] = True genAsm.genInstr("movl (" + ir[lineNo].dst + "), %" + addrDes[ir[lineNo].dst]['register']) elif ir[lineNo].type == 'callvoid': genAsm.genInstr(instrType + " " + ir[lineNo].dst) elif ir[lineNo].type == 'goto': genAsm.genInstr(instrType + ' ' + ir[lineNo].dst) elif ir[lineNo].type == 'retint': locationDst = getreg.getreg(lineNo, nextUseTable) if check_int(ir[lineNo].dst): genAsm.genInstr('movl $' + ir[lineNo].dst + ', %' + locationDst) else: regDst = addrDes[ir[lineNo].dst]['register'] if (regDst is None): genAsm.genInstr('movl (' + ir[lineNo].dst + '), %' + locationDst) else: genAsm.genInstr('movl %' + regDst + ', %' + locationDst) genAsm.genInstr("leave") genAsm.genInstr(instrType) elif ir[lineNo].type == 'push': if addrDes[ir[lineNo].dst]['register'] is None: genAsm.genInstr("pushl " + ir[lineNo].dst) else: genAsm.genInstr("pushl %" + addrDes[ir[lineNo].dst]['register']) elif ir[lineNo].type == 'pop': regDst = addrDes[ir[lineNo].dst]['register'] if (regDst is None): genAsm.genInstr('popl ' + ir[lineNo].dst) else: genAsm.genInstr('popl %' + regDst) addrDes[ir[lineNo].dst]['memory'] = False elif ir[lineNo].type in type_1: genAsm.genInstr("leave") genAsm.genInstr(instrType)