Previous: Generated code, Up: Backend creation [Contents][Index]
codegen_c_generic.py is a fairly substantial piece of code. It is divided into ten sections:
The NCPTL_CodeGen
class defined
in
codegen_c_generic.py
generates code as follows. The generate
method,
which is invoked by ncptl.py,
calls upon PLY to
process the abstract-syntax tree ( AST) in
postorder fashion. NCPTL_CodeGen
maintains a
stack (
codestack
) on which code
fragments are pushed and popped but that ends up containing a
complete line of C code in each element. For example, in the
coNCePTuaL program ‘TASK 0 OUTPUTS 1+2*3’, the
n_outputs
method will pop ‘[('expr', '(1)+((2)*(3))')]’ (a list
containing the single expression ‘1+2*3’) and
‘('task_expr', '0')’ (a tuple designating a task by
the expression ‘0’) and push multiple lines of code
that prepare task 0 to evaluate and output the
given expression.
The utility functions are the most useful for backend developers to understand, as they are frequently called from hook methods (see Hook methods). The following should be of particular importance:
push
pushmany
Push a single value (typically a string of C code) or each value in a list of values onto a stack.
error_fatal
error_internal
Output a generic error message or an “internal error” error message and abort the program.
code_declare_var
Push (using the
push
method) a line of C code that
declares a variable with an optionally specified type, name,
initial value, and comment. Return the variable name actually
used.
See the definitions in codegen_c_generic.py of each of the above to determine required and optional parameters. The following, adapted from codegen_c_udgram.py demonstrates some of the preceding methods:
def n_for_count_SYNC_ALL(self, localvars): "Synchronize all of the tasks in the job." synccode = [] self.push("{", synccode) loopvar = self.code_declare_var(suffix="task", comment="Loop variable that iterates over all (physical) ranks", stack=synccode) self.pushmany([ "thisev_sync->s.sync.peerqueue = ncptl_queue_init (sizeof(int));", "for (%s=0; %s<var_num_tasks; %s++)" % (loopvar, loopvar, loopvar), "*(int *)ncptl_queue_allocate(thisev_sync->s.sync.peerqueue) = %s;" % loopvar, "thisev_sync->s.sync.syncrank = physrank;", "}"], stack=synccode) return synccode |
That definition of the
n_for_count_SYNC_ALL
hook method defines a new stack
(synccode
) and pushes a ‘{’
onto it. It then declares a loop variable, letting code_declare_var
select a
name but dictating that it end in ‘_task’. The hook
method then pushes some additional C code onto the
synccode
stack and finally returns the stack (which is
really just a list of lines of C code).
Some useful variables defined by
NCPTL_CodeGen
include the following:
base_global_parameters
a list of 6-ary tuples defining extra command-line parameters to parse (format: {type, variable, long_name, short_name, description, default_value})
events_used
a dictionary containing the names of events actually used by the program being compiled
Some methods in codegen_c_generic.py that are worth understanding but are unlikely to be used directly in a derived backend include the following:
pop
Pop a value from a stack.
push_marker
Push a specially designated “marker” value onto a stack.
combine_to_marker
Pop all items off a stack up to the first marker value found;
discard the marker; then, push the popped items as a single list of
items. This is used, for example, by a complex statement (see
Complex
statements) that applies to a list of statements, which can be
popped as a unit using combine_to_marker
.
invoke_hook
Call a hook method, specifying code to be pushed before/after the hook-produced code and alternative text (or Python code) to be pushed (or executed) in the case that a hook method is not provided.
Previous: Generated code, Up: Backend creation [Contents][Index]