示例#1
0
def bindStreams(compiler, translator, context):
	code = symbols.SymbolRewriter(compiler.extractor, streamCodeTemplate)
	bind = symbols.SymbolRewriter(compiler.extractor, streamBindTemplate)

	originalParams = context.originalParams
	currentParams = context.code.codeparameters

	self   = ast.Local('self')
	streams   = []

	statements = []

	for original in originalParams.params[2:]:
		root = ast.Local(original.name)
		streams.append(root)

		ioname = context.shaderdesc.fields[original]
		if ioname in translator.liveInputs:

			refs = original.annotation.references.merged
			assert len(refs) == 1
			obj = refs[0]
			assert intrinsics.isIntrinsicObject(obj)
			t = obj.xtype.obj.pythonType()
			attr = "bind_stream_" + t.__name__

			structInfo = translator.ioRefInfo.get(ioname)

			shaderName = structInfo.lut.subpools[t].name

			statements.append(bind.rewrite(self=self, attr=attr, shaderName=shaderName, name=root))

#	for original, current in zip(originalParams.params, currentParams.params)[2:]:
#		root = ast.Local(original.name)
#		streams.append(root)
#
#		if current.isDoNotCare(): continue
#
#		refs = current.annotation.references.merged
#		assert len(refs) == 1
#		obj = refs[0]
#		assert intrinsics.isIntrinsicObject(obj)
#		t = obj.xtype.obj.pythonType()
#		attr = "bind_stream_" + t.__name__
#
#		structInfo = translator.serializationInfo(current)
#		assert structInfo is not None
#
#		shaderName = structInfo.intrinsics[t].decl.name
#
#		statements.append(bind.rewrite(self=self, attr=attr, shaderName=shaderName, name=root))

	body = ast.Suite(statements)

	args = [self]
	args.extend(streams)
	names = [arg.name for arg in args]

	return code.rewrite(args=args, argnames=names, body=body)
示例#2
0
def bindUniforms(compiler, translator, uniformSlot):
	code = symbols.SymbolRewriter(compiler.extractor, uniformCodeTemplate)

	self   = ast.Local('self')
	shader = ast.Local('shader')

	if uniformSlot.annotation.references:
		uniformRefs = uniformSlot.annotation.references.merged
		body = ast.Suite(serializeUniformNode(compiler, translator, self, uniformSlot, uniformRefs, shader))
	else:
		# No uniforms are used.
		body = ast.Suite([])

	return code.rewrite(args=[self, shader], body=body)
示例#3
0
 def makeExternalSlot(self, name):
     code = self.externalFunction
     context = self.externalFunctionContext
     dummyLocal = ast.Local(name)
     dummyName = self.canonical.localName(code, dummyLocal, context)
     dummySlot = self.storeGraph.root(dummyName)
     return dummySlot
示例#4
0
def createLocalNode(hyperblock, name, values):
    lcl = ast.Local(name)
    node = graph.LocalNode(hyperblock, (lcl, ))
    annotation = annotations.DataflowSlotAnnotation(values, True)
    node.annotation = annotation

    return node
示例#5
0
 def upwardSlots(self, slot):
     if slot not in self.slotReverse:
         self.slotReverse[slot].append(
             self.src.local(ast.Local('summaryTemp')))
     result = self.slotReverse[slot]
     assert result
     return result
示例#6
0
	def process(self, node, vparamLen):
		# TODO rewrite local references.

		p = node.codeparameters

		self.code   = node
		self.vparam = p.vparam

		self.newParams = [ast.Local(None) for i in range(vparamLen)]
		self.newNames  = [None for i in range(vparamLen)]

		if vparamLen > 0:
			# Defaults are never used
			defaults = ()
		else:
			# Number of arguments unchanged, defaults may be used, do nothing
			defaults = p.defaults

		for i, lcl in enumerate(self.newParams):
			field = self.storeGraph.canonical.fieldName('Array', self.storeGraph.extractor.getObject(i))
			self.transferReferences(self.vparam, field, lcl)

		selfparam = p.selfparam
		parameters = self.extend(p.params, self.newParams)
		parameternames = self.extend(p.paramnames, self.newNames)
		vparam = None
		kparam = p.kparam
		returnparams = p.returnparams

		node.codeparameters = ast.CodeParameters(selfparam, parameters, parameternames, defaults, vparam, kparam, returnparams)
		node.ast = self(node.ast)
