module Cil:CIL API Documentation. An html version of this document can be found at http://hal.cs.berkeley.edu/cilsig
..end
val initCIL : unit -> unit
Cil.msvcMode
.val cilVersion : string
val cilVersionMajor : int
val cilVersionMinor : int
val cilVersionRevision : int
Frontc.parse: string -> unit ->
Cil.file
. This function must be given
the name of a preprocessed C file and will return the top-level data
structure that describes a whole source file. By default the parsing and
elaboration into CIL is done as for GCC source. If you want to use MSVC
source you must set the Cil.msvcMode
to true
and must also invoke the
function Frontc.setMSVCMode: unit -> unit
.Cil.file
using the following iterators: Cil.mapGlobals
,
Cil.iterGlobals
and Cil.foldGlobals
. You can also use the
Cil.dummyFile
when you need a Cil.file
as a placeholder. For each
global item CIL stores the source location where it appears (using the
type Cil.location
)type
file = {
|
mutable fileName : |
(* | The complete file name | *) |
|
mutable globals : |
(* | List of globals as they will appear in the printed file | *) |
|
mutable globinit : |
(* | An optional global initializer function. This is a function where
you can put stuff that must be executed before the program is
started. This function is conceptually at the end of the file,
although it is not part of the globals list. Use Cil.getGlobInit
to create/get one. | *) |
|
mutable globinitcalled : |
(* | Whether the global initialization function is called in main. This should always be false if there is no global initializer. When you create a global initialization CIL will try to insert code in main to call it. This will not happen if your file does not contain a function called "main" | *) |
typecomment =
location * string
type
global =
| |
GType of |
(* | A typedef. All uses of type names (through the TNamed constructor)
must be preceded in the file by a definition of the name. The string
is the defined name and always not-empty. | *) |
| |
GCompTag of |
(* | Defines a struct/union tag with some fields. There must be one of
these for each struct/union tag that you use (through the TComp
constructor) since this is the only context in which the fields are
printed. Consequently nested structure tag definitions must be
broken into individual definitions with the innermost structure
defined first. | *) |
| |
GCompTagDecl of |
(* | Declares a struct/union tag. Use as a forward declaration. This is printed without the fields. | *) |
| |
GEnumTag of |
(* | Declares an enumeration tag with some fields. There must be one of
these for each enumeration tag that you use (through the TEnum
constructor) since this is the only context in which the items are
printed. | *) |
| |
GEnumTagDecl of |
(* | Declares an enumeration tag. Use as a forward declaration. This is printed without the items. | *) |
| |
GVarDecl of |
(* | A variable declaration (not a definition). If the variable has a function type then this is a prototype. There can be several declarations and at most one definition for a given variable. If both forms appear then they must share the same varinfo structure. A prototype shares the varinfo with the fundec of the definition. Either has storage Extern or there must be a definition in this file | *) |
| |
GVar of |
(* | A variable definition. Can have an initializer. The initializer is updateable so that you can change it without requiring to recreate the list of globals. There can be at most one definition for a variable in an entire program. Cannot have storage Extern or function type. | *) |
| |
GFun of |
(* | A function definition. | *) |
| |
GAsm of |
(* | Global asm statement. These ones can contain only a template | *) |
| |
GPragma of |
(* | Pragmas at top level. Use the same syntax as attributes | *) |
| |
GText of |
(* | Some text (printed verbatim) at top level. E.g., this way you can put comments in the output. | *) |
Cil.typ
.
Among types we differentiate the integral types (with different kinds
denoting the sign and precision), floating point types, enumeration types,
array and pointer types, and function types. Every type is associated with
a list of attributes, which are always kept in sorted order. Use
Cil.addAttribute
and Cil.addAttributes
to construct list of
attributes. If you want to inspect a type, you should use
Cil.unrollType
or Cil.unrollTypeDeep
to see through the uses of
named types.Cil.bitsSizeOf
, the alignment of a type
(in bytes) Cil.alignOf_int
, and can convert an offset into a start and
width (both in bits) using the function Cil.bitsOffset
. At the moment
these functions do not take into account the packed
attributes and
pragmas.type
typ =
| |
TVoid of |
(* | Void type. Also predefined as Cil.voidType | *) |
| |
TInt of |
(* | An integer type. The kind specifies the sign and width. Several
useful variants are predefined as Cil.intType , Cil.uintType ,
Cil.longType , Cil.charType . | *) |
| |
TFloat of |
(* | A floating-point type. The kind specifies the precision. You can
also use the predefined constant Cil.doubleType . | *) |
| |
TPtr of |
(* | Pointer type. Several useful variants are predefined as
Cil.charPtrType , Cil.charConstPtrType (pointer to a
constant character), Cil.voidPtrType ,
Cil.intPtrType | *) |
| |
TArray of |
(* | Array type. It indicates the base type and the array length. | *) |
| |
TFun of |
(* | Function type. Indicates the type of the result, the name, type
and name attributes of the formal arguments (None if no
arguments were specified, as in a function whose definition or
prototype we have not seen; Some [] means void). Use
Cil.argsToList to obtain a list of arguments. The boolean
indicates if it is a variable-argument function. If this is the
type of a varinfo for which we have a function declaration then
the information for the formals must match that in the
function's sformals. Use Cil.setFormals , or
Cil.setFunctionType , or Cil.makeFormalVar for this
purpose. | *) |
| |
TNamed of |
(* | The use of a named type. Each such type name must be preceded
in the file by a GType global. This is printed as just the
type name. The actual referred type is not printed here and is
carried only to simplify processing. To see through a sequence
of named type references, use Cil.unrollType or
Cil.unrollTypeDeep . The attributes are in addition to those
given when the type name was defined. | *) |
| |
TComp of |
(* | The most delicate issue for C types is that recursion that is possible by
using structures and pointers. To address this issue we have a more
complex representation for structured types (struct and union). Each such
type is represented using the Cil.compinfo type. For each composite
type the Cil.compinfo structure must be declared at top level using
GCompTag and all references to it must share the same copy of the
structure. The attributes given are those pertaining to this use of the
type and are in addition to the attributes that were given at the
definition of the type and which are stored in the Cil.compinfo . | *) |
| |
TEnum of |
(* | A reference to an enumeration type. All such references must
share the enuminfo among them and with a GEnumTag global that
precedes all uses. The attributes refer to this use of the
enumeration and are in addition to the attributes of the
enumeration itself, which are stored inside the enuminfo | *) |
| |
TBuiltin_va_list of |
(* | This is the same as the gcc's type with the same name | *) |
Cil.isIntegralType
,
Cil.isArithmeticType
,
Cil.isPointerType
,
Cil.isFunctionType
,
Cil.isArrayType
.
There are two easy ways to scan a type. First, you can use the
Cil.existsType
to return a boolean answer about a type. This function
is controlled by a user-provided function that is queried for each type that is
used to construct the current type. The function can specify whether to
terminate the scan with a boolean result or to continue the scan for the
nested types.
The other method for scanning types is provided by the visitor interface (see
Cil.cilVisitor
).
If you want to compare types (or to use them as hash-values) then you should
use instead type signatures (represented as Cil.typsig
). These
contain the same information as types but canonicalized such that simple Ocaml
structural equality will tell whether two types are equal. Use
Cil.typeSig
to compute the signature of a type. If you want to ignore
certain type attributes then use Cil.typeSigWithAttrs
.
type
ikind =
| |
IChar |
(* | char | *) |
| |
ISChar |
(* | signed char | *) |
| |
IUChar |
(* | unsigned char | *) |
| |
IBool |
(* | _Bool (C99) | *) |
| |
IInt |
(* | int | *) |
| |
IUInt |
(* | unsigned int | *) |
| |
IShort |
(* | short | *) |
| |
IUShort |
(* | unsigned short | *) |
| |
ILong |
(* | long | *) |
| |
IULong |
(* | unsigned long | *) |
| |
ILongLong |
(* | long long (or _int64 on Microsoft Visual C) | *) |
| |
IULongLong |
(* | unsigned long long (or unsigned _int64 on Microsoft
Visual C) | *) |
type
fkind =
| |
FFloat |
(* | float | *) |
| |
FDouble |
(* | double | *) |
| |
FLongDouble |
(* | long double | *) |
type
attribute =
| |
Attr of |
(* | An attribute has a name and some optional parameters. The name should not start or end with underscore. When CIL parses attribute names it will strip leading and ending underscores (to ensure that the multitude of GCC attributes such as const, __const and __const__ all mean the same thing.) | *) |
typeattributes =
attribute list
Cil.addAttribute
and Cil.addAttributes
to insert attributes in an
attribute list and maintain the sortedness.type
attrparam =
| |
AInt of |
(* | An integer constant | *) |
| |
AStr of |
(* | A string constant | *) |
| |
ACons of |
(* | Constructed attributes. These
are printed foo(a1,a2,...,an) .
The list of parameters can be
empty and in that case the
parentheses are not printed. | *) |
| |
ASizeOf of |
(* | A way to talk about types | *) |
| |
ASizeOfE of |
|||
| |
ASizeOfS of |
(* | Replacement for ASizeOf in type signatures. Only used for attributes inside typsigs. | *) |
| |
AAlignOf of |
|||
| |
AAlignOfE of |
|||
| |
AAlignOfS of |
|||
| |
AUnOp of |
|||
| |
ABinOp of |
|||
| |
ADot of |
(* | a.foo * | *) |
| |
AStar of |
(* | a | *) |
| |
AAddrOf of |
(* | & a * | *) |
| |
AIndex of |
(* | a1a2 | *) |
| |
AQuestion of |
(* | a1 ? a2 : a3 * | *) |
Cil.compinfo
describes the definition of a
structure or union type. Each such Cil.compinfo
must be defined at the
top-level using the GCompTag
constructor and must be shared by all
references to this type (using either the TComp
type constructor or from
the definition of the fields.
If all you need is to scan the definition of each
composite type once, you can do that by scanning all top-level GCompTag
.
Constructing a Cil.compinfo
can be tricky since it must contain fields
that might refer to the host Cil.compinfo
and furthermore the type of
the field might need to refer to the Cil.compinfo
for recursive types.
Use the Cil.mkCompInfo
function to create a Cil.compinfo
. You can
easily fetch the Cil.fieldinfo
for a given field in a structure with
Cil.getCompField
.
type
compinfo = {
|
mutable cstruct : |
(* | True if struct, False if union | *) |
|
mutable cname : |
(* | The name. Always non-empty. Use Cil.compFullName to get the full
name of a comp (along with the struct or union) | *) |
|
mutable ckey : |
(* | A unique integer. This is assigned by Cil.mkCompInfo using a
global variable in the Cil module. Thus two identical structs in two
different files might have different keys. Use Cil.copyCompInfo to
copy structures so that a new key is assigned. | *) |
|
mutable cfields : |
(* | Information about the fields. Notice that each fieldinfo has a pointer back to the host compinfo. This means that you should not share fieldinfo's between two compinfo's | *) |
|
mutable cattr : |
(* | The attributes that are defined at the same time as the composite
type. These attributes can be supplemented individually at each
reference to this compinfo using the TComp type constructor. | *) |
|
mutable cdefined : |
(* | This boolean flag can be used to distinguish between structures that have not been defined and those that have been defined but have no fields (such things are allowed in gcc). | *) |
|
mutable creferenced : |
(* | True if used. Initially set to false. | *) |
Cil.mkCompInfo
to
make one and use Cil.copyCompInfo
to copy one (this ensures that a new
key is assigned and that the fields have the right pointers to parents.).Cil.fieldinfo
structure is used to describe
a structure or union field. Fields, just like variables, can have
attributes associated with the field itself or associated with the type of
the field (stored along with the type of the field).type
fieldinfo = {
|
mutable fcomp : |
(* | The host structure that contains this field. There can be only one
compinfo that contains the field. | *) |
|
mutable fname : |
(* | The name of the field. Might be the value of Cil.missingFieldName
in which case it must be a bitfield and is not printed and it does not
participate in initialization | *) |
|
mutable ftype : |
(* | The type | *) |
|
mutable fbitfield : |
(* | If a bitfield then ftype should be an integer type and the width of the bitfield must be 0 or a positive integer smaller or equal to the width of the integer type. A field of width 0 is used in C to control the alignment of fields. | *) |
|
mutable fattr : |
(* | The attributes for this field (not for its type) | *) |
|
mutable floc : |
(* | The location where this field is defined | *) |
GEnumTag
for each of
of these.type
enuminfo = {
|
mutable ename : |
(* | The name. Always non-empty. | *) |
|
mutable eitems : |
(* | Items with names and values. This list should be non-empty. The item values must be compile-time constants. | *) |
|
mutable eattr : |
(* | The attributes that are defined at the same time as the enumeration
type. These attributes can be supplemented individually at each
reference to this enuminfo using the TEnum type constructor. | *) |
|
mutable ereferenced : |
(* | True if used. Initially set to false | *) |
|
mutable ekind : |
(* | The integer kind used to represent this enum. Per ANSI-C, this should always be IInt, but gcc allows other integer kinds | *) |
GEnumTag
for each of
of these.type
typeinfo = {
|
mutable tname : |
(* | The name. Can be empty only in a GType when introducing a composite
or enumeration tag. If empty cannot be referred to from the file | *) |
|
mutable ttype : |
(* | The actual type. This includes the attributes that were present in the typedef | *) |
|
mutable treferenced : |
(* | True if used. Initially set to false | *) |
Cil.varinfo
structure. A global Cil.varinfo
can be introduced with the GVarDecl
or
GVar
or GFun
globals. A local varinfo can be introduced as part of a
function definition Cil.fundec
.
All references to a given global or local variable must refer to the same
copy of the varinfo
. Each varinfo
has a globally unique identifier that
can be used to index maps and hashtables (the name can also be used for this
purpose, except for locals from different functions). This identifier is
constructor using a global counter.
It is very important that you construct varinfo
structures using only one
of the following functions:
Cil.makeGlobalVar
: to make a global variableCil.makeTempVar
: to make a temporary local variable whose name
will be generated so that to avoid conflict with other locals. Cil.makeLocalVar
: like Cil.makeTempVar
but you can specify the
exact name to be used. Cil.copyVarinfo
: make a shallow copy of a varinfo assigning a new name
and a new unique identifiervarinfo
is also used in a function type to denote the list of formals.type
varinfo = {
|
mutable vname : |
(* | The name of the variable. Cannot be empty. It is primarily your
responsibility to ensure the uniqueness of a variable name. For local
variables Cil.makeTempVar helps you ensure that the name is unique. | *) |
|
mutable vtype : |
(* | The declared type of the variable. | *) |
|
mutable vattr : |
(* | A list of attributes associated with the variable. | *) |
|
mutable vstorage : |
(* | The storage-class | *) |
|
mutable vglob : |
(* | True if this is a global variable | *) |
|
mutable vinline : |
(* | Whether this varinfo is for an inline function. | *) |
|
mutable vdecl : |
(* | Location of variable declaration. | *) |
|
mutable vid : |
(* | A unique integer identifier. This field will be
set for you if you use one of the Cil.makeFormalVar ,
Cil.makeLocalVar , Cil.makeTempVar , Cil.makeGlobalVar , or
Cil.copyVarinfo . | *) |
|
mutable vaddrof : |
(* | True if the address of this variable is taken. CIL will set these
flags when it parses C, but you should make sure to set the flag
whenever your transformation create AddrOf expression. | *) |
|
mutable vreferenced : |
(* | True if this variable is ever referenced. This is computed by
Rmtmps.removeUnusedTemps . It is safe to just initialize this to False | *) |
|
mutable vdescr : |
(* | For most temporary variables, a description of what the var holds. (e.g. for temporaries used for function call results, this string is a representation of the function call.) | *) |
|
mutable vdescrpure : |
(* | Indicates whether the vdescr above is a pure expression or call. Printing a non-pure vdescr more than once may yield incorrect results. | *) |
type
storage =
| |
NoStorage |
(* | The default storage. Nothing is printed | *) |
| |
Static |
|||
| |
Register |
|||
| |
Extern |
Cil.exp
. There are several
interesting aspects of CIL expressions:
Integer and floating point constants can carry their textual representation. This way the integer 15 can be printed as 0xF if that is how it occurred in the source.
CIL uses 64 bits to represent the integer constants and also stores the width
of the integer type. Care must be taken to ensure that the constant is
representable with the given width. Use the functions Cil.kinteger
,
Cil.kinteger64
and Cil.integer
to construct constant
expressions. CIL predefines the constants Cil.zero
,
Cil.one
and Cil.mone
(for -1).
Use the functions Cil.isConstant
and Cil.isInteger
to test if
an expression is a constant and a constant integer respectively.
CIL keeps the type of all unary and binary expressions. You can think of that type qualifying the operator. Furthermore there are different operators for arithmetic and comparisons on arithmetic types and on pointers.
Another unusual aspect of CIL is that the implicit conversion between an
expression of array type and one of pointer type is made explicit, using the
StartOf
expression constructor (which is not printed). If you apply the
AddrOf}
constructor to an lvalue of type T
then you will be getting an
expression of type TPtr(T)
.
You can find the type of an expression with Cil.typeOf
.
You can perform constant folding on expressions using the function
Cil.constFold
.
type
exp =
| |
Const of |
(* | Constant | *) |
| |
Lval of |
(* | Lvalue | *) |
| |
SizeOf of |
(* | sizeof(<type>). Has unsigned int type (ISO 6.5.3.4). This is not
turned into a constant because some transformations might want to
change types | *) |
| |
SizeOfE of |
(* | sizeof(<expression>) | *) |
| |
SizeOfStr of |
(* | sizeof(string_literal). We separate this case out because this is the only instance in which a string literal should not be treated as having type pointer to character. | *) |
| |
AlignOf of |
(* | This corresponds to the GCC __alignof_. Has unsigned int type | *) |
| |
AlignOfE of |
|||
| |
UnOp of |
(* | Unary operation. Includes the type of the result. | *) |
| |
BinOp of |
(* | Binary operation. Includes the type of the result. The arithmetic conversions are made explicit for the arguments. | *) |
| |
CastE of |
(* | Use Cil.mkCast to make casts. | *) |
| |
AddrOf of |
(* | Always use Cil.mkAddrOf to construct one of these. Apply to an
lvalue of type T yields an expression of type TPtr(T) . Use
Cil.mkAddrOrStartOf to make one of these if you are not sure which
one to use. | *) |
| |
StartOf of |
(* | Conversion from an array to a pointer to the beginning of the array.
Given an lval of type TArray(T) produces an expression of type
TPtr(T) . Use Cil.mkAddrOrStartOf to make one of these if you are
not sure which one to use. In C this operation is implicit, the
StartOf operator is not printed. We have it in CIL because it makes
the typing rules simpler. | *) |
type
constant =
| |
CInt64 of |
(* | Integer constant. Give the ikind (see ISO9899 6.1.3.2) and the
textual representation, if available. (This allows us to print a
constant as, for example, 0xF instead of 15.) Use Cil.integer or
Cil.kinteger to create these. Watch out for integers that cannot be
represented on 64 bits. OCAML does not give Overflow exceptions. | *) |
| |
CStr of |
(* | String constant. The escape characters inside the string have been already interpreted. This constant has pointer to character type! The only case when you would like a string literal to have an array type is when it is an argument to sizeof. In that case you should use SizeOfStr. | *) |
| |
CWStr of |
(* | Wide character string constant. Note that the local interpretation
of such a literal depends on Cil.wcharType and Cil.wcharKind .
Such a constant has type pointer to Cil.wcharType . The
escape characters in the string have not been "interpreted" in
the sense that L"A\xabcd" remains "A\xabcd" rather than being
represented as the wide character list with two elements: 65 and
43981. That "interpretation" depends on the underlying wide
character type. | *) |
| |
CChr of |
(* | Character constant. This has type int, so use charConstToInt to read the value in case sign-extension is needed. | *) |
| |
CReal of |
(* | Floating point constant. Give the fkind (see ISO 6.4.4.2) and also the textual representation, if available. | *) |
| |
CEnum of |
(* | An enumeration constant with the given value, name, from the given
enuminfo. This is used only if Cil.lowerConstants is true
(default). Use Cil.constFoldVisitor to replace these with integer
constants. | *) |
type
unop =
| |
Neg |
(* | Unary minus | *) |
| |
BNot |
(* | Bitwise complement (~) | *) |
| |
LNot |
(* | Logical Not (!) | *) |
type
binop =
| |
PlusA |
(* | arithmetic + | *) |
| |
PlusPI |
(* | pointer + integer | *) |
| |
IndexPI |
(* | pointer + integer but only when
it arises from an expression
e[i] when e is a pointer and
not an array. This is semantically
the same as PlusPI but CCured uses
this as a hint that the integer is
probably positive. | *) |
| |
MinusA |
(* | arithmetic - | *) |
| |
MinusPI |
(* | pointer - integer | *) |
| |
MinusPP |
(* | pointer - pointer | *) |
| |
Mult |
|||
| |
Div |
(* | / | *) |
| |
Mod |
(* | % | *) |
| |
Shiftlt |
(* | shift left | *) |
| |
Shiftrt |
(* | shift right | *) |
| |
Lt |
(* | < (arithmetic comparison) | *) |
| |
Gt |
(* | > (arithmetic comparison) | *) |
| |
Le |
(* | <= (arithmetic comparison) | *) |
| |
Ge |
(* | > (arithmetic comparison) | *) |
| |
Eq |
(* | == (arithmetic comparison) | *) |
| |
Ne |
(* | != (arithmetic comparison) | *) |
| |
BAnd |
(* | bitwise and | *) |
| |
BXor |
(* | exclusive-or | *) |
| |
BOr |
(* | inclusive-or | *) |
| |
LAnd |
(* | logical and. Unlike other
expressions this one does not
always evaluate both operands. If
you want to use these, you must
set Cil.useLogicalOperators . | *) |
| |
LOr |
(* | logical or. Unlike other
expressions this one does not
always evaluate both operands. If
you want to use these, you must
set Cil.useLogicalOperators . | *) |
a[0][1][2]might involve 1, 2 or 3 memory reads when used in an expression context, depending on the declared type of the variable
a
. If a
has type int
[4][4][4]
then we have one memory read from somewhere inside the area
that stores the array a
. On the other hand if a
has type int ***
then
the expression really means * ( * ( * (a + 0) + 1) + 2)
, in which case it is
clear that it involves three separate memory operations.
An lvalue denotes the contents of a range of memory addresses. This range
is denoted as a host object along with an offset within the object. The
host object can be of two kinds: a local or global variable, or an object
whose address is in a pointer expression. We distinguish the two cases so
that we can tell quickly whether we are accessing some component of a
variable directly or we are accessing a memory location through a pointer.
To make it easy to
tell what an lvalue means CIL represents lvalues as a host object and an
offset (see Cil.lval
). The host object (represented as
Cil.lhost
) can be a local or global variable or can be the object
pointed-to by a pointer expression. The offset (represented as
Cil.offset
) is a sequence of field or array index designators.
Both the typing rules and the meaning of an lvalue is very precisely specified in CIL.
The following are a few useful function for operating on lvalues:
Cil.mkMem
- makes an lvalue of Mem
kind. Use this to ensure
that certain equivalent forms of lvalues are canonized.
For example, *&x = x
. Cil.typeOfLval
- the type of an lvalueCil.typeOffset
- the type of an offset, given the type of the
host. Cil.addOffset
and Cil.addOffsetLval
- extend sequences
of offsets.Cil.removeOffset
and Cil.removeOffsetLval
- shrink sequences
of offsets.Mem(AddrOf(Mem a, aoff)), off = Mem a, aoff + off Mem(AddrOf(Var v, aoff)), off = Var v, aoff + off AddrOf (Mem a, NoOffset) = a
typelval =
lhost * offset
type
lhost =
| |
Var of |
(* | The host is a variable. | *) |
| |
Mem of |
(* | The host is an object of type T when the expression has pointer
TPtr(T) . | *) |
Cil.lval
.type
offset =
| |
NoOffset |
(* | No offset. Can be applied to any lvalue and does not change either the starting address or the type. This is used when the lval consists of just a host or as a terminator in a list of other kinds of offsets. | *) |
| |
Field of |
(* | A field offset. Can be applied only to an lvalue that denotes a structure or a union that contains the mentioned field. This advances the offset to the beginning of the mentioned field and changes the type to the type of the mentioned field. | *) |
| |
Index of |
(* | An array index offset. Can be applied only to an lvalue that denotes an array. This advances the starting address of the lval to the beginning of the mentioned array element and changes the denoted type to be the type of the array element | *) |
Cil.lval
. Each offset can be applied to certain
kinds of lvalues and its effect is that it advances the starting address
of the lvalue and changes the denoted type, essentially focusing to some
smaller lvalue that is contained in the original one.Cil.init
. You can create initializers with Cil.makeZeroInit
and you
can conveniently scan compound initializers them with
Cil.foldLeftCompound
.type
init =
| |
SingleInit of |
(* | A single initializer | *) |
| |
CompoundInit of |
(* | Used only for initializers of structures, unions and arrays. The
offsets are all of the form Field(f, NoOffset) or Index(i,
NoOffset) and specify the field or the index being initialized. For
structures all fields must have an initializer (except the unnamed
bitfields), in the proper order. This is necessary since the offsets
are not printed. For unions there must be exactly one initializer. If
the initializer is not for the first field then a field designator is
printed, so you better be on GCC since MSVC does not understand this.
For arrays, however, we allow you to give only a prefix of the
initializers. You can scan an initializer list with
Cil.foldLeftCompound . | *) |
type
initinfo = {
|
mutable init : |
GFun
constructor at the
top level. All the information about the function is stored into a
Cil.fundec
. Some of the information (e.g. its name, type,
storage, attributes) is stored as a Cil.varinfo
that is a field of the
fundec
. To refer to the function from the expression language you must use
the varinfo
.
The function definition contains, in addition to the body, a list of all the
local variables and separately a list of the formals. Both kind of variables
can be referred to in the body of the function. The formals must also be shared
with the formals that appear in the function type. For that reason, to
manipulate formals you should use the provided functions
Cil.makeFormalVar
and Cil.setFormals
and Cil.makeFormalVar
.
type
fundec = {
|
mutable svar : |
(* | Holds the name and type as a variable, so we can refer to it
easily from the program. All references to this function either
in a function call or in a prototype must point to the same
varinfo . | *) |
|
mutable sformals : |
(* | Formals. These must be in the same order and with the same
information as the formal information in the type of the function.
Use Cil.setFormals or
Cil.setFunctionType or Cil.makeFormalVar
to set these formals and ensure that they
are reflected in the function type. Do not make copies of these
because the body refers to them. | *) |
|
mutable slocals : |
(* | Locals. Does NOT include the sformals. Do not make copies of these because the body refers to them. | *) |
|
mutable smaxid : |
(* | Max local id. Starts at 0. Used for
creating the names of new temporary
variables. Updated by
Cil.makeLocalVar and
Cil.makeTempVar . You can also use
Cil.setMaxId to set it after you
have added the formals and locals. | *) |
|
mutable sbody : |
(* | The function body. | *) |
|
mutable smaxstmtid : |
(* | max id of a (reachable) statement
in this function, if we have
computed it. range = 0 ...
(smaxstmtid-1). This is computed by
Cil.computeCFGInfo . | *) |
|
mutable sallstmts : |
(* | After you call Cil.computeCFGInfo
this field is set to contain all
statements in the function | *) |
type
block = {
|
mutable battrs : |
(* | Attributes for the block | *) |
|
mutable bstmts : |
(* | The statements comprising the block | *) |
Cil.stmt
. Every
statement has a (possibly empty) list of labels. The
Cil.stmtkind
field of a statement indicates what kind of statement it
is.
Use Cil.mkStmt
to make a statement and the fill-in the fields.
CIL also comes with support for control-flow graphs. The sid
field in
stmt
can be used to give unique numbers to statements, and the succs
and preds
fields can be used to maintain a list of successors and
predecessors for every statement. The CFG information is not computed by
default. Instead you must explicitly use the functions
Cil.prepareCFG
and Cil.computeCFGInfo
to do it.
type
stmt = {
|
mutable labels : |
(* | Whether the statement starts with some labels, case statements or default statements. | *) |
|
mutable skind : |
(* | The kind of statement | *) |
|
mutable sid : |
(* | A number (>= 0) that is unique in a function. Filled in only after the CFG is computed. | *) |
|
mutable succs : |
(* | The successor statements. They can always be computed from the skind and the context in which this statement appears. Filled in only after the CFG is computed. | *) |
|
mutable preds : |
(* | The inverse of the succs function. | *) |
type
label =
| |
Label of |
(* | A real label. If the bool is "true", the label is from the input source program. If the bool is "false", the label was created by CIL or some other transformation | *) |
| |
Case of |
(* | A case statement. This expression
is lowered into a constant if
Cil.lowerConstants is set to
true. | *) |
| |
Default of |
(* | A default statement | *) |
type
stmtkind =
| |
Instr of |
(* | A group of instructions that do not contain control flow. Control implicitly falls through. | *) |
| |
Return of |
(* | The return statement. This is a leaf in the CFG. | *) |
| |
Goto of |
(* | A goto statement. Appears from actual goto's in the code or from goto's that have been inserted during elaboration. The reference points to the statement that is the target of the Goto. This means that you have to update the reference whenever you replace the target statement. The target statement MUST have at least a label. | *) |
| |
Break of |
(* | A break to the end of the nearest enclosing Loop or Switch | *) |
| |
Continue of |
(* | A continue to the start of the nearest enclosing Loop | *) |
| |
If of |
(* | A conditional. Two successors, the "then" and the "else" branches. Both branches fall-through to the successor of the If statement. | *) |
| |
Switch of |
(* | A switch statement. The statements that implement the cases can be
reached through the provided list. For each such target you can find
among its labels what cases it implements. The statements that
implement the cases are somewhere within the provided block . | *) |
| |
Loop of |
(* | A while(1) loop. The termination test is implemented in the body of
a loop using a Break statement. If prepareCFG has been called,
the first stmt option will point to the stmt containing the continue
label for this loop and the second will point to the stmt containing
the break label for this loop. | *) |
| |
Block of |
(* | Just a block of statements. Use it as a way to keep some block attributes local | *) |
| |
TryFinally of |
|||
| |
TryExcept of |
Cil.instr
is a statement that has no local
(intraprocedural) control flow. It can be either an assignment,
function call, or an inline assembly instruction.type
instr =
| |
Set of |
(* | An assignment. The type of the expression is guaranteed to be the same with that of the lvalue | *) |
| |
Call of |
(* | A function call with the (optional) result placed in an lval. It is possible that the returned type of the function is not identical to that of the lvalue. In that case a cast is printed. The type of the actual arguments are identical to those of the declared formals. The number of arguments is the same as that of the declared formals, except for vararg functions. This construct is also used to encode a call to "__builtin_va_arg". In this case the second argument (which should be a type T) is encoded SizeOf(T) | *) |
| |
Asm of |
(* | There are for storing inline assembly. They follow the GCC
specification:
asm [volatile] ("...template..." "..template.." : "c1" (o1), "c2" (o2), ..., "cN" (oN) : "d1" (i1), "d2" (i2), ..., "dM" (iM) : "r1", "r2", ..., "nL" ); where the parts are
asm volatile ("movc3 %0,%1,%2" : /* no outputs */ : "g" (from), "g" (to), "g" (count) : "r0", "r1", "r2", "r3", "r4", "r5"); Starting with gcc 3.1, the operands may have names:
asm volatile ("movc3 %[in0],%1,%2" : /* no outputs */ : [in0] "g" (from), "g" (to), "g" (count) : "r0", "r1", "r2", "r3", "r4", "r5"); | *) |
type
location = {
|
line : |
(* | The line number. -1 means "do not know" | *) |
|
file : |
(* | The name of the source file | *) |
|
byte : |
(* | The byte position in the source file | *) |
type
typsig =
| |
TSArray of |
| |
TSPtr of |
| |
TSComp of |
| |
TSFun of |
| |
TSEnum of |
| |
TSBase of |
TNamed
constructors are unrolled.val lowerConstants : bool ref
val insertImplicitCasts : bool ref
type
featureDescr = {
|
fd_enabled : |
(* | The enable flag. Set to default value | *) |
|
fd_name : |
(* | This is used to construct an option "--doxxx" and "--dontxxx" that enable and disable the feature | *) |
|
fd_description : |
(* | A longer name that can be used to document the new options | *) |
|
fd_extraopt : |
(* | Additional command line options. The description strings should usually start with a space for Arg.align to print the --help nicely. | *) |
|
fd_doit : |
(* | This performs the transformation | *) |
|
fd_post_check : |
(* | Whether to perform a CIL consistency checking after this stage, if checking is enabled (--check is passed to cilly). Set this to true if your feature makes any changes for the program. | *) |
val compareLoc : location -> location -> int
val emptyFunction : string -> fundec
val setFormals : fundec -> varinfo list -> unit
fundec
and make sure that the function type
has the same information. Will copy the name as well into the type.val setFunctionType : fundec -> typ -> unit
val setFunctionTypeMakeFormals : fundec -> typ -> unit
val setMaxId : fundec -> unit
Cil.makeLocalVar
or
Cil.makeTempVar
.val dummyFunDec : fundec
val dummyFile : file
val saveBinaryFile : file -> string -> unit
Cil.file
in binary form to the filesystem. The file can be
read back in later using Cil.loadBinaryFile
, possibly saving parsing
time. The second argument is the name of the file that should be
created.val saveBinaryFileChannel : file -> out_channel -> unit
Cil.file
in binary form to the filesystem. The file can be
read back in later using Cil.loadBinaryFile
, possibly saving parsing
time. Does not close the channel.val loadBinaryFile : string -> file
Cil.file
in binary form from the filesystem. The first
argument is the name of a file previously created by
Cil.saveBinaryFile
. Because this also reads some global state,
this should be called before any other CIL code is parsed or generated.val getGlobInit : ?main_name:string -> file -> fundec
val iterGlobals : file -> (global -> unit) -> unit
val foldGlobals : file -> ('a -> global -> 'a) -> 'a -> 'a
val mapGlobals : file -> (global -> global) -> unit
val findOrCreateFunc : file -> string -> typ -> varinfo
Because the new prototype is added to the start of the file, you shouldn't
refer to any struct or union types in the function type.
val new_sid : unit -> int
val prepareCFG : fundec -> unit
Cil.computeCFGInfo
. This function converts all Break
, Switch
,
Default
and Continue
Cil.stmtkind
s and Cil.label
s into If
s
and Goto
s, giving the function body a very CFG-like character. This
function modifies its argument in place.val computeCFGInfo : fundec -> bool -> unit
Break
, Switch
,
Default
, or Continue
Cil.stmtkind
s or Cil.label
s. Use
Cil.prepareCFG
to transform them away. The second argument should
be true
if you wish a global statement number, false
if you wish a
local (per-function) statement numbering. The list of statements is set
in the sallstmts field of a fundec.
NOTE: unless you want the simpler control-flow graph provided by
prepareCFG, or you need the function's smaxstmtid and sallstmt fields
filled in, we recommend you use Cfg.computeFileCFG
instead of this
function to compute control-flow information.
Cfg.computeFileCFG
is newer and will handle switch, break, and
continue correctly.
val copyFunction : fundec -> string -> fundec
val pushGlobal : global ->
types:global list ref ->
variables:global list ref -> unit
val invalidStmt : stmt
val builtinFunctions : (string, typ * typ list * bool) Hashtbl.t
!msvcMode
). Maps the name to the
result and argument types, and whether it is vararg.
Initialized by Cil.initCIL
This map replaces gccBuiltins
and msvcBuiltins
in previous
versions of CIL.
val gccBuiltins : (string, typ * typ list * bool) Hashtbl.t
val msvcBuiltins : (string, typ * typ list * bool) Hashtbl.t
val builtinLoc : location
val makeZeroInit : typ -> init
val foldLeftCompound : implicit:bool ->
doinit:(offset -> init -> typ -> 'a -> 'a) ->
ct:typ -> initl:(offset * init) list -> acc:'a -> 'a
doinit
is called on every present initializer, even if it is of
compound type. The parameters of doinit
are: the offset in the compound
(this is Field(f,NoOffset)
or Index(i,NoOffset)
), the initializer
value, expected type of the initializer value, accumulator. In the case of
arrays there might be missing zero-initializers at the end of the list.
These are scanned only if implicit
is true. This is much like
List.fold_left
except we also pass the type of the initializer.
This is a good way to use it to scan even nested initializers :
let rec myInit (lv: lval) (i: init) (acc: 'a) : 'a = match i with SingleInit e -> ... do something with lv and e and acc ... | CompoundInit (ct, initl) -> foldLeftCompound ~implicit:false ~doinit:(fun off' i' t' acc -> myInit (addOffsetLval lv off') i' acc) ~ct:ct ~initl:initl ~acc:acc
val voidType : typ
val isVoidType : typ -> bool
val isVoidPtrType : typ -> bool
val intType : typ
val uintType : typ
val longType : typ
val ulongType : typ
val charType : typ
val charPtrType : typ
val wcharKind : ikind ref
Cil.initCIL
.val wcharType : typ ref
val charConstPtrType : typ
val voidPtrType : typ
val intPtrType : typ
val uintPtrType : typ
val doubleType : typ
val upointType : typ ref
Cil.msvcMode
and is set when you call Cil.initCIL
.val typeOfSizeOf : typ ref
Cil.msvcMode
and is set when you call Cil.initCIL
.val kindOfSizeOf : ikind ref
val isSigned : ikind -> bool
val mkCompInfo : bool ->
string ->
(compinfo ->
(string * typ * int option * attributes * location) list) ->
attributes -> compinfo
val copyCompInfo : compinfo -> string -> compinfo
Cil.compinfo
changing the name and the key.val missingFieldName : string
val compFullName : compinfo -> string
val isCompleteType : typ -> bool
val unrollType : typ -> typ
TNamed
. Will collect all attributes appearing in TNamed
!!!val unrollTypeDeep : typ -> typ
TPtr
, TFun
or TArray
. Does not unroll the types of fields in TComp
types. Will collect all attributesval separateStorageModifiers : attribute list -> attribute list * attribute list
val isIntegralType : typ -> bool
val isArithmeticType : typ -> bool
val isPointerType : typ -> bool
val isFunctionType : typ -> bool
val argsToList : (string * typ * attributes) list option ->
(string * typ * attributes) list
val isArrayType : typ -> bool
exception LenOfArray
Cil.lenOfArray
fails either because the length is None
or because it is a non-constant expressionval lenOfArray : exp option -> int
Cil.LenOfArray
if not able to compute the length, such
as when there is no length or the length is not a constant.val getCompField : compinfo -> string -> fieldinfo
type
existsAction =
| |
ExistsTrue |
(* | We have found it | *) |
| |
ExistsFalse |
(* | Stop processing this branch | *) |
| |
ExistsMaybe |
(* | This node is not what we are looking for but maybe its successors are | *) |
existsType
val existsType : (typ -> existsAction) -> typ -> bool
val splitFunctionType : typ ->
typ * (string * typ * attributes) list option * bool *
attributes
Same as Cil.splitFunctionType
but takes a varinfo. Prints a nicer
error message if the varinfo is not for a function
val splitFunctionTypeVI : varinfo ->
typ * (string * typ * attributes) list option * bool *
attributes
TNamed
constructors are unrolled.val d_typsig : unit -> typsig -> Pretty.doc
val typeSig : typ -> typsig
val typeSigWithAttrs : ?ignoreSign:bool ->
(attributes -> attributes) -> typ -> typsig
Cil.typeSig
but customize the incorporation of attributes.
Use ~ignoreSign:true to convert all signed integer types to unsigned,
so that signed and unsigned will compare the same.val setTypeSigAttrs : attributes -> typsig -> typsig
val typeSigAttrs : typsig -> attributes
val makeVarinfo : bool -> string -> typ -> varinfo
Cil.makeLocalVar
or Cil.makeFormalVar
or
Cil.makeTempVar
) and globals (Cil.makeGlobalVar
). Note that this
function will assign a new identifier. The first argument specifies
whether the varinfo is for a global.val makeFormalVar : fundec -> ?where:string -> string -> typ -> varinfo
val makeLocalVar : fundec -> ?insert:bool -> string -> typ -> varinfo
val makeTempVar : fundec ->
?insert:bool ->
?name:string ->
?descr:Pretty.doc -> ?descrpure:bool -> typ -> varinfo
The variable will be added to the function's slocals unless you explicitly set insert=false. (Make sure you know what you are doing if you set insert=false.)
Optionally, you can give the variable a description of its contents
that will be printed by descriptiveCilPrinter.
val makeGlobalVar : string -> typ -> varinfo
val copyVarinfo : varinfo -> string -> varinfo
varinfo
and assign a new identifierval newVID : unit -> int
Cil.makeLocalVar
and friendsval addOffsetLval : offset -> lval -> lval
val addOffset : offset -> offset -> offset
addOffset o1 o2
adds o1
to the end of o2
.val removeOffsetLval : lval -> lval * offset
NoOffset
then the original lval
did not have an offset.val removeOffset : offset -> offset * offset
NoOffset
then the original lval
did not have an offset.val typeOfLval : lval -> typ
val typeOffset : typ -> offset -> typ
val zero : exp
val one : exp
val mone : exp
val kinteger64 : ikind -> int64 -> exp
val kinteger : ikind -> int -> exp
val integer : int -> exp
val isInteger : exp -> int64 option
val i64_to_int : int64 -> int
val isConstant : exp -> bool
val isConstantOffset : offset -> bool
val isZero : exp -> bool
val charConstToInt : char -> constant
val convertInts : int64 -> ikind -> int64 -> ikind -> int64 * int64 * ikind
val constFold : bool -> exp -> exp
Cil.constFoldVisitor
, which will run constFold on all
expressions in a given AST node.val constFoldBinOp : bool -> binop -> exp -> exp -> typ -> exp
constFold
is done here. If the first argument is true then
will also compute compiler-dependent expressions such as sizeofval increm : exp -> int -> exp
val var : varinfo -> lval
val mkAddrOf : lval -> exp
0
"val mkAddrOrStartOf : lval -> exp
val mkMem : addr:exp -> off:offset -> lval
val mkString : string -> exp
val mkCastT : e:exp -> oldt:typ -> newt:typ -> exp
val mkCast : e:exp -> newt:typ -> exp
val stripCasts : exp -> exp
val typeOf : exp -> typ
val parseInt : string -> exp
val mkStmt : stmtkind -> stmt
sid
field to -1,
and labels
, succs
and preds
to the empty listval mkBlock : stmt list -> block
val mkStmtOneInstr : instr -> stmt
val compactStmts : stmt list -> stmt list
val mkEmptyStmt : unit -> stmt
Instr
)val dummyInstr : instr
val dummyStmt : stmt
dummyInstr
val mkWhile : guard:exp -> body:stmt list -> stmt list
val mkForIncr : iter:varinfo ->
first:exp ->
stopat:exp -> incr:exp -> body:stmt list -> stmt list
val mkFor : start:stmt list ->
guard:exp -> next:stmt list -> body:stmt list -> stmt list
type
attributeClass =
| |
AttrName of |
(* | Attribute of a name. If argument is true and we are on MSVC then the attribute is printed using __declspec as part of the storage specifier | *) |
| |
AttrFunType of |
(* | Attribute of a function type. If argument is true and we are on MSVC then the attribute is printed just before the function name | *) |
| |
AttrType |
(* | Attribute of a type | *) |
val attributeHash : (string, attributeClass) Hashtbl.t
val partitionAttributes : default:attributeClass ->
attributes ->
attribute list * attribute list * attribute list
val addAttribute : attribute -> attributes -> attributes
val addAttributes : attribute list -> attributes -> attributes
val dropAttribute : string -> attributes -> attributes
val dropAttributes : string list -> attributes -> attributes
val filterAttributes : string -> attributes -> attributes
val hasAttribute : string -> attributes -> bool
val typeAttrs : typ -> attribute list
val setTypeAttrs : typ -> attributes -> typ
val typeAddAttributes : attribute list -> typ -> typ
val typeRemoveAttributes : string list -> typ -> typ
val expToAttrParam : exp -> attrparam
exception NotAnAttrParam of exp
type 'a
visitAction =
| |
SkipChildren |
(* | Do not visit the children. Return the node as it is. | *) |
| |
DoChildren |
(* | Continue with the children of this node. Rebuild the node on return if any of the children changes (use == test) | *) |
| |
ChangeTo of |
(* | Replace the expression with the given one | *) |
| |
ChangeDoChildrenPost of |
(* | First consider that the entire exp is replaced by the first parameter. Then continue with the children. On return rebuild the node if any of the children has changed and then apply the function on the node | *) |
exp
, instr
,
etc.class type cilVisitor =object
..end
class nopCilVisitor :cilVisitor
val visitCilFile : cilVisitor -> file -> unit
Cil.visitCilFileSameGlobals
if your visitor will
not change the list of globals.val visitCilFileSameGlobals : cilVisitor -> file -> unit
Cil.visitCilFile
whenever appropriate because it is more efficient for
long files.val visitCilGlobal : cilVisitor -> global -> global list
val visitCilFunction : cilVisitor -> fundec -> fundec
val visitCilExpr : cilVisitor -> exp -> exp
val visitCilLval : cilVisitor -> lval -> lval
val visitCilOffset : cilVisitor -> offset -> offset
val visitCilInitOffset : cilVisitor -> offset -> offset
val visitCilInstr : cilVisitor -> instr -> instr list
val visitCilStmt : cilVisitor -> stmt -> stmt
val visitCilBlock : cilVisitor -> block -> block
val visitCilType : cilVisitor -> typ -> typ
val visitCilVarDecl : cilVisitor -> varinfo -> varinfo
val visitCilInit : cilVisitor -> varinfo -> offset -> init -> init
val visitCilAttributes : cilVisitor -> attribute list -> attribute list
val msvcMode : bool ref
Cil.initCIL
.val useLogicalOperators : bool ref
val oldstyleExternInline : bool ref
val constFoldVisitor : bool -> cilVisitor
type
lineDirectiveStyle =
| |
LineComment |
(* | Before every element, print the line number in comments. This is ignored by processing tools (thus errors are reproted in the CIL output), but useful for visual inspection | *) |
| |
LineCommentSparse |
(* | Like LineComment but only print a line directive for a new source line | *) |
| |
LinePreprocessorInput |
(* | Use # nnn directives (in gcc mode) | *) |
| |
LinePreprocessorOutput |
(* | Use #line directives | *) |
val lineDirectiveStyle : lineDirectiveStyle option ref
val print_CIL_Input : bool ref
val printCilAsIs : bool ref
val lineLength : int ref
val forgcc : string -> string
val currentLoc : location ref
val currentGlobal : global ref
Pretty.doc
) and the error-message modules (see Errormsg.error
).
Here is a typical example for printing a log message:
ignore (Errormsg.log "Expression %a is not positive (at %s:%i)\n" d_exp e loc.file loc.line)
and here is an example of how you print a fatal error message that stop the execution:
Errormsg.s (Errormsg.bug "Why am I here?")
Notice that you can use C format strings with some extension. The most
useful extension is "%a" that means to consumer the next two argument from
the argument list and to apply the first to unit
and then to the second
and to print the resulting Pretty.doc
. For each major type in CIL there is
a corresponding function that pretty-prints an element of that type:
val d_loc : unit -> location -> Pretty.doc
val d_thisloc : unit -> Pretty.doc
Cil.currentLoc
val d_ikind : unit -> ikind -> Pretty.doc
val d_fkind : unit -> fkind -> Pretty.doc
val d_storage : unit -> storage -> Pretty.doc
val d_const : unit -> constant -> Pretty.doc
val derefStarLevel : int
val indexLevel : int
val arrowLevel : int
val addrOfLevel : int
val additiveLevel : int
val comparativeLevel : int
val bitwiseLevel : int
val getParenthLevel : exp -> int
class type cilPrinter =object
..end
class defaultCilPrinterClass :cilPrinter
val defaultCilPrinter : cilPrinter
class plainCilPrinterClass :cilPrinter
val plainCilPrinter : cilPrinter
class type descriptiveCilPrinter =object
..end
class descriptiveCilPrinterClass :bool ->
descriptiveCilPrinter
val descriptiveCilPrinter : descriptiveCilPrinter
val printerForMaincil : cilPrinter ref
val printType : cilPrinter -> unit -> typ -> Pretty.doc
val printExp : cilPrinter -> unit -> exp -> Pretty.doc
val printLval : cilPrinter -> unit -> lval -> Pretty.doc
val printGlobal : cilPrinter -> unit -> global -> Pretty.doc
val printAttr : cilPrinter -> unit -> attribute -> Pretty.doc
val printAttrs : cilPrinter -> unit -> attributes -> Pretty.doc
val printInstr : cilPrinter -> unit -> instr -> Pretty.doc
val printStmt : cilPrinter -> unit -> stmt -> Pretty.doc
Cil.dumpStmt
instead.val printBlock : cilPrinter -> unit -> block -> Pretty.doc
Cil.dumpBlock
instead.val dumpStmt : cilPrinter -> out_channel -> int -> stmt -> unit
Cil.printStmt
whenever possible.val dumpBlock : cilPrinter -> out_channel -> int -> block -> unit
Cil.printBlock
whenever possible.val printInit : cilPrinter -> unit -> init -> Pretty.doc
Cil.dumpInit
instead.val dumpInit : cilPrinter -> out_channel -> int -> init -> unit
Cil.printInit
whenever possible.val d_type : unit -> typ -> Pretty.doc
Cil.defaultCilPrinter
val d_exp : unit -> exp -> Pretty.doc
Cil.defaultCilPrinter
val d_lval : unit -> lval -> Pretty.doc
Cil.defaultCilPrinter
val d_offset : Pretty.doc -> unit -> offset -> Pretty.doc
Cil.defaultCilPrinter
, given the pretty
printing for the base.val d_init : unit -> init -> Pretty.doc
Cil.defaultCilPrinter
. This can be
extremely slow (or even overflow the stack) for huge initializers. Use
Cil.dumpInit
instead.val d_binop : unit -> binop -> Pretty.doc
val d_unop : unit -> unop -> Pretty.doc
val d_attr : unit -> attribute -> Pretty.doc
Cil.defaultCilPrinter
val d_attrparam : unit -> attrparam -> Pretty.doc
Cil.defaultCilPrinter
val d_attrlist : unit -> attributes -> Pretty.doc
Cil.defaultCilPrinter
val d_instr : unit -> instr -> Pretty.doc
Cil.defaultCilPrinter
val d_label : unit -> label -> Pretty.doc
Cil.defaultCilPrinter
val d_stmt : unit -> stmt -> Pretty.doc
Cil.defaultCilPrinter
. This can be
extremely slow (or even overflow the stack) for huge statements. Use
Cil.dumpStmt
instead.val d_block : unit -> block -> Pretty.doc
Cil.defaultCilPrinter
. This can be
extremely slow (or even overflow the stack) for huge blocks. Use
Cil.dumpBlock
instead.val d_global : unit -> global -> Pretty.doc
Cil.defaultCilPrinter
. This can be extremely slow (or even overflow the
stack) for huge globals (such as arrays with lots of initializers). Use
Cil.dumpGlobal
instead.val dn_exp : unit -> exp -> Pretty.doc
val dn_lval : unit -> lval -> Pretty.doc
val dn_init : unit -> init -> Pretty.doc
val dn_type : unit -> typ -> Pretty.doc
val dn_global : unit -> global -> Pretty.doc
val dn_attrlist : unit -> attributes -> Pretty.doc
val dn_attr : unit -> attribute -> Pretty.doc
val dn_attrparam : unit -> attrparam -> Pretty.doc
val dn_stmt : unit -> stmt -> Pretty.doc
val dn_instr : unit -> instr -> Pretty.doc
val d_shortglobal : unit -> global -> Pretty.doc
val dumpGlobal : cilPrinter -> out_channel -> global -> unit
val dumpFile : cilPrinter -> out_channel -> string -> file -> unit
Errormsg.bug
and Errormsg.unimp
if you do not want
thatval bug : ('a, unit, Pretty.doc) format -> 'a
val unimp : ('a, unit, Pretty.doc) format -> 'a
val error : ('a, unit, Pretty.doc) format -> 'a
val errorLoc : location -> ('a, unit, Pretty.doc) format -> 'a
Cil.error
except that it explicitly takes a location argument,
instead of using the Cil.currentLoc
val warn : ('a, unit, Pretty.doc) format -> 'a
val warnOpt : ('a, unit, Pretty.doc) format -> 'a
Errormsg.warnOpt
except that Cil.currentLoc
is also printed.
This warning is printed only of Errormsg.warnFlag
is set.val warnContext : ('a, unit, Pretty.doc) format -> 'a
val warnContextOpt : ('a, unit, Pretty.doc) format -> 'a
Errormsg.warn
except that Cil.currentLoc
and context is also
printed. This warning is printed only of Errormsg.warnFlag
is set.val warnLoc : location -> ('a, unit, Pretty.doc) format -> 'a
Cil.warn
except that it explicitly takes a location argument,
instead of using the Cil.currentLoc
val d_plainexp : unit -> exp -> Pretty.doc
val d_plaininit : unit -> init -> Pretty.doc
val d_plainlval : unit -> lval -> Pretty.doc
val d_plaintype : unit -> typ -> Pretty.doc
val dd_exp : unit -> exp -> Pretty.doc
Pretty-print an lvalue on the left side of an assignment.
If there is an offset or memory dereference, temporaries will
be replaced by descriptions as in dd_exp. If the lval is a temp var,
that var will not be replaced by a description; use "dd_exp () (Lval lv)"
if that's what you want.
val dd_lval : unit -> lval -> Pretty.doc
val uniqueVarNames : file -> unit
val peepHole2 : (instr * instr -> instr list option) -> stmt list -> unit
val peepHole1 : (instr -> instr list option) -> stmt list -> unit
peepHole2
except that the optimization window consists of
one instruction, not twoexception SizeOfError of string * typ
val unsignedVersionOf : ikind -> ikind
val intKindForSize : int -> bool -> ikind
val floatKindForSize : int -> fkind
val bytesSizeOfInt : ikind -> int
val bitsSizeOf : typ -> int
Cil.SizeOfError
when it cannot compute the size. This
function is architecture dependent, so you should only call this after you
call Cil.initCIL
. Remember that on GCC sizeof(void) is 1!val truncateInteger64 : ikind -> int64 -> int64 * bool
val fitsInInt : ikind -> int64 -> bool
val intKindForValue : int64 -> bool -> ikind
val sizeOf : typ -> exp
Cil.initCIL
.val alignOf_int : typ -> int
Cil.initCIL
.val bitsOffset : typ -> offset -> int * int
Cil.SizeOfError
when it cannot compute
the size. This function is architecture dependent, so you should only call
this after you call Cil.initCIL
.val char_is_unsigned : bool ref
Cil.initCIL
val little_endian : bool ref
Cil.initCIL
val underscore_name : bool ref
Cil.initCIL
val locUnknown : location
val get_instrLoc : instr -> location
val get_globalLoc : global -> location
val get_stmtLoc : stmtkind -> location
val dExp : Pretty.doc -> exp
Cil.exp
to be used in case of errors.val dInstr : Pretty.doc -> location -> instr
Cil.instr
to be used in case of errors.val dGlobal : Pretty.doc -> location -> global
Cil.global
to be used in case of errors.val mapNoCopy : ('a -> 'a) -> 'a list -> 'a list
val mapNoCopyList : ('a -> 'a list) -> 'a list -> 'a list
val startsWith : string -> string -> bool
val endsWith : string -> string -> bool
val stripUnderscores : string -> string
type
formatArg =
| |
Fe of |
|||
| |
Feo of |
(* | For array lengths | *) |
| |
Fu of |
|||
| |
Fb of |
|||
| |
Fk of |
|||
| |
FE of |
(* | For arguments in a function call | *) |
| |
Ff of |
(* | For a formal argument | *) |
| |
FF of |
(* | For formal argument lists | *) |
| |
Fva of |
(* | For the ellipsis in a function type | *) |
| |
Fv of |
|||
| |
Fl of |
|||
| |
Flo of |
|||
| |
Fo of |
|||
| |
Fc of |
|||
| |
Fi of |
|||
| |
FI of |
|||
| |
Ft of |
|||
| |
Fd of |
|||
| |
Fg of |
|||
| |
Fs of |
|||
| |
FS of |
|||
| |
FA of |
|||
| |
Fp of |
|||
| |
FP of |
|||
| |
FX of |
val d_formatarg : unit -> formatArg -> Pretty.doc
val warnTruncate : bool ref
val envMachine : Machdep.mach option ref