Previous: Generated code, Up: Backend creation
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
error_fatal
error_internal
code_declare_var
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
events_used
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
push_marker
combine_to_marker
combine_to_marker
.invoke_hook