示例#7
0
    def __init__(self, compiler, graph, opPathLength, clone):
        self.decompileTime = 0
        self.console = compiler.console
        self.extractor = compiler.extractor
        self.clone = clone  # Should we copy the code before annotating it?

        # Has the context been constructed?
        self.liveContexts = set()

        self.liveCode = set()

        # Constraint information, for debugging
        self.constraints = []

        # The worklist
        self.dirty = collections.deque()

        self.canonical = graph.canonical
        self._canonicalContext = util.canonical.CanonicalCache(
            base.AnalysisContext)

        # Controls how many previous ops are remembered by a context.
        # TODO remember prior CPA signatures?
        self.opPathLength = opPathLength
        self.cache = {}

        # Information for contextual operations.
        self.opAllocates = collections.defaultdict(set)
        self.opReads = collections.defaultdict(set)
        self.opModifies = collections.defaultdict(set)
        self.opInvokes = collections.defaultdict(set)

        self.codeContexts = collections.defaultdict(set)

        self.storeGraph = graph

        # Setup the "external" context, used for creaing bogus slots.
        self.externalOp = util.canonical.Sentinel('<externalOp>')

        self.externalFunction = ast.Code(
            'external',
            ast.CodeParameters(None, [], [], [], None, None,
                               [ast.Local('internal_return')]), ast.Suite([]))
        externalSignature = self._signature(self.externalFunction, None, ())
        opPath = self.initialOpPath()
        self.externalFunctionContext = self._canonicalContext(
            externalSignature, opPath, self.storeGraph)
        self.codeContexts[self.externalFunction].add(
            self.externalFunctionContext)

        # For vargs
        self.tupleClass = self.extractor.getObject(tuple)
        self.ensureLoaded(self.tupleClass)

        # For kargs
        self.dictionaryClass = self.extractor.getObject(dict)
        self.ensureLoaded(self.dictionaryClass)

        self.entryPointOp = {}
示例#8
0
def buildTempLocal(analysis, objs):
    if objs is None:
        return None
    else:
        lcl = analysis.root.local(ast.Local('entry_point_arg'))
        objs = frozenset([analysis.objectName(xtype) for xtype in objs])
        lcl.updateValues(objs)
        return lcl
示例#9
0
 def translateLocal(self, node):
     if not node in self.localMap:
         lcl = ast.Local(node.name)
         self.localMap[node] = lcl
         self.transferLocal(node, lcl)
     else:
         lcl = self.localMap[node]
     return lcl
示例#10
0
	def setNumReturns(self, num):
		if self.numReturns is None:
			self.numReturns = num

			p = self.code.codeparameters
			if num != len(p.returnparams):
				returnparams = [ast.Local('internal_return_%d' % i) for i in range(num)]
				self.code.codeparameters = ast.CodeParameters(p.selfparam, p.params, p.paramnames, p.defaults, p.vparam, p.kparam, returnparams)

		else:
			assert num == self.numReturns
示例#11
0
文件: fold.py 项目: winex/pystream
    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
示例#12
0
def handleUniformType(compiler, translator, self, holdingSlot, ref, root, t):
	statements = []

	# Find the group name
	holdingSlot = translator.compatible[holdingSlot]

	structInfo = translator.ioRefInfo.get(holdingSlot)

	if structInfo:
		if structInfo.multipleTypes():
			sub = structInfo.lut.subpools['type']
			name = sub.name
			uid  = translator.typeIDs[t]
			uidO = compiler.extractor.getObject(uid)

			statements.append(bindUniform(compiler, self, name, int, ast.Existing(uidO)))

		if intrinsics.isIntrinsicType(t):
			if t in intrinsics.samplerTypes:
				sg = translator.samplerGroup(ref)
				assert sg.unique
				name = sg.name
			else:
				sub = structInfo.lut.subpools[t]
				name = sub.name
			statements.append(bindUniform(compiler, self, name, t, root))

		# TODO fields?

	get = symbols.SymbolRewriter(compiler.extractor, uniformGetTemplate)

	# TODO mutually exclusive?

	for field in ref.slots.itervalues():
		if not intrinsics.isIntrinsicSlot(field):
			if field.slotName.type != 'Attribute': continue

			cls, attr = classAttrFromField(compiler, field.slotName)

			assert issubclass(t, cls), (ref, field)

			target  = ast.Local('bogus')

			# Load the field
			assign = get.rewrite(cls=cls, attr=attr, root=root, target=target)
			statements.append(assign)

			# Recurse
			statements.extend(serializeUniformNode(compiler, translator, self, field, field, target))

	return statements
示例#13
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
示例#14
0
	def visitAssign(self, node):
		if isinstance(node.expr, ast.BinaryOp) and node.expr.op in opnames.inplaceOps:
			assert len(node.lcls) == 1
			target = node.lcls[0]

			#assert not node.lcl in self.collapsable
			# Workarround for synthesizing inplace BinaryOps that don't put their result into the left argument.
			# If the operation actually is inplace, don't hack it.

			temp = node.expr.right
			if target != node.expr.left:
				if target == node.expr.right:
					# Take care of the case Assign(a, BinaryOp(b, inplace, a))
					# Otherwise the subsequent statement cobbers the right value.
					temp = ast.Local(None)
					stmt = "%s = %s" % (self.seg.process(temp), self.seg.process(node.expr.right))
					self.emitStatement(stmt)

				stmt = "%s = %s" % (self.seg.process(target), self.seg.process(node.expr.left))
				self.emitStatement(stmt)

			stmt = "%s %s %s" % (self.seg.process(target), node.expr.op, self.seg.process(temp))
			self.emitStatement(stmt)
		elif isinstance(node.expr, ast.MakeFunction):
			assert len(node.lcls) == 1
			# HACK to rename the function
			self(node.expr)
			name = node.expr.code.name
			lcl = self.seg.process(node.lcls[0])
			if name != lcl:
				self.emitStatement("%s = %s" % (lcl, name))
		elif isinstance(node.expr, ast.Existing) and node.expr.object.isConstant() and isinstance(node.expr.object.pyobj, types.CodeType):
			# HACK
			pass
##		elif isinstance(node.expr, (ast.ShortCircutAnd, ast.ShortCircutOr)):
##			expr, p = self(node.expr)
##
##			stmt = "%s = %s" % (self.seg.process(node.lcl), expr)
##			self.emitStatement(stmt)
		else:
			if len(node.lcls) == 1 and node.lcls[0] in self.collapsable and self.supressStatements:
			#if node.lcl in self.collapsable:
				self.seg.processCollapsed(node.lcls[0], node.expr)
			else:
				stmt = "%s = %s" % (', '.join([self.seg.process(lcl) for lcl in node.lcls]), self.seg.process(node.expr))

				self.emitStatement(stmt)
示例#15
0
	def makeLocalForGroup(self, group):
		# Make up a name, based on an arbitrary field
		field = group[0].slotName
		name = field.name.pyobj

		if field.type == 'Attribute':
			descriptor = self.compiler.slots.reverse[name]
			originalName = descriptor.__name__
		elif field.type == 'Array':
			originalName = 'array_%d' % name
		elif field.type == 'LowLevel':
			originalName = name

		else:
			assert False, field

		return ast.Local(originalName)
示例#16
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
示例#17
0
 def existingTemp(self, obj):
     lcl = self.context.local(ast.Local('existing_temp'))
     lcl.updateSingleValue(obj)
     return lcl
示例#18
0
 def makeTarget(self, context):
     lcl = context.local(ast.Local(self.localName()))
     lcl.addPrev(self)
     self.dst.append(lcl)
     return lcl
示例#19
0
 def makeLocalObjs(self, name):
     lcl = ast.Local(name)
     slot = self.sys.canonical.localSlot(lcl)
     expr = self.sys.canonical.localExpr(slot)
     return lcl, slot, expr
示例#20
0
	body = ast.Suite(statements)

	args = [self]
	args.extend(streams)
	names = [arg.name for arg in args]

	return code.rewrite(args=args, argnames=names, body=body)

classTemplate = ast.ClassDef(
	symbols.Symbol('className'),
	[ast.GetAttr(
		ast.GetGlobal(existingConstant('pystreamruntime')),
		existingConstant('BaseCompiledShader')
	)],
	ast.Suite([
		ast.Assign(existingSymbol('original'), [ast.Local('original')]),
		ast.Assign(existingSymbol('vsCode'), [ast.Local('vs')]),
		ast.Assign(existingSymbol('fsCode'), [ast.Local('fs')]),
		ast.FunctionDef('_bindUniforms', symbols.Symbol('bindUniforms'), []),
		ast.FunctionDef('bindStreams',  symbols.Symbol('bindStreams'), [])
	]),
	[]
)


callback = ast.Local('callback')
# Not a FunctionDef, as the symbol rewriter would not be able to reach through the (shared) code
registerTemplate = ast.Code(
	'register',
	ast.CodeParameters(
		None,