<*>= [D->] link pretty procedure emit_encoding(outfilename) local i, f emit_encoding_interface(open(i := outfilename || interface_extension, "w")) | error("Could not open ", image(i), " for writing") emit_encoding_implementation( open(f := outfilename || implementation_extension, "w"), i, outfilename) | error("Could not open ", image(f), " for writing") end
Definesemit_encoding
(links are to index).
<*>+= [<-D->] procedure emit_encoding_interface(outfile) local cons, t, u verbose("Emitting encoding interface") pp := PPnew(outfile) every PPwrite(pp, pretty(!header_lines)) PPwrite(pp, "/* must #include <mclib.h> before this file */") <write definitions of all instance types> if \gen_counters then declare_counter_types(pp) if \indirectname then PPxwrite(pp, "struct ", indirecttype, " {$t") <emit declarations for all of the kept constructors> if \gen_counters then declare_counter_funs(pp) if \indirectname then PPxwrite(pp, "$b$n};") return end
Definesemit_encoding_interface
(links are to index).
<write definitions of all instance types>= (<-U) s := set([instructionctype]) # don't try to emit instance def for untyped constructors every cons := kept_constructors() & not member(s, cons.type) do { insert(s, cons.type) emit_instance_type(pp, cons.type) } s := &null # enable garbage collection
If an indirect encoder is emitted, the order of the constructors has
to match exactly the order used in emit_encoding_interface
.
At one time we rearranged things to put typed constructors first, but
on March 3, 1996, we decided there was no good reason to rearrange the
users' constructor declarations.
<emit declarations for all of the kept constructors>= (<-U) every emit_proc_declaration(pp, kept_constructors())
<*>+= [<-D->] procedure emit_indirect_encoder(pp) e := [] every cons := kept_constructors() do put(e, Cnoreserve(cons.name) || ", $o") c := if \gen_counters then counter_names() else "" emit_template(pp, "proc-structure.t", "indirectname", indirectname, "indirecttype", indirecttype, "encoders", e, "counters", c) return end
Definesemit_indirect_encoder
(links are to index).
<proc-structure.t>= static struct %indirecttype encoding_procs = {$t%encoders%counters$b }; struct %indirecttype *%indirectname = &encoding_procs;
<proc-structure.t (segregated version)>= static struct %indirecttype encoding_procs = {$t%typed%untyped%counters$b }; struct %indirecttype *%indirectname = &encoding_procs;
<emit declarations for all of the kept constructors (segregated version)>= every t | u := [] every cons := kept_constructors() do put(if cons.type === instructionctype then u else t, cons) every emit_proc_declaration(pp, !t | !u)
<*>+= [<-D->]
procedure emit_encoding_implementation(outfile, interfacename, basename)
verbose("Emitting encoding implementation")
pp := PPnew(outfile)
every PPwrite(pp, pretty(!header_lines))
PPwrite(pp, "#include <mclib.h>")
PPwrite(pp, "#include ", image(interfacename))
PPwrite(pp, "#define sign_extend(N,SIZE) \\")
PPwrite(pp, " (((int)((N) << (sizeof(unsigned)*8-(SIZE)))) ",
">> (sizeof(unsigned)*8-(SIZE)))")
pushtrace("ASS")
if \gen_counters then declare_counters(pp)
<write tag definitions for typed kept_constructors
>
every cons := kept_constructors() do {
verbose("Encoder for constructor ", cons.name)
PPwrite(pp, "/**************")
show_constructor(pp, cons)
PPwrite(pp, "***********/")
if cons.type ~=== instructionctype then
emit_create_instance_body(pp, cons)
else
emit_emitter_body(pp, cons)
}
PPwrite(pp) # flush prettyprinter
poptrace()
if \gen_counters then define_counter_funs(pp)
if \indirectname then emit_indirect_encoder(pp)
emit_closure_functions_postfix(pp, basename)
return
end
Definesemit_encoding_implementation
(links are to index).
<write tag definitions for typed kept_constructors
>= (<-U)
every cons := kept_constructors() & cons.type ~=== instructionctype do
PPwrite(pp, "#define ", cons.name, "_TAG ", cons.tag)
<*>+= [<-D->] procedure show_constructor(pp, cons) PPwrite(pp) PPwrites(pp, cons.name, " ") every o := !cons.operands do case type(o) of { "literal" : PPwrites(pp, o.s) "input" : PPwrites(pp, o.name, if type(o.meaning) == "integer" then "!" else "") default : impossible("operand") } PPxwrites(pp, " is $t${$c") PPxwrite(pp, ppexpimage(pattern_to_case(crhs(cons))), "$}$b$n") return end
Definesshow_constructor
(links are to index).
<*>+= [<-D->] procedure show_constype(outfile, type) write(outfile) l := []; every put(l, kept_constructors(type).name) PPwrite(pp, type.name, " (", commaseparate(l, " | "), "):") show_case(outfile, pattern_to_case(constype_pattern(type))) write(outfile) return end
Definesshow_constype
(links are to index).
<*>+= [<-D]
procedure declare_counters(pp)
every PPwrite(pp, "static int ", kept_constructors().name, "_ctr = 0;")
return
end
procedure declare_counter_types(pp)
PPwrite(pp, "typedef void (*Printer)(void *closure, char *fmt, ...);")
return
end
procedure declare_counter_funs(pp)
c_function_declaration(pp, "void", "reset_cons_counters", "(void)")
c_function_declaration(pp, "void", "dump_cons_counters","(Printer p, void *closure)")
return
end
procedure counter_names()
return "reset_cons_counters, dump_cons_counters, $o"
end
procedure define_counter_funs(pp)
PPxwrites(pp, if \indirectname then "static " else "",
"void reset_cons_counters(void) {$t")
every PPxwrites(pp, "$n", kept_constructors().name, "_ctr = 0;")
PPxwrite(pp, "$b$n}")
PPxwrites(pp, if \indirectname then "static " else "",
"void dump_cons_counters(Printer p, void *closure) {$t")
every cons := kept_constructors() do
PPxwrites(pp, "$np(closure, \"%d ", cons.name, " : ", <type of cons
>,
"\\n\", ", cons.name, "_ctr);")
PPxwrite(pp, "$b$n}")
end
Definescounter_names
,declare_counter_funs
,declare_counters
,declare_counter_types
,define_counter_funs
(links are to index).
<type of cons
>= (<-U)
(if cons.type === instructionctype then "<instruction>" else cons.type.name)
<refman: counter functions>= The C procedure \begin{quote} \tt void reset\_cons\_counters(void); \end{quote} resets the counters; the procedure \begin{quote} \tt typedef void (*Printer)(void *closure, char *fmt, ...);\\ void dump\_cons\_counters(Printer p, void *closure); \end{quote} dumps the values of all the counters. The user must provide a function of type {\tt Printer}, a variadic function which accepts a closure, a {\tt printf}-style format, and additional arguments. The closure encapsulates any information needed by the user's printing function. For example, the standard C~function {\tt fprintf} may be used as a {\tt Printer}, in which case a file pointer acts as a closure.
cons
>: U1, D2
kept_constructors
>: U1, D2