def new_context(entity, assembly, render_state, state_key, outfile_name, templates, **kwargs): '''Create a new default context for rendering.''' obj_space = render_state.obj_space cap_space = render_state.cspaces[state_key] if state_key else None addr_space = render_state.addr_spaces[state_key] if state_key else None return dict(list(__builtins__.items()) + ObjectType.__members__.items() + ObjectRights.__members__.items() + list({ # Kernel object allocator 'alloc_obj':( lambda name, type, label=entity.label(), **kwargs: alloc_obj((entity.label(), obj_space), obj_space, '%s_%s' % (entity.label(), name), type, label, **kwargs)) if obj_space else None, # Cap allocator 'alloc_cap':(lambda name, obj, **kwargs: alloc_cap((entity.label(), cap_space), cap_space, name, obj, **kwargs)) \ if cap_space else None, 'Cap': Cap, # The CNode root of your CSpace. Should only be necessary in cases # where you need to allocate a cap to it. 'my_cnode':cap_space.cnode if cap_space is not None else None, # Batched object and cap allocation for when you don't need a reference # to the object. Probably best not to look directly at this one. When # you see `set y = alloc('foo', bar, moo)` in template code, think: # set x = alloc_obj('foo_obj', bar) # set y = alloc_cap('foo_cap', x, moo) 'alloc':(lambda name, type, label=entity.label(), **kwargs: alloc_cap((entity.label(), cap_space), cap_space, name, alloc_obj((entity.label(), obj_space), obj_space, '%s_%s' % (entity.label(), name), type, label, **kwargs), **kwargs)) if cap_space else None, # Functionality for templates to inform us that they've emitted a C # variable that's intended to map to a shared variable. It is # (deliberately) left to the template authors to ensure global names # (gnames) only collide when intended; i.e. when they should map to the # same shared variable. The local name (lname) will later be used by us # to locate the relevant ELF frame(s) to remap. Note that we assume # address spaces and CSpaces are 1-to-1. 'register_shared_variable':None if cap_space is None else \ (lambda global_name, symbol, size, frame_size=None, paddr=None, perm='RWX', cached=None, label=entity.parent.label(): register_shared_variable( addr_space, obj_space, global_name, symbol, size, frame_size, paddr, perm, cached, label)), 'get_shared_variable_backing_frames':None if cap_space is None else \ (lambda global_name, size, frame_size=None, label=entity.parent.label(): get_shared_variable_backing_frames( obj_space, global_name, size, frame_size, label)), # Get the object-label mapping for our verification models. 'object_label_mapping': (lambda: object_label_mapping(obj_space)), # Function for templates to inform us that they would like certain # 'fill' information to get placed into the provided symbol. Provided # symbol should be page size and aligned. The 'fill' parameter is # an arbitrary string that will be set as the 'fill' parameter on the # capDL frame object. The meaning of fill is completely dependent # on the underlying loader 'register_fill_frame':(lambda symbol, fill: register_fill_frame(addr_space, symbol, fill, obj_space, entity.label())), 'register_stack_symbol':(lambda symbol, size: register_stack_symbol(addr_space, symbol, size, obj_space, entity.label())), 'register_ipc_symbol':(lambda symbol, frame: register_ipc_symbol(addr_space, symbol, frame)), 'register_dma_pool':(lambda symbol, page_size, caps: register_dma_pool(addr_space, symbol, page_size, caps, cap_space)), # A `self`-like reference to the current AST object. It would be nice # to actually call this `self` to lead to more pythonic templates, but # `self` inside template blocks refers to the jinja2 parser. 'me':entity, # The AST assembly's configuration. 'configuration':assembly.configuration, # The AST assembly's composition 'composition':assembly.composition, # Cross-template variable passing helpers. These are quite low-level. # Avoid calling them unless necessary. 'stash':partial(stash, entity.label()), 'pop':partial(pop, entity.label()), 'guard':partial(guard, entity.label()), # If the previous group of functions are considered harmful, these are # to be considered completely off limits. These expose a mechanism for # passing data between unrelated templates (_stash and _pop) and a way # of running arbitrary Python statements and expressions. They come # with significant caveats. E.g. _stash and _pop will likely not behave # as expected with the template cache enabled. '_stash':partial(stash, ''), '_pop':partial(pop, ''), 'exec':_exec, # Helpers for creating unique symbols within templates. 'c_symbol':partial(symbol, '_camkes_%(tag)s_%(counter)d'), 'isabelle_symbol':partial(symbol, '%(tag)s%(counter)d\'', 's'), # Expose some library functions 'assert':_assert, 'itertools':itertools, 'functools':functools, 'lambda':lambda s: eval('lambda %s' % s), 'numbers':numbers, 'os':os, 'pdb':pdb, 'raise':_raise, 're':re, 'six':six, 'set':orderedset.OrderedSet, 'textwrap':textwrap, 'copy':copy, 'zip':zip, 'math':math, 'enumerate':enumerate, # Allocation pools. In general, do not touch these in templates, but # interact with them through the alloc* functions. They are only in the # context to allow unanticipated template extensions. 'obj_space':obj_space, 'cap_space':cap_space, # Debugging functions 'breakpoint':_breakpoint, 'sys':sys, # Work around for Jinja's bizarre scoping rules. 'Counter':Counter, # Return a list of distinct elements. Normally you would just do this # as list(set(xs)), but this turns out to be non-deterministic in the # template environment for some reason. 'uniq':lambda xs: reduce(lambda ys, z: ys if z in ys else (ys + [z]), xs, []), # Functional helpers. 'flatMap':lambda f, xs: list(itertools.chain.from_iterable(map(f, xs))), 'flatten':lambda xss: list(itertools.chain.from_iterable(xss)), # Macros for common operations. 'macros':macros, # This function abstracts away the differences between the RT kernel's # seL4_Recv and the master kernel's seL4_Recv. Namely, the RT kernel's # seL4_Recv takes an extra reply object cap. # # seL4_Recv is distinct from seL4_Wait, in that a seL4_Recv() call # expects to potentially get a reply cap from the sender. 'generate_seL4_Recv': generate_seL4_Recv, # This function is similar to generate_seL4_Recv, in that it also # abstracts away the differences between the RT and master kernels. # This function specifically abstracts away the differences between # seL4_SignalRecv (on master) and seL4_NBSendRecv (on RT). 'generate_seL4_SignalRecv': generate_seL4_SignalRecv, # This function is similar to generate_seL4_Recv as well, but it # abstracts away the differences between seL4_ReplyRecv between the # RT and master branches. 'generate_seL4_ReplyRecv': generate_seL4_ReplyRecv, # Give template authors access to AST types just in case. Templates # should never be constructing objects of these types, but they may # need to do `isinstance` testing. 'camkes':collections.namedtuple('camkes', ['ast'])(AST), # Expose CapDL module for `isinstance` testing. 'capdl':capdl, # Give the template authors a mechanism for writing C-style include # guards. Use the following idiom to guard an include target: # /*- if 'template.filename' not in included' -*/ # /*- do included.add('template.filename') -*/ # ... my template ... # /*- endif -*/ 'included':set(), # Expose an exception class templates can use to throw errors related # to invalid input specification. 'TemplateError':TemplateError, # Look up a template 'lookup_template':lambda path, entity: templates.lookup(path, entity), # Output filename (mainly needed by Isabelle templates) # Currently only supported for misc templates. 'outfile_name': outfile_name, }.items()) + list(kwargs.items()))
'precedence10':_lift_numeric_expr, 'precedence11':_lift_precedence11, 'procedure_decl':_lift_procedure_decl, 'procedure_defn':_lift_procedure_defn, 'provides':_lift_provides, 'quoted_string':_collapse, 'reference':_lift_reference, 'semaphore':_lift_semaphore, 'binary_semaphore':_lift_binary_semaphore, 'setting':_lift_setting, 'signed_char':_lift_signed_char, 'signed_int':_lift_signed_int, 'struct_type':_lift_struct_type, 'struct_defn':_lift_struct_defn, 'struct_decl':_lift_struct_decl, 'struct_ref':_lift_struct_ref, 'to':_lift_to, 'type':_lift_type, 'unary_minus':_lift_unary_minus, 'unsigned_char':_lift_unsigned_char, 'unsigned_int':_lift_unsigned_int, 'uses':_lift_uses, } # Sanity checks. assert all(map(re.compile(r'\w+$').match, LIFT)), 'illegal character in ' \ 'LIFT key; all keys should correspond to grammar rule names' assert len(list(DONT_LIFT) + list(LIFT)) == len(set(list(DONT_LIFT) + list(LIFT))), 'conflicting items present in LIFT and DONT_LIFT'
'procedure_decl': _lift_procedure_decl, 'procedure_defn': _lift_procedure_defn, 'provides': _lift_provides, 'quoted_string': _collapse, 'reference': _lift_reference, 'semaphore': _lift_semaphore, 'binary_semaphore': _lift_binary_semaphore, 'setting': _lift_setting, 'signed_char': _lift_signed_char, 'signed_int': _lift_signed_int, 'struct_type': _lift_struct_type, 'struct_defn': _lift_struct_defn, 'struct_decl': _lift_struct_decl, 'struct_ref': _lift_struct_ref, 'to': _lift_to, 'type': _lift_type, 'unary_minus': _lift_unary_minus, 'unsigned_char': _lift_unsigned_char, 'unsigned_int': _lift_unsigned_int, 'uses': _lift_uses, 'query': _lift_query, } # Sanity checks. assert all(map(re.compile(r'\w+$').match, LIFT)), 'illegal character in ' \ 'LIFT key; all keys should correspond to grammar rule names' assert len(list(DONT_LIFT) + list(LIFT)) == len( set(list(DONT_LIFT) + list(LIFT))), 'conflicting items present in LIFT and DONT_LIFT'