Beispiel #1
0
    def process(self, dst, originalNode, code, map, selfarg, args, returnargs):
        self.localMap = {}

        self.dst = dst
        self.originalNode = originalNode
        self.contextRemap = map

        self.returnargs = returnargs
        outp = []

        p = code.codeparameters

        # Do argument transfer
        if isinstance(p.selfparam, ast.Local):
            outp.append(ast.Assign(selfarg, [self(p.selfparam)]))

        for arg, param in zip(args, p.params):
            if isinstance(param, ast.Local):
                outp.append(ast.Assign(arg, [self(param)]))

        assert not isinstance(p.vparam, ast.Local), p.vparam
        #assert len(args) == len(p.params), "TODO: default arguments."

        outp.append(self(code.ast))

        return outp
Beispiel #2
0
	def visitAssign(self, node):
		assert self.locals

		if any([len(self.localuses[lcl]) > 0 for lcl in node.lcls]):
			expr = self(node.expr)

			assert self.locals, node.expr

			if isinstance(node.expr, ast.Local):
				# Assign local to local.  Nullop for SSA.
				assert len(node.lcls) == 1

				expr = self.reach(expr)
				self.locals.redefineLocal(node.lcls[0], expr)

				# Create a merge for exception handling.
				if self.hasExceptionHandling:
					el = self.exceptLocal(node.lcls[0])
					easgn = ast.Assign(expr, el)
					easgn.markMerge()
					return easgn
				else:
					return None


			else:
				renames = [self.locals.writeLocal(lcl) for lcl in node.lcls]
				for rename in renames:
					self.defns[rename] = expr

				asgn = ast.Assign(expr, renames)

				if self.hasExceptionHandling:
					# Create a merge for exception handling.
					output = [asgn]
					for lcl, rename in zip(node.lcls, renames):
						el = self.exceptLocal(lcl)
						easgn = ast.Assign(rename, el)
						easgn.markMerge()
						output.append(easgn)
					asgn = ast.Suite(output)

				return asgn

		elif not node.expr.isPure():
			return ast.Discard(self(node.expr))
		else:
			return None
Beispiel #3
0
    def visitUnpackSequence(self, node):
        # HACK oh so ugly... does not resemble what actually happens.
        if True:
            dc = self.directCall(
                node, self.exports['interpreter_unpack%d' % len(node.targets)],
                None, [self(node.expr)])
            return ast.Assign(dc, node.targets)
        else:
            calls = []

            for i, arg in enumerate(node.targets):
                obj = self.extractor.getObject(i)
                call = self.directCall(
                    None, self.exports['interpreter_getitem'], None,
                    [self(node.expr), self(ast.Existing(obj))])
                calls.append(ast.Assign(call, [arg]))

            return calls
Beispiel #4
0
    def visitAssign(self, node):
        expr = self(node.expr)
        if isinstance(expr, (ast.Local, ast.Existing)):
            if len(node.lcls) == 1:
                # Reach
                self.currentFrame[node.lcls[0]] = expr
                return None

        lcls = [self.clone(lcl, self.currentFrame) for lcl in node.lcls]
        return ast.Assign(expr, lcls)
Beispiel #5
0
 def visitReturn(self, node):
     if self.returnargs is not None:
         # Inlined into assignment
         assert len(self.returnargs) == len(node.exprs)
         return [
             ast.Assign(self(src), [dst])
             for src, dst in zip(node.exprs, self.returnargs)
         ]
     else:
         # Inlined into discard
         return []
