Audience: You are expected to be an advanced GCC user (fluent with command-line), and to have successfully downloaded and installed GCC MELT on your computer (probably under GNU/Linux running a recent version -preferably 4.7 or later- of GCC). You have read the tutorial on how to use GCC MELT and then the tutorial on the MELT domain specific language. You may want to have a look at GCC internals documentation (each released version of GCC has its own).
Remember that without any mode given with
the MELT plugin don't do anything
useful. You should choose a name for your mode (which should not
clash with existing mode names given by the help mode
-fplugin-arg-melt-mode=help). Imagine that we
want to implement a mode which counts the functions defined in the
client source code which have a single integer argument. Let's
name this mode count1int.
We need to install a new mode, by creating one instance
class_melt_mode then passing it
install_melt_mode. That instance, which
'count1int_mode contains a
count1int_docmd, doing the
real job. We'll define
below (but it should appear first in
your MELT source code file, before
(definstance count1int_mode class_melt_mode :named_name '"count1int" :meltmode_help '"install a pass counting functions with a single integer argument." :meltmode_fun count1int_docmd ) (install_melt_mode count1int_mode)The string literals should be quoted, since they are values!
count1int_docmd, should usually install one -or several- GCC pass[es] coded in MELT. Of course it could do other mode-specific initialization (e.g. connecting to some database server).
The GCC compiler is running a lot (more
than 200 when optimizing!)
of passes. You'll
want to add your own pass within them. There are several kind of
passes, the simplest being plain gimple passes. A pass has
some name (we suggest to start the name
melt_ to avoid collision with existing passes
names), it also has a optional gate function
deciding if the pass should be run or skipped, and an execute
function doing the actual job.
We obviously need a global counter, as a boxed value:
(define count1int_counter (box 0))
An important issue is to understand where should your own pass be
added. It is difficult to answer. Look into
your GCC compiler source code (you
probably should download the source code of your
compiler, to be able to study it). You could add your pass
after cfg (the control flow graph pass), or phiopt, etc...
Our count1int_docmd function, referenced
is creating and installing a pass, instance
(defun count1int_docmd (cmd moduldata) (let ( (count1intpass (instance class_gcc_gimple_pass :named_name '"melt_count1intpass" :gccpass_exec count1intpass_exec :gccpass_data (make_maptree discr_map_trees 100) )) ) (install_melt_pass_in_gcc count1intpass :after '"cfg" 0) (debug "count1int_mode installed pass=" count1intpass) (return cmd)The MELT pass has a field
;return non-nil to continue compilation))
:gccpass_datato keep some arbitrary data for client convenience. Here it is an hash-map keyed by
:treestuff (we'll use that to avoid processing several times the same C function in the compiled code). Our pass is so simple that we don't need any gate function (but you could give one using the
Our pass is simple, but it has to figure out if it encounters an
already seen C function (because
the GCC compiler is complex enough to be
able to process several times some functions of the input source
code). The current function declaration (as
:tree stuff) is given by
cfun_decl primitive. We use the pass' client data.
(defun count1intpass_exec (pass) (let ( (trmap (get_field :gccpass_data pass)) (curfun (cfun_decl)) ) (match curfun (?(tree_function_decl ?tname ?tres) (if (maptree_get trmap curfun) (return)This is incomplete. We need to figure out if the function has one integer formal argument. We still need to inform the user about the counted number of functions, e.g. by registering a function to be done before exiting using
;;already seen function(let ( (oldcnt (get_int count1int_counter)) ) (maptree_put trmap curfun :true)
;; incomplete: should figure out if the function has one single formal.)) ) (?_
;; not a function, but a variable, a top level asm, ...(return)) ) ))