Previous Up

F  Tools

F.1  The compiler

General options

The Cyclone compiler has the following command-line options:
-help
Print a short description of the command-line options.
-v
Print compilation stages verbosely.
--version
Print version number and exit.
-o file
Set the output file name to file.
-Dname
Define a macro named name for preprocessing.
-Dname=defn
Give macro name the definition defn in preprocessing.
-Bdir
Add dir to the list of directories to search for special compiler files.
-Idir
Add dir to the list of directories to search for include files.
-Ldir
Add dir to the list of directories to search for libraries.
-llib
Link library lib into the final executable.
-c
Produce an object (.o) file instead of an executable; do not link.
-x language
Specify language for the following input files
-s
Remove all symbol table and relocation information from the executable.
-O
Optimize.
-O2
A higher level of optimization.
-O3
Even more optimization.
-p
Compile for profiling with the prof tool.
-pg
Compile for profiling with the gprof tool.
-pa
Compile for profiling with the aprof tool.
-S
Stop after producing assembly code.
-M
Produce dependencies for inclusion in a makefile.
-MG
When producing dependencies assume missing files are generated. Must be used with -M.
-MT file
Make file be the target of any dependencies generated using the -M flag.
-E
Stop after preprocessing.
-nogc
Don't link in the garbage collector.

Developer options

In addition, the compiler has some options that are primarily of use to its developers:
-g
Compile for debugging. This is bulletproof for compiler developers, as the debugging information reflects the C code that the Cyclone code is compiled to, and not the Cyclone code itself. To have a look at Cyclone code during debugging (but not very cleanly as of yet), also pass in --lineno (see below).
-stopafter-parse
Stop after parsing.
-stopafter-tc
Stop after type checking.
-stopafter-toc
Stop after translation to C.
-ic
Activate the link-checker.
-pp
Pretty print.
-up
Ugly print.
-tovc
Avoid gcc extensions in the C output.
-save-temps
Don't delete temporary files.
-save-c
Don't delete temporary C files.
--lineno
Insert #line directives in generated C code. This slows down compilation, but helps debugging. Works best when also using -pp.
--nochecks
Disable all null and array bounds checks (still uses ``fat'' representation of ? pointers).
--nonullchecks
Disable null checks.
--noboundschecks
Disable array bounds checks (still uses ``fat'' representation of ? pointers).
-use-cpppath
Indicate which preprocessor to use.
-no-cpp-precomp
Disable smart preprocessing (mac only).
-nocyc
Don't add the implicit namespace Cyc to variable names in the C output.
-noremoveunused
Don't remove externed variables that aren't used.
-noexpandtypedefs
Don't expand typedefs in pretty printing.
-printalltvars
Print all type variables (even implicit default effects).
-printallkinds
Always print kinds of type variables.
-printfullevars
Print full information for evars (type debugging).

F.2  The lexer generator

F.3  The parser generator

F.4  The allocation profiler, aprof

To get a profile of the allocation behavior of a Cyclone program, follow these steps:
  1. Compile the program with the flag -pa. The resulting executable will be compiled to record allocation behavior. It will also be linked with a version of the standard library that records its allocation behavior. (If you get the message, ``can't find internal compiler file libcyc_a.a,'' then ask your system administrator to install the special version of the library.)
  2. Execute the program as normal. As it executes, it will write to a file amon.out in the current working directory; if the file exists before execution, it will be overwritten.
  3. Run the program aprof. This will examine amon.out and print a report on the allocation behavior of the program.

F.5  The C interface tool, buildlib

buildlib is a tool that semi-automatically constructs a Cyclone interface to C code. It scans C header files and builds Cyclone header files and stub code so that Cyclone programs can call the C code. We use it to build the Cyclone interface to the C standard library (in much the same way that gcc uses the fixincludes program).

To use buildlib, you must construct a spec file that tells it what C headers to scan, and what functions and constants to extract from the headers. By convention, the names of spec files end in .cys. If spec.cys is a spec file, then buildlib is invoked by
  buildlib spec.cys
The output of buildlib is placed in a directory, BUILDLIB.OUT. The output consists of Cyclone header files and the stub files cstubs.c and cycstubs.cyc.

Spec files

The form of a spec file is given by the following grammar.
spec-file:
(empty)
spec spec-file
spec:
header-name : directives ;
directives:
(empty)
directive directives
directive:
cpp { balanced-braces }
include { ids }
hstub idopt{ balanced-braces }
cycstub idopt{ balanced-braces }
cstub idopt{ balanced-braces }
ids:
(empty)
id balanced-braces* ids
The non-terminal id refers to C identifiers, and header-name ranges over C header names (e.g., stdio.h, sys/types.h). We use balanced-braces to refer to any sequence of C tokens with balanced braces, ignoring braces inside of comments, strings, and character constants.

Directives

include
The include directive is used to extract constants and type definitions from C header files and put them into the equivalent Cyclone header file. For example, here is part of the spec that we use to interface to C's errno.h:
  errno.h:
  include { E2BIG EACCES EADDRINUSE ... }
The spec says that the Cyclone version of errno.h should use the C definitions of error constants like E2BIG. These are typically macro-defined as integers, but the integers can differ from system to system. We ensure that Cyclone uses the right constants by running buildlib on each system.

For another example, our spec for sys/types.h reads, in part:
  sys/types.h:
  include { id_t mode_t off_t pid_t ... }
Here the symbols are typedef names, and the result will be that the Cyclone header file contains the typedefs that define id_t, etc. Again, these can differ from system to system.

You can use include to obtain not just constants (macros) and typedefs, but struct and union definitions as well. Furthermore, if a definition you include requires any other definitions that you do not explicitly include, those other definitions will be placed into the Cyclone header too. Moreover, for all such definitions, you can include an optional, expected Cyclonedefinition that is ``equivalent'' to the C definition on your system. By ``equivalent,'' we mean that your definition defines all of the same elements as the system definition (but possibly fewer), and each of these elements is ``representation-compatible'' in the sense that they use the same amount of storage when compiled. As example, here is our spec for grp.h:
include {
  gid_t
  group {
    struct group {
      char @gr_name;
      char @gr_passwd;
      gid_t gr_gid;
      char ** @zeroterm gr_mem;
    };  
  }
}
This provides richer information than the compatible definition on most systems. Here is the Linux definition:
struct group {
  char *gr_name;
  char *gr_passwd;
  gid_t gr_gid;
  char **gr_mem;
};  
The user definition refines the system definition by indicating that for group strings gr_name and gr_passwd must be non-NULL, and indicates that the array of strings gr_mem, is null-terminated. But note that the two definitions are representation-compatible in that they have the same run-time storage requirements. The Cyclone version simplifies provides more precise type information. You can provide user definitions for enumerated types and typedef's as well.

Some refinements (such as polymorphism), are not yet supported for user definitions. Also, include does not work for variable or function declarations. You have to use the hstub directive to add variable and function declarations to your Cyclone header.

cstub
The cstub directive adds code (the balanced-braces) to the C stub file. If an optional id is used, then the code will be added to the stub file only if the id is declared by the C header. This is useful because every system defines a different subset of the C standard library.

cycstub
The cycstub directive is like the cstub directive, except that the code is added to the Cyclone stub file.

hstub
The hstub directive is like the cstub directive, except that the code is added to the Cyclone header file.

cpp
The cpp directive is used to tell buildlib to scan some extra header files before scanning the header file of the spec. This is useful when a header file can't be parsed in isolation. For example, the standard C header sys/resource.h is supposed to define struct timeval, but on some systems, this is defined in sys/types.h, which must be included before sys/resource.h for that file to parse. This can be handled with a spec like the following:
  sys/resource.h:
  cpp {
    #include <sys/types.h>
  }
  ...
This will cause sys/types.h to be scanned by buildlib before sys/resource.h.

You can also use the cpp directive to directly specify anything that might appear in a C include file (e.g., macros).

Options

buildlib has the following options.
-d directory
Use directory as the output directory instead of the default BUILDLIB.OUT.

-gather and -finish
buildlib works in two phases. In the gather phase, buildlib grabs the C headers listed in the spec file from their normal locations in the C include tree, and stores them in a special format in the output directory. In the finish phase, buildlib uses the specially formatted C headers to build the Cyclone headers and stub files. The -gather flag tells buildlib to perform just the gather phase, and the -finish flag tells it to perform just the finish phase.

buildlib's two-phase strategy is intended to support cross compilation. A Cyclone compiler on one architecture can compile to a second architecture provided it has the other architecture's Cyclone header files. These headers can be generated on the first architecture from the output of the gather phase on the second architecture. This is more general than just having the second architecture's Cyclone headers, because it permits works even in the face of some changes in the spec file or buildlib itself (which would change the other architecture's Cyclone headers).

-gatherscript
The -gatherscript flag tells buildlib to output a shell script that, when executed, performs buildlib's gather phase. This is useful when porting Cyclone to an unsupported architecture, where buildlib itself does not yet work. The script can be executed on the unsupported architecture, and the result can be moved to a supported architecture, which can then cross-compile itself to the new architecture.

Previous Up