Beispiel #6
0
    def methodCallToTypeSwitch(self, node, arg, pos, targets):
        # TODO if mutable types are allowed, we should be looking at the LowLevel type slot?
        # TODO localy rebuild read/modify/allocate information using filtered invokes.
        # TODO should the return value be SSAed?  This might interfere with nessled type switches.
        # If so, retarget the return value and fix up return types

        groups = self.groupTypes(node, arg, pos)
        if groups is None or len(groups) <= 1:
            return None  # Don't create trivial type switches

        cases = []
        for group in groups:
            # Create a filtered version of the argument.
            name = arg.name if isinstance(arg, ast.Local) else None
            expr = ast.Local(name)
            expr.annotation = self.filterReferenceAnnotationByType(
                arg.annotation, group)

            # Create the new op
            opannotation = node.annotation

            # Kill contexts where the filtered expression has no references.
            # (In these contexts, the new op will never be evaluated.)
            mask = self.makeRemapMask(expr.annotation)
            if -1 in mask: opannotation = opannotation.contextSubset(mask)

            # Filter out invocations that don't have the right type for the given parameter.
            opannotation = self.filterOpAnnotationByType(
                opannotation, group, pos)

            # Rewrite the op to use expr instead of the original arg.
            newop = rewrite.rewriteTerm(node, {arg: expr})
            assert newop is not node
            newop.annotation = opannotation

            # Try to reduce it to a direct call
            newop = self(newop)

            # Create the suite for this case
            stmts = []
            if targets is None:
                stmts.append(ast.Discard(newop))
            else:
                # HACK should SSA it?
                stmts.append(ast.Assign(newop, list(targets)))
            suite = ast.Suite(stmts)

            case = ast.TypeSwitchCase([self.existingFromObj(t) for t in group],
                                      expr, suite)
            cases.append(case)

        ts = ast.TypeSwitch(arg, cases)
        return ts
Beispiel #7
0
	def visitUnpackSequence(self, node):
		expr = self(node.expr)
		targets = [self.locals.writeLocal(target) for target in node.targets]
		out = node.reconstruct(expr, targets)

		if self.hasExceptionHandling:
			out = ast.Suite([out])

			for oldtgt, newtgt in zip(node.targets, targets):
				asgn = ast.Assign(newtgt, self.exceptLocal(oldtgt))
				asgn.markMerge()
				out.append(asgn)

		return out
Beispiel #8
0
	def visitAssign(self, node):
		expr = self(node.expr)
		assert not isinstance(expr, ast.Store), "Must discard stores."

		# A little strange, but it works because there will only be one target in the cases we care about.
		for lcl in node.lcls:
			self.defn[lcl] = expr

		if expr not in self.specialGlobals:
			if node.expr == expr:
				return node
			else:
				return ast.Assign(expr, node.lcls)
		else:
			return ()
Beispiel #9
0
	def generateTypeLoad(self, expr, fieldName, refs):
		pt = refs[0].xtype.obj.pythonType()

		for ref in refs[1:]:
			assert ref.xtype.obj.pythonType is pt, "Temporary Limitation"

		ex = self.generateExisting(self.compiler.extractor.getObject(pt))

		name = common.nameForField(self.compiler, fieldName)

		lcl = ast.Local(name)
		lcl.annotation = ex.annotation

		self.statements.append(ast.Assign(ex, [lcl]))

		return lcl
Beispiel #10
0
    def generateReplacements(self, signatures):
        self.newName = {}
        self.replace = {}

        for sig, loads in signatures.iteritems():
            if len(loads) > 1:
                dom = self.dominatorSubtree(loads)

                for op, dominator in dom.iteritems():
                    if op is not dominator:
                        assert not isinstance(op, ast.Store)
                        assert len(op.lcls) == 1

                        src = self.getReplacementSource(dominator)
                        self.replace[op] = ast.Assign(src, [op.lcls[0]])
                        self.eliminated += 1
        return self.replace
Beispiel #11
0
    def generateRewrites(self, code, name, group):
        lcl, ioname = self.remap[name]

        for field in group:
            self.fields[field] = ioname

        isLoaded = False

        for load in self.loadLUT.get((code, name), ()):
            self.rewrites[load] = lcl
            isLoaded = True

        storeCount = 0
        for store in self.storeLUT.get((code, name), ()):
            self.rewrites[store] = ast.Assign(store.value, [lcl])
            storeCount += 1

        if storeCount > 1 or storeCount == 1 and isLoaded:
            self.ssaBroken = True
Beispiel #12
0
    def getReplacementSource(self, dominator):
        if dominator not in self.newName:
            if isinstance(dominator, ast.Store):
                old = dominator.value
            else:
                assert len(dominator.lcls) == 1
                old = dominator.lcls[0]

            if isinstance(old, ast.Existing):
                src = ast.Existing(old.object)
            else:
                src = ast.Local(old.name)
                self.replace[dominator] = [dominator, ast.Assign(old, [src])]

            src.annotation = old.annotation
            self.newName[dominator] = src
        else:
            src = self.newName[dominator]
        return src
Beispiel #13
0
	def visitMerge(self, node):
		if node.phi:
			for i, (prev, prevName) in enumerate(node.iterprev()):
				transfer = [(phi.arguments[i], phi.target) for phi in node.phi if phi.arguments[i] is not None]
				if not transfer:
					continue

				# HACK can't handle pushing assignments up into exceptions?
				assert prevName in ('normal', 'true', 'false', 'entry'), prevName

				transfer, temps = serializeMerges(transfer, self.createTemp)

				stmts = [ast.Assign(src, [dst]) for src, dst in transfer]

				suite = cfg.Suite(prev.region)
				suite.ops = stmts

				prev.insertAtExit(prevName, suite, 'normal')

			node.phi = []
Beispiel #14
0
	def generateLoad(self, expr, fieldName, refs):
		if fieldName.type == 'LowLevel' and fieldName.name.pyobj == 'type':
			# This a kludge until IPA works.
			return self.generateTypeLoad(expr, fieldName, refs)

		fields = []
		for ref in refs:
			fields.append(ref.knownField(fieldName))

		lcl = common.localForFieldSlot(self.compiler, self.code, fields[0], fields)

		exname = self.generateExisting(fieldName.name)
		load = ast.Load(expr, fieldName.type, exname)

		empty = common.emptyAnnotation(self.code)

		load.rewriteAnnotation(allocates=empty, modifies=empty, reads=common.annotationFromValues(self.code, fields))

		self.statements.append(ast.Assign(load, [lcl]))

		return lcl
Beispiel #15
0
	def enterExcept(self, r):
		self.exceptLevel += 1

		rn = {}

		if self.exceptLevel > 1:
			rn.update(self.exceptRename[-1])


		merges = ast.Suite([])

		for lcl in r:
			if not lcl in rn:
				old = self(lcl)
				merge = lcl.clone()
				rn[lcl] = merge
				asgn = ast.Assign(old, merge)
				asgn.markMerge()
				merges.append(asgn)

		self.exceptRename.append(rn)

		return merges
Beispiel #16
0
			switches.append((cond, ast.Suite(body)))

		current = ast.Suite([ast.Assert(ast.Existing(compiler.extractor.getObject(False)), None)])

		for cond, suite in reversed(switches):
			current = ast.Switch(ast.Condition(ast.Suite([]), cond), suite, ast.Suite([current]))

		return [current]

uniformGetTemplate = ast.Assign(
	ast.Call(
		ast.GetAttr(
			ast.GetAttr(
				existingSymbol('cls'),
				existingSymbol('attr')
				),
			existingConstant('__get__')
		),
		[Symbol('root')], [], None, None
	),
	[Symbol('target')]
)

def classAttrFromField(compiler, field):
	assert field.type == 'Attribute', field

	name = field.name.pyobj
	descriptor = compiler.slots.reverse[name]
	cls  = descriptor.__objclass__
	attr = descriptor.__name__
Beispiel #17
0
 def visitAssign(self, node):
     # Modified bottom up
     # Avoids folding assignment targets
     node = ast.Assign(self(node.expr), node.lcls)
     node = self.strategy(node)
     return node