Section two describes about the design and the structure of the COINS compiler driver. Section three is a users manual of the CLI driver. Section four describes about an outline of the driver API.
Hereafter, we call a user of the latter category "operator". When we write "user" without explanation, it doesn't mean the operators.
Operators (and we) must not be willing to follow some ritual procedures to use a compiler. Some of them will try "make CC=newcc", without reading documents. To meet the requirement, a traditionally fashioned CLI driver is provided. This CLI driver has many similarities with the gcc (GNU C compiler) in the command syntax and the basic compile options.
prepared +---------------------+ +---------------------+ +------------+
by users |driver implementation| |driver user interface| |suffix rules|
+---------------------+ +---------------------+ +------------+
+-----------------------------+ +----------------------------+
API | tracer API / warning API | | compile specification API |
+-----------------------------+ +----------------------------+
+------------------------------------------------------------+
| engine |
+------------------------------------------------------------+
Figure 1-1: The structure of the COINS compile driver
Users should prepare the following three parts if needed:
Each API and the engine has following functions:
The class coins.driver.Driver is the driver implementation and the class coins.driver.CommandLine is the driver user interface.
java [java-option ...] coins.driver.Driver [option | filename]...
The command name 'java' may be 'jre' or other command name
according to your Java runtime.
'java-option's are for Java runtime environment, e.g., a -cp option
to use COINS classes. If you deployed the COINS classes at
/usr/local/coins,
java -cp /usr/local/coins coins.driver.Driver [option | filename]
will be enough to load COINS classes to the Java runtime.
-coins:option,option,...
option is a COINS option. Any string not including `,' can be
specified as option.
More than one COINS option can be specified by delimiting
them by `,'s, e.g.
-coins:debug,trace=HIR.8,suffix=/tmp/mysuffixes
is same as
-coins:debug -coins:trace=HIR.8 -coins:suffix=/tmp/mysuffixes
Standard COINS options (which means the options that affects driver API behavior) are as follows:
"-coins:target=arch" is equivalent to
-coins:target=arch-standardand "-coins:target=arch-convention" is equivalent to
-coins:target-arch=arch,target-convention=convention
-coins:target-arch=arch
specifies a target architecture name. arch
must be one of:
-coins:target-convention=convention
specifies a target convention name.
convention can be:
Cygwin users usually need to specify a following option, as well as -b x86-cygwin:
-coins:assembler=as
And, depending on the cygwin installation, there may be a case which requires
following option:
-coins:preprocessor="cpp -I/usr/include"
cf // constant folding
cpf // constant propagation and folding
cse // common subexpression elimination
dce // dead code elimination
fromc // simple optimizations done by C parser
gt // global variable temporalization within basic block
pre // partial redundancy elimination
alias=opt // optimistic alias analysis
loopexp // loop expansion
inlain // inline expansion
See 5.1. How to Use HIR Basic Optimizer for detail.
level
or
category.level
where a level is non-negative integer which
represents a trace level, and the category is a
sequence of letters and digits which represents a
message category. The former form specifies the trace
level of a generic trace message (hereafter, a generic
trace level). A generic trace message is printed only
if its message level is less than or equals to the
generic trace level. The latter form specifies the
trace level of categorized messages whose message
category is category. A trace message whose message
category is category is printed only if its message
level is less than or equals to the trace level. For
example,
-coins:trace=2
prints generic trace messages whose message level is
less than or equals to 2;
-coins:trace=HIR.8
prints trace messages of category `HIR' whose
message level is less than or equals to 8.
When more than one generic trace levels are specified,
or more than one trace levels are specified for a same
category, the latter one overwrites the former one.
For example,
-coins:trace=4/8
prints generic trace messages whose message level is
less than or equals to 8, not 4;
-coins:trace=HIR.6/HIR.3
prints HIR trace messages whose message level is
less than or equals to 3, not 6.
A special category `default' is provided to specify a
trace level of all trace messages other than trace
messages whose trace levels are explicitly specified in
the other tracespecs. For example,
-coins:trace=default.5/HIR.8
prints HIR trace messages whose message level is
less than or equals to 8, and all non-HIR messages
(and generic trace messages) whose message level is
less than or equals to 5.
Note that a large trace level (e.g. 7, 8, 9, etc.) may
produce huge amount of traces.
Examples of available trace categories are:
HIR, LIR, Sym, SSA, TMD.
new ... just after HIR creation,
flo ... just after data flow analysis on HIR has
been done, and
opt ... after all optimizations on HIR.
When more than one timing specifiers are specified,
HIR is translated at all specified timings.
Generated files are named as r-hir-t.c, where `r' is
the file name root of original source file, and `t' is
the timing specifier. For example,
java coins.driver.Driver -coins:hir2c=new foo.c
will produce foo-hir-new.c as the hir2c result.
Invalid timing specifiers are ignored and the
corresponding file is not generated.
new ... just after LIR creation,
opt ... after all optimizations.
When more than one timing specifiers are specified,
LIR is translated at all specified timings.
Generated files are named as r-lir-t.c, where `r' is
the file name root of original source file, and `t' is
the timing specifier. For example,
java coins.driver.Driver -coins:lir2c=new foo.c
will produce foo-lir-new.c as the lir2c result.
Invalid timing specifiers are ignored and the
corresponding file is not generated.
-coins:assembler=as
Blanks appeared in the command name works as a word
delimiter: e.g., following example sets the gcc as the
preprocessor and an option -E is given to it.
-coins:preprocessor=gcc -E
Do not forget to escape the blanks from your command
interpreter, if it treats blanks as a word delimiter,
too. For example, most of Unix shells can escape
blanks using quotations, e.g.,
-coins:preprocessor="gcc -E"
-coins:preprocessor='gcc -E'
'-coins:preprocessor=gcc -E'
Double quotations will work on Windows, too.
A quotation mark (' and ") and a next appearing same
quotation mark are removed from the string and
characters between them are interpreted as follows:
-coins:preprocessor='my cc' -E
In this example, a program 'my cc' is invoked as a
preprocessor with an option '-E'. Do not forget to
escape quotation marks and blanks from your command
interpreter. For example, in Windows, double
quotations will be required as follows:
-coins:preprocessor="'my cc' -E"
Any character following a backslash (`\') is
interpreted as the character itself. A backslash can
be given by a backslash following a backslash. A
quotation mark can be interpreted as itself losing the
special effect described above by following a
backslash. This escape rule can be used to escape a
blank from being interpreted as a word delimiter. For
example, if your environment allows you to include
blanks in file/directory name, you can escape them by
backslashes: e.g.,
-coins:linker=c:\\Program\ Files\\bin_utils\\ld
will set `c:\Program Files\bin_utils\ld' as a linker.
Again, never forget to escape `\'s and blanks from your
command interpreter, if necessary; e.g., in Windows,
-coins:linker="c:\\Program\ Files\\bin_utils\\ld"
Each output file is generated at the directory where its source file exists, unless -o option is specified.
java coins.driver.Driver foo.c
will compile foo.c and generate a.out.
java coins.driver.Driver -o foo foo.c
will compile foo.c and generate foo as an executable binary.
java coins.driver.Driver -c foo.c
will compile foo.c and generate foo.o as an object file.
java coins.driver.Driver -E foo/bar.c baz/boo.c
will preprocess foo/bar.c and baz/boo.c and generate foo/bar.i and
baz/boo.i where `.i' is a suffix meaning `preprocessed C source' in
the default suffix rule.
java coins.driver.Driver -S foo.c bar.i
will compile foo.c and bar.i and generate foo.s and bar.s.Generally speaking, aliasing `java coins.driver.Driver' as `cc', you can use COINS C compiler like an ordinary C compiler except some exceptions; e.g., cc -E will not work as cpp.
The compile specification object must implements an interface
coins.driver.CompileSpecification.
In the CLI driver, the methods main() and go() of class
coins.driver.Driver correspond the driver user interface. They are
described as follows:
protected void go(String[] args) {
CompileSpecification spec = new CommandLine(args);
int status = new CompilerDriver(spec).go(this);
System.exit(status);
}
public static void main(String[] args) {
new Driver().go(args);
}
The class coins.driver.CommandLine is a compile specification class
for the CLI driver. The class coins.driver.CompilerDriver is the
engine. Since the class coins.driver.Driver is a driver
implementation class, it passes an instance of itself as a driver
implementation.If you are to build a compiler driver which has a same user interface as the CLI driver, the above code segment will be reused without change.
In case of the CLI driver, the class coins.driver.Driver is the driver implementation. The CLI driver is providing the above four services. Three of the four, i.e., preprocess, assemble, and link are just call an external program.
A driver implementation, and compiler modules called from it, can use the trace API to put a trace message, specifying a message category and a message level. A message category can be an arbitrary string of letters and digits. A message level must be a non-negative integer.
A trace option is a set of pairs of a trace category and a trace level. The tracer API prints a trace message if its message level is less than or equal to the trace level of the trace category which is a same string with the message category.
To obtain an instance of a Tracer API, which knows trace options specified by an operator, use a method
CompileSpecification#getTrace().
A driver implementation, and compile modules called from it, can use the warning API to put a warning message, specifying a warning category. A warning category can be an arbitrary string of letters and digits.
A warning option is a set of warning categories which should be printed and a set of warning categories which should not be printed. The warning API prints warnings specified to be printed.
To obtain an instance of Warning API which knows warning options specified by an operator, use a method
CompileSpecification#getWarning().
A compiler module can ask the COINS driver API where the library directory is, i.e., use a method CoinsOptions#getLibDir() to an instance of class.driver.CoinsOptions, which can be obtained by a method CompileSpecification#getCoinsOptions(). A COINS user can let an operator to prepare a configuration file at his/her library directory and let a compiler module to read the file using the API.
If a -coins:libdir=path option, which is one of the COINS options, is specified, the driver API returns path as the library directory path name. If not specified, the driver API searches a directory named `coins' at the operators home directory (`user.home' property value returned by the Java runtime) and returns its path name if it is found. If not found, a relative path name which represents a current working directory is returned as the library directory path name.
By default, a file named `properties' in the library directory (see
section 2.4.6) is treated as a property file.
Since some operators may change the property file location, it is
changeable at creating compile specification. Interpretation of the
property file is done at that time by class coins.driver.CoinsOptions.
The property file may be written in arbitrary format which can be read by a method java.utils.Properties#load(). An example follows:
debug:
trace: HIR.8
suffix: /tmp/mysuffixes
This example is exactly same as giving a following COINS option to the
CLI driver.
-coins:debug,trace=HIR.8,suffix=/tmp/mysuffixes
By default, a file named `suffixes' under library directory (see section 4.6) is treated as a suffix database file. If not found, following default is used:
#SRD, 2, Suffix rule DB file, format version 2 c, C, C source, i,s,o c(out-newlir), C, C source, i,lir,- i, C, preprocessed C source, -,s,o cc/cpp/cxx/C, C++, C++ source, ii,s,o ii, C++, preprocessed C++ source, -,s,o java, Java, Java source, -,class,- java(native), Java, Java source (native compile), -,s,o f, FORTRAN, FORTRAN source, -,s,o f(out-newlir), FORTRAN, FORTRAN source, -,lir,o lir, LIR, new LIR, -,s,o S, Assembler, assembly source (need preprocess), s,-,o s, Assembler, assembly source, -,-,oDetail of this file format is described in a JavaDoc document of class coins.driver.SuffixFactory.java. Roughly speaking, it is a sequence of records each of which is in structure of:
suffix, language name, meaning, suffixes after preprocess, compile, and assemble.Since some operators may change the suffix database file location, it is changeable at creating compile specification. Interpretation of the property file is done at that time by class coins.driver.SuffixFactory.
coins.driver.Driver reads settings file by a method java.utils.Process#load() from a library directory if it exists, and stores the contents to a member variable named `defaultSettings'. For coins.driver.Driver, valid properties are: