def visitSLambda(self, n): # Creat New Label label_name = 'Q' + generate_name("SLambda") # Recurse on code body slambdas = [] (code, rslambdas) = self.dispatch(n.code, False) slambdas += rslambdas # Setup fvs list fvs_n = generate_name("fvs") fvs = [] # Setup each free variable stmts = [] cnt = 0 for var in n.free_vars: fvs += [Name(var)] stmt = make_assign(var, Subscript(Name(fvs_n), [InjectFrom(INT_t, Const(cnt))])) stmts += [stmt] cnt += 1 # Setup list of stmts stmts += code.nodes # Setup params, appending fvs params = [] params += [fvs_n] params += n.params #Create SLambdaLabel label = SLambdaLabel(label_name, len(params)) # Create new closed slambda slambdas += [SLambda(params, StmtList(stmts), label_name)] # Return Call and list of SLambdas return (InjectFrom(BIG_t, CallCREATECLOSURE([label, List(fvs)])), slambdas)
def explicateBinary(self, lhsexpr, rhsexpr, smallFunc, smallType, bigFunc, bigType): lhsname = generate_name('let_binexp_lhs') rhsname = generate_name('let_binexp_rhs') lhsvar = Name(lhsname) rhsvar = Name(rhsname) t = mono_Let(lhsvar, self.dispatch(lhsexpr), mono_Let(rhsvar, self.dispatch(rhsexpr), # Small-Small Case IfExp(And([Or([mono_IsTag(BOOL_t, lhsvar), mono_IsTag(INT_t, lhsvar)]), Or([mono_IsTag(BOOL_t, rhsvar), mono_IsTag(INT_t, rhsvar)])]), mono_InjectFrom(smallType, smallFunc((self.projectType(lhsvar), self.projectType(rhsvar)))), # Big-Big Case IfExp(And([mono_IsTag(BIG_t, lhsvar), mono_IsTag(BIG_t, rhsvar)]), mono_InjectFrom(bigType, bigFunc([self.projectType(lhsvar), self.projectType(rhsvar)])), # Mixed Case # TODO: Add mixed case logic CallTERROR([]))))) return t
def visitCallFunc(self, n, target): instrList = [] args = [] for arg in n.args: if isinstance(arg, SLambdaLabel): name = generate_name("instrsel_SLamdaLabel") numargs = 0 temp = VarLLVM(LocalLLVM(name), DEFAULTTYPE) arg_types = LLVMFuncPtrType(DEFAULTTYPE, DEFAULTTYPE, arg.numargs) value = VarLLVM(GlobalLLVM(arg.name),arg_types) instrList += [ptrtointLLVM(temp, value, DEFAULTTYPE)] args += [temp] elif isinstance(arg, String): stringArray = LLVMArray(len(arg.string) + 1, I8) actualString = LLVMString(stringArray, arg.string) tmp = VarLLVM(GlobalLLVM(generate_name("stringName")), stringArray) stringDeclare = declareLLVMString(tmp, actualString) self.stringsInstr += [stringDeclare] placeholder = VarLLVM(LocalLLVM(generate_name("cast")), PI8) cast = getelementptrLLVM(placeholder, tmp, [DEFAULTZERO, DEFAULTZERO]) instrList += [cast] args += [placeholder] else: args += [self.dispatch(arg)] instrList += [callLLVM(DEFAULTTYPE, GlobalLLVM(n.node.name), args, target)] return instrList
def explicateBinary(self, lhsexpr, rhsexpr, smallFunc, smallType, bigFunc, bigType, mixedDefault, op=None): lhsname = generate_name('let_binexp_lhs') rhsname = generate_name('let_binexp_rhs') lhsvar = Name(lhsname) rhsvar = Name(rhsname) t = Let(lhsvar, self.dispatch(lhsexpr), Let(rhsvar, self.dispatch(rhsexpr), # Small-Small Case IfExp(And([Or([IsTag(BOOL_t, lhsvar), IsTag(INT_t, lhsvar)]), Or([IsTag(BOOL_t, rhsvar), IsTag(INT_t, rhsvar)])]), InjectFrom(smallType, (smallFunc((self.projectType(lhsvar), self.projectType(rhsvar)))) if op==None else (smallFunc(op, (self.projectType(lhsvar), self.projectType(rhsvar))))), # Big-Big Case IfExp(And([IsTag(BIG_t, lhsvar), IsTag(BIG_t, rhsvar)]), InjectFrom(bigType, bigFunc([self.projectType(lhsvar), self.projectType(rhsvar)])), # Mixed Case mixedDefault)))) return t
def visitmono_IntUnarySub(self, n, needs_to_be_simple): (expr,ss) = self.dispatch(n.expr, True) if needs_to_be_simple: tmp = generate_name('usubtmp') return (Name(tmp), ss + [make_assign(tmp, mono_IntUnarySub(expr))]) else: return (mono_IntUnarySub(expr), ss)
def visitLambda(self, n, renaming): new_renaming = copy.deepcopy(renaming) local_vars = n.args for v in local_vars: new_renaming[v] = generate_name(v) return Lambda([new_renaming[x] for x in n.args], self.dispatch(n.expr, new_renaming))
def visitLet(self, n, renaming): new_renaming = copy.deepcopy(renaming) new_renaming[n.var] = generate_name(n.var.name) var = self.dispatch(n.var, new_renaming) rhs = self.dispatch(n.rhs, renaming) body = self.dispatch(n.body, new_renaming) return Let(var, rhs, body)
def specializeCallFunc(self, n): if isinstance(n.node, Name) and n.node.name in RESERVED_NAMES: return CallFunc(self.dispatch(n.node), map(self.dispatch, n.args)) ftemp = generate_name('func') def gen_arg(args, vals): if args: temp = generate_name('arg') return Let(Name(temp), self.dispatch(args[0]), gen_arg(args[1:], vals + [Name(temp)])) else: objtemp = generate_name('obj') initemp = generate_name('ini') discardtemp = generate_name('discard') return IfExp(CallISCLASS([Name(ftemp)]), Let(Name(objtemp), CallCREATEOBJECT([Name(ftemp)]), IfExp(CallHASATTR([Name(ftemp), String('__init__')]), Let(Name(discardtemp), CallFunc(CallGETFUNCTION([GetAttr(Name(ftemp), '__init__')]), [Name(objtemp)]+vals), Name(objtemp)), Name(objtemp))), IfExp(CallISBOUNDMETHOD([Name(ftemp)]), CallFunc(CallGETFUNCTION([Name(ftemp)]), [CallGETRECEIVER([Name(ftemp)])]+vals), IfExp(CallISUNBOUNDMETHOD([Name(ftemp)]), CallFunc(CallGETFUNCTION([Name(ftemp)]), vals), CallFunc(Name(ftemp), vals)))) return Let(Name(ftemp), self.dispatch(n.node), gen_arg(n.args, []))
def visitSubscriptAssign(self, n): name = generate_name('sub') return Discard(Let(Name(name), self.dispatch(n.value), CallSETSUB([self.dispatch(n.target), self.dispatch(n.subs[0]), Name(name)])))
def visitIntCmp(self, n, needs_to_be_simple): (left, ss1) = self.dispatch(n.left, True) (right, ss2) = self.dispatch(n.right, True) if needs_to_be_simple: tmp = generate_name('intequaltmp') return (Name(tmp), ss1 + ss2 + [make_assign(tmp, IntCmp(n.op, (left, right)))]) else: return (IntCmp(n.op, (left, right)), ss1 + ss2)
def visitFunction(self, n, renaming): new_renaming = copy.deepcopy(renaming) local_vars = FindLocalsVisitor().preorder(n.code) | set(n.args) for v in local_vars: new_renaming[v] = generate_name(v) return Function(renaming[n.name], [new_renaming[x] for x in n.args], self.dispatch(n.code, new_renaming))
def visitmono_IntNotEqual(self, n, needs_to_be_simple): (left, ss1) = self.dispatch(n.left, True) (right, ss2) = self.dispatch(n.right, True) if needs_to_be_simple: tmp = generate_name('intnotequaltmp') return (Name(tmp), ss1 + ss2 + [make_assign(tmp, mono_IntNotEqual((left, right)))]) else: return (mono_IntNotEqual((left, right)), ss1 + ss2)
def visitClass(self, n, scope): classtemp = generate_name(n.name + '_temp') bases = map(self.dispatch, n.bases) stmts = [VarAssign(classtemp, CallCREATECLASS([List(bases)]))] stmts += DeclassifyVisitor(classtemp, self).preorder(n.code, scope).nodes stmts += [VarAssign(n.name, Name(classtemp))] return stmts
def fixMemToMem(instrs, colors): regTempPrefix = "RegTmp" def validNode(val): return isinstance(val, Var86) def name(val): if isinstance(val, Var86): return val.name else: raise Exception("Attempting to get name of invalid argument: " + str(val)) def addTemp(instr, tmp): if(isinstance(instr, Add86)): return [Move86(instr.value, tmp), Add86(tmp, instr.target)] elif(isinstance(instr, Sub86)): return [Move86(instr.value, tmp), Sub86(tmp, instr.target)] elif(isinstance(instr, Move86)): return [Move86(instr.value, tmp), Move86(tmp, instr.target)] elif(isinstance(instr, Comp86)): return [Move86(instr.value, tmp), Comp86(tmp, instr.target)] else: raise Exception("Cannot add temp to node: " + str(instr)) fixedInstrs = [] regOnlyVars = [] #Loop through instructions for instr in instrs: # Binary read/write if(isinstance(instr, Add86) or isinstance(instr, Sub86) or isinstance(instr, Move86) or isinstance(instr, Comp86)): if(validNode(instr.target) and validNode(instr.value)): # Find mem to mem operations if((colors[name(instr.target)] >= len(REGCOLORS)) and (colors[name(instr.value)] >= len(REGCOLORS))): # Add temp var tmp = Var86(generate_name(regTempPrefix)) fixedInstrs += addTemp(instr, tmp) regOnlyVars += [tmp.name] else: fixedInstrs += [instr] else: fixedInstrs += [instr] else: fixedInstrs += [instr] return (fixedInstrs, regOnlyVars)
def visitUnarySub(self, n): varname = generate_name('let_us_expr') exprvar = Name(varname) t = mono_Let(exprvar, self.dispatch(n.expr), IfExp(Or([mono_IsTag(INT_t, exprvar), mono_IsTag(BOOL_t, exprvar)]), mono_InjectFrom(INT_t, mono_IntUnarySub(mono_ProjectTo(INT_t, exprvar))), CallTERROR([]))) return t
def visitIndirectCallFunc(self, n, target): args = [] instrList = [] for arg in n.args: args += [self.dispatch(arg)] arg_types = LLVMFuncPtrType(DEFAULTTYPE, DEFAULTTYPE, len(n.args)) tmp = VarLLVM(LocalLLVM(generate_name("inttoptrConversion")), DEFAULTTYPE) instrList += [inttoptrLLVM(tmp, VarLLVM(LocalLLVM(n.node.name), DEFAULTTYPE), arg_types)] instrList += [callLLVM(DEFAULTTYPE, getArg(tmp), args, target)] return instrList
def visitUnarySub(self, n): varname = generate_name('let_us_expr') exprvar = Name(varname) t = Let(exprvar, self.dispatch(n.expr), IfExp(IsTag(INT_t, exprvar), InjectFrom(INT_t, IntUnarySub(ProjectTo(INT_t, exprvar))), IfExp(IsTag(BOOL_t, exprvar), InjectFrom(INT_t, IntUnarySub(ProjectTo(BOOL_t, exprvar))), CallGERROR([])))) return t
def visitDict(self, n, needs_to_be_simple): myss = [] # Create new Dict (expr, ss) = self.dispatch(CallINJECTBIG([CallMAKEDICT([])]), needs_to_be_simple) myss += ss # Add each dict memeber for item in n.items: valname = generate_name('item') myss += self.dispatch(Discard(Let(Name(valname), item[1], CallSETSUB([expr, item[0], Name(valname)])))) return (expr, myss)
def visitCallFunc(self, n, needs_to_be_simple): if isinstance(n.node, Name): args_sss = [self.dispatch(arg, True) for arg in n.args] args = [arg for (arg,ss) in args_sss] ss = reduce(lambda a,b: a + b, [ss for (arg,ss) in args_sss], []) if needs_to_be_simple: tmp = generate_name('callfunctmp') return (Name(tmp), ss + [make_assign(tmp, CallFunc(n.node, args))]) else: return (CallFunc(n.node, args), ss) else: raise Exception('flatten: only calls to named functions allowed')
def gen_arg(args, vals): if args: temp = generate_name('arg') return Let(Name(temp), self.dispatch(args[0]), gen_arg(args[1:], vals + [Name(temp)])) else: objtemp = generate_name('obj') initemp = generate_name('ini') discardtemp = generate_name('discard') return IfExp(CallISCLASS([Name(ftemp)]), Let(Name(objtemp), CallCREATEOBJECT([Name(ftemp)]), IfExp(CallHASATTR([Name(ftemp), String('__init__')]), Let(Name(discardtemp), CallFunc(CallGETFUNCTION([GetAttr(Name(ftemp), '__init__')]), [Name(objtemp)]+vals), Name(objtemp)), Name(objtemp))), IfExp(CallISBOUNDMETHOD([Name(ftemp)]), CallFunc(CallGETFUNCTION([Name(ftemp)]), [CallGETRECEIVER([Name(ftemp)])]+vals), IfExp(CallISUNBOUNDMETHOD([Name(ftemp)]), CallFunc(CallGETFUNCTION([Name(ftemp)]), vals), CallFunc(Name(ftemp), vals))))
def visitIndirectCallFunc(self, n): slambdas = [] (node, rslambdas) = self.dispatch(n.node) slambdas += rslambdas args = [] for arg in n.args: (rarg, rslambdas) = self.dispatch(arg) args += [rarg] slambdas += rslambdas tmpname = generate_name('let_ICF') tmpvar = Name(tmpname) t = Let(tmpvar, node, IndirectCallFunc(CallGETFUNPTR([tmpvar]), ([CallGETFREEVARS([tmpvar])] + args))) return (t, slambdas)
def visitIndirectCallFunc(self, n, needs_to_be_simple): if isinstance(n.node, CallFunc): args_sss = [self.dispatch(arg, True) for arg in n.args] args = [arg for (arg,ss) in args_sss] ss = reduce(lambda a,b: a + b, [ss for (arg,ss) in args_sss], []) (expr, sss) = self.dispatch(n.node, True) ss += sss if needs_to_be_simple: tmp = generate_name('indirectcallfunctmp') return (Name(tmp), ss + [make_assign(tmp, IndirectCallFunc(expr, args))]) else: return (IndirectCallFunc(expr, args), ss) else: raise Exception('flatten: only indirectcalls to closure converted functions allowed')
def visitmono_IfExp(self, n, needs_to_be_simple): (teste, testss) = self.dispatch(n.test, True) (thene, thenss) = self.dispatch(n.then, True) (elsee, elsess) = self.dispatch(n.else_, True) simple = mono_IfExp(teste, flat_InstrSeq(thenss, thene), flat_InstrSeq(elsess, elsee)) if needs_to_be_simple: tmp = generate_name('ifexptmp') myexpr = (Name(tmp)) myss = [make_assign(tmp, simple)] else: myexpr = simple myss = [] return (myexpr, testss + myss)
def visitWhileFlat(self, n, funcName): #Setup Label whileStartL, whileEndL = generate_while_labels() # Test Instructions testtmp = Var86(generate_name(WHILETESTTMP)) test = [] test += [Label86(whileStartL)] test += self.dispatch(n.testss, funcName) test += self.dispatch(n.test, testtmp) test += [Comp86(x86FALSE, testtmp)] test += [JumpEqual86(whileEndL)] # Body Instructions body = [] body += self.dispatch(n.body, funcName) body += [Jump86(whileStartL)] body += [Label86(whileEndL)] return [Loop86(test, body)]
def make_branches(testlist, caseLs, else_): if testlist: test, body = testlist[0] tmp = Var86(generate_name(IFTEMP)) tinstrs = self.dispatch(test, tmp) tinstrs += [Comp86(x86FALSE, tmp)] tinstrs += [JumpEqual86(caseLs[0])] ninstrs = self.dispatch(body, func_name) ninstrs += [Jump86(endIfL)] einstrs = [Label86(caseLs[0])] + make_branches(testlist[1:], caseLs[1:], else_) return tinstrs + [If86(ninstrs, einstrs)] else: instrs = self.dispatch(else_, func_name) instrs += [Label86(endIfL)] return instrs
def visitSLambda(self, n): lvs = n.local_vars self.needs_heapification = self.needs_heapification | self.nested_visitor.preorder(n.code) code = self.dispatch(n.code) new_params = [] new_stmts = [] for param in n.params: if param in self.needs_heapification: new_param = generate_name('heaped_at_')+param new_stmts.append(VarAssign(param, List([ZERO]))) new_stmts.append(SubscriptAssign(Name(param), [ZERO], Name(new_param))) new_params.append(new_param) else: new_params.append(param) for local in lvs: if local in self.needs_heapification: new_stmts.append(VarAssign(local, List([ZERO]))) ret = SLambda(new_params, StmtList(new_stmts + code.nodes)) ret.free_vars = n.free_vars return ret
def visitIntCmp(self, n, target): if(n.op == PY_EQ): op = ICMP_EQ elif(n.op == PY_NE): op = ICMP_NE elif(n.op == PY_GT): op = ICMP_SGT elif(n.op == PY_GE): op = ICMP_SGE elif(n.op == PY_LT): op = ICMP_SLT elif(n.op == PY_LE): op = ICMP_SLE else: raise Exception("Unknown op in IntCmp") left = self.dispatch(n.left) right = self.dispatch(n.right) tmp = VarLLVM(LocalLLVM(generate_name(ICMPTEMP)), LLVMBOOLTYPE) instrs = [] instrs += [icmpLLVM(tmp, op, left, right)] instrs += [zextLLVM(target, tmp, DEFAULTTYPE)] return instrs
def OrToIfExp(self, nodes): if(len(nodes) < 2): # Error Condition raise Exception("expand: OR expression must have at least 2 nodes") thisnode = self.dispatch(nodes[0]) thistmp = generate_name('or') if(len(nodes) == 2): # Exit Condition nextnode = self.dispatch(nodes[1]) return Let(Name(thistmp), thisnode, IfExp(CallISTRUE([Name(thistmp)]), Name(thistmp), nextnode)) else: # Recurse return Let(Name(thistmp), thisnode, IfExp(CallISTRUE([Name(thistmp)]), Name(thistmp), self.AndToIfExp(nodes[1:])))
def visitDiscard(self, n): tmp = Var86(generate_name(DISCARDTEMP)) return self.dispatch(n.expr, tmp)
def visitString(self, n): location = '.L' + generate_name('str') n.location = location return set([(location, n.string)])