Exemple #1
0
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()))
Exemple #2
0
    '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'
Exemple #3
0
    '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'
Exemple #4
0
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()))