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 -> unitCil.msvcMode.val cilVersion : stringval cilVersionMajor : intval cilVersionMinor : intval cilVersionRevision : intFrontc.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.isScalarType,
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 refval insertImplicitCasts : bool reftype 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 -> intval emptyFunction : string -> fundecval setFormals : fundec -> varinfo list -> unitfundec and make sure that the function type
has the same information. Will copy the name as well into the type.val setFunctionType : fundec -> typ -> unitval setFunctionTypeMakeFormals : fundec -> typ -> unitval setMaxId : fundec -> unitCil.makeLocalVar or
Cil.makeTempVar.val dummyFunDec : fundecval dummyFile : fileval saveBinaryFile : file -> string -> unitCil.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 -> unitCil.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 -> fileCil.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 -> fundecval iterGlobals : file -> (global -> unit) -> unitval foldGlobals : file -> ('a -> global -> 'a) -> 'a -> 'aval mapGlobals : file -> (global -> global) -> unitval 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 -> intval prepareCFG : fundec -> unitCil.computeCFGInfo. This function converts all Break, Switch,
Default and Continue Cil.stmtkinds and Cil.labels into Ifs
and Gotos, giving the function body a very CFG-like character. This
function modifies its argument in place.val computeCFGInfo : fundec -> bool -> unitBreak, Switch,
Default, or Continue Cil.stmtkinds or Cil.labels. 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 -> fundecval pushGlobal : global ->
types:global list ref ->
variables:global list ref -> unitval invalidStmt : stmtval 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 builtinLoc : locationval makeZeroInit : typ -> initval foldLeftCompound : implicit:bool ->
doinit:(offset -> init -> typ -> 'a -> 'a) ->
ct:typ -> initl:(offset * init) list -> acc:'a -> 'adoinit 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:accval voidType : typval isVoidType : typ -> boolval isVoidPtrType : typ -> boolval intType : typval uintType : typval longType : typval ulongType : typval charType : typval charPtrType : typval wcharKind : ikind refCil.initCIL.val wcharType : typ refval charConstPtrType : typval voidPtrType : typval intPtrType : typval uintPtrType : typval doubleType : typval upointType : typ refCil.msvcMode
and is set when you call Cil.initCIL.val typeOfSizeOf : typ refCil.msvcMode and is set when you call Cil.initCIL.val kindOfSizeOf : ikind ref
val isSigned : ikind -> boolval mkCompInfo : bool ->
string ->
(compinfo ->
(string * typ * int option * attributes * location) list) ->
attributes -> compinfoval copyCompInfo : compinfo -> string -> compinfoCil.compinfo changing the name and the key.val missingFieldName : stringval compFullName : compinfo -> stringval isCompleteType : typ -> boolval unrollType : typ -> typTNamed. Will collect all attributes appearing in TNamed!!!val unrollTypeDeep : typ -> typTPtr, TFun or TArray. Does not unroll the types of fields in TComp
types. Will collect all attributesval separateStorageModifiers : attribute list -> attribute list * attribute listval isIntegralType : typ -> boolval isArithmeticType : typ -> boolval isPointerType : typ -> boolval isScalarType : typ -> boolval isFunctionType : typ -> boolval argsToList : (string * typ * attributes) list option ->
(string * typ * attributes) listval isArrayType : typ -> boolexception LenOfArray
Cil.lenOfArray fails either because the length is None
or because it is a non-constant expressionval lenOfArray : exp option -> intCil.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 -> fieldinfotype 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 | *) |
existsTypeval existsType : (typ -> existsAction) -> typ -> boolval 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 *
attributesTNamed
constructors are unrolled.val d_typsig : unit -> typsig -> Pretty.docval typeSig : typ -> typsigval typeSigWithAttrs : ?ignoreSign:bool ->
(attributes -> attributes) -> typ -> typsigCil.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 -> typsigval typeSigAttrs : typsig -> attributesval makeVarinfo : bool -> string -> typ -> varinfoCil.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 -> varinfoval makeLocalVar : fundec -> ?insert:bool -> string -> typ -> varinfoval makeTempVar : fundec ->
?insert:bool ->
?name:string ->
?descr:Pretty.doc -> ?descrpure:bool -> typ -> varinfoThe 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 -> varinfoval copyVarinfo : varinfo -> string -> varinfovarinfo and assign a new identifierval newVID : unit -> intCil.makeLocalVar and friendsval addOffsetLval : offset -> lval -> lvalval addOffset : offset -> offset -> offsetaddOffset o1 o2 adds o1 to the end of o2.val removeOffsetLval : lval -> lval * offsetNoOffset
then the original lval did not have an offset.val removeOffset : offset -> offset * offsetNoOffset
then the original lval did not have an offset.val typeOfLval : lval -> typval typeOffset : typ -> offset -> typval zero : expval one : expval mone : expval kintegerCilint : ikind -> Cilint.cilint -> expval kinteger64 : ikind -> int64 -> expval kinteger : ikind -> int -> expval integer : int -> expval getInteger : exp -> Cilint.cilint optionval i64_to_int : int64 -> intval cilint_to_int : Cilint.cilint -> intval isConstant : exp -> boolval isConstantOffset : offset -> boolval isZero : exp -> boolval charConstToInt : char -> constantval constFold : bool -> exp -> expCil.constFoldVisitor, which will run constFold on all
expressions in a given AST node.val constFoldBinOp : bool -> binop -> exp -> exp -> typ -> expconstFold is done here. If the first argument is true then
will also compute compiler-dependent expressions such as sizeofval increm : exp -> int -> expval var : varinfo -> lvalval mkAddrOf : lval -> exp0"val mkAddrOrStartOf : lval -> expval mkMem : addr:exp -> off:offset -> lvalval mkString : string -> expval mkCastT : e:exp -> oldt:typ -> newt:typ -> expval mkCast : e:exp -> newt:typ -> exp
val stripCasts : exp -> expval typeOf : exp -> typval parseInt : string -> expval mkStmt : stmtkind -> stmtsid field to -1,
and labels, succs and preds to the empty listval mkBlock : stmt list -> blockval mkStmtOneInstr : instr -> stmtval compactStmts : stmt list -> stmt listval mkEmptyStmt : unit -> stmtInstr)val dummyInstr : instrval dummyStmt : stmtdummyInstrval mkWhile : guard:exp -> body:stmt list -> stmt listval mkForIncr : iter:varinfo ->
first:exp ->
stopat:exp -> incr:exp -> body:stmt list -> stmt listval mkFor : start:stmt list ->
guard:exp -> next:stmt list -> body:stmt list -> stmt listtype 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.tval partitionAttributes : default:attributeClass ->
attributes ->
attribute list * attribute list * attribute listval addAttribute : attribute -> attributes -> attributesval addAttributes : attribute list -> attributes -> attributesval dropAttribute : string -> attributes -> attributesval dropAttributes : string list -> attributes -> attributesval filterAttributes : string -> attributes -> attributesval hasAttribute : string -> attributes -> boolval typeAttrs : typ -> attribute listval setTypeAttrs : typ -> attributes -> typval typeAddAttributes : attribute list -> typ -> typval typeRemoveAttributes : string list -> typ -> typval expToAttrParam : exp -> attrparamexception 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 -> unitCil.visitCilFileSameGlobals if your visitor will
not change the list of globals.val visitCilFileSameGlobals : cilVisitor -> file -> unitCil.visitCilFile whenever appropriate because it is more efficient for
long files.val visitCilGlobal : cilVisitor -> global -> global listval visitCilFunction : cilVisitor -> fundec -> fundecval visitCilExpr : cilVisitor -> exp -> expval visitCilLval : cilVisitor -> lval -> lvalval visitCilOffset : cilVisitor -> offset -> offsetval visitCilInitOffset : cilVisitor -> offset -> offsetval visitCilInstr : cilVisitor -> instr -> instr listval visitCilStmt : cilVisitor -> stmt -> stmtval visitCilBlock : cilVisitor -> block -> blockval visitCilType : cilVisitor -> typ -> typval visitCilVarDecl : cilVisitor -> varinfo -> varinfoval visitCilInit : cilVisitor -> varinfo -> offset -> init -> initval visitCilAttributes : cilVisitor -> attribute list -> attribute listval msvcMode : bool refCil.initCIL.val useLogicalOperators : bool refval oldstyleExternInline : bool refval constFoldVisitor : bool -> cilVisitortype 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 refval print_CIL_Input : bool refval printCilAsIs : bool refval lineLength : int refval forgcc : string -> stringval currentLoc : location refval currentGlobal : global refPretty.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.docval d_thisloc : unit -> Pretty.docCil.currentLocval d_ikind : unit -> ikind -> Pretty.docval d_fkind : unit -> fkind -> Pretty.docval d_storage : unit -> storage -> Pretty.docval d_const : unit -> constant -> Pretty.docval derefStarLevel : intval indexLevel : intval arrowLevel : intval addrOfLevel : intval additiveLevel : intval comparativeLevel : intval bitwiseLevel : intval getParenthLevel : exp -> intclass type cilPrinter =object..end
class defaultCilPrinterClass :cilPrinter
val defaultCilPrinter : cilPrinterclass plainCilPrinterClass :cilPrinter
val plainCilPrinter : cilPrinterclass type descriptiveCilPrinter =object..end
class descriptiveCilPrinterClass :bool ->descriptiveCilPrinter
val descriptiveCilPrinter : descriptiveCilPrinterval printerForMaincil : cilPrinter refval printType : cilPrinter -> unit -> typ -> Pretty.docval printExp : cilPrinter -> unit -> exp -> Pretty.docval printLval : cilPrinter -> unit -> lval -> Pretty.docval printGlobal : cilPrinter -> unit -> global -> Pretty.docval printAttr : cilPrinter -> unit -> attribute -> Pretty.docval printAttrs : cilPrinter -> unit -> attributes -> Pretty.docval printInstr : cilPrinter -> unit -> instr -> Pretty.docval printStmt : cilPrinter -> unit -> stmt -> Pretty.docCil.dumpStmt
instead.val printBlock : cilPrinter -> unit -> block -> Pretty.docCil.dumpBlock
instead.val dumpStmt : cilPrinter -> out_channel -> int -> stmt -> unitCil.printStmt whenever possible.val dumpBlock : cilPrinter -> out_channel -> int -> block -> unitCil.printBlock whenever possible.val printInit : cilPrinter -> unit -> init -> Pretty.docCil.dumpInit
instead.val dumpInit : cilPrinter -> out_channel -> int -> init -> unitCil.printInit whenever possible.val d_type : unit -> typ -> Pretty.docCil.defaultCilPrinterval d_exp : unit -> exp -> Pretty.docCil.defaultCilPrinterval d_lval : unit -> lval -> Pretty.docCil.defaultCilPrinterval d_offset : Pretty.doc -> unit -> offset -> Pretty.docCil.defaultCilPrinter, given the pretty
printing for the base.val d_init : unit -> init -> Pretty.docCil.defaultCilPrinter. This can be
extremely slow (or even overflow the stack) for huge initializers. Use
Cil.dumpInit instead.val d_binop : unit -> binop -> Pretty.docval d_unop : unit -> unop -> Pretty.docval d_attr : unit -> attribute -> Pretty.docCil.defaultCilPrinterval d_attrparam : unit -> attrparam -> Pretty.docCil.defaultCilPrinterval d_attrlist : unit -> attributes -> Pretty.docCil.defaultCilPrinterval d_instr : unit -> instr -> Pretty.docCil.defaultCilPrinterval d_label : unit -> label -> Pretty.docCil.defaultCilPrinterval d_stmt : unit -> stmt -> Pretty.docCil.defaultCilPrinter. This can be
extremely slow (or even overflow the stack) for huge statements. Use
Cil.dumpStmt instead.val d_block : unit -> block -> Pretty.docCil.defaultCilPrinter. This can be
extremely slow (or even overflow the stack) for huge blocks. Use
Cil.dumpBlock instead.val d_global : unit -> global -> Pretty.docCil.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.docval dn_lval : unit -> lval -> Pretty.docval dn_init : unit -> init -> Pretty.docval dn_type : unit -> typ -> Pretty.docval dn_global : unit -> global -> Pretty.docval dn_attrlist : unit -> attributes -> Pretty.docval dn_attr : unit -> attribute -> Pretty.docval dn_attrparam : unit -> attrparam -> Pretty.docval dn_stmt : unit -> stmt -> Pretty.docval dn_instr : unit -> instr -> Pretty.docval d_shortglobal : unit -> global -> Pretty.docval dumpGlobal : cilPrinter -> out_channel -> global -> unitval dumpFile : cilPrinter -> out_channel -> string -> file -> unitErrormsg.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 -> 'aCil.error except that it explicitly takes a location argument,
instead of using the Cil.currentLocval warn : ('a, unit, Pretty.doc) format -> 'a
val warnOpt : ('a, unit, Pretty.doc) format -> 'aErrormsg.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 -> 'aErrormsg.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 -> 'aCil.warn except that it explicitly takes a location argument,
instead of using the Cil.currentLocval d_plainexp : unit -> exp -> Pretty.docval d_plaininit : unit -> init -> Pretty.docval d_plainlval : unit -> lval -> Pretty.docval d_plaintype : unit -> typ -> Pretty.docval 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.docval uniqueVarNames : file -> unitval peepHole2 : (instr * instr -> instr list option) -> stmt list -> unitval peepHole1 : (instr -> instr list option) -> stmt list -> unitpeepHole2 except that the optimization window consists of
one instruction, not twoexception SizeOfError of string * typ
val unsignedVersionOf : ikind -> ikindval signedVersionOf : ikind -> ikindval intRank : ikind -> intval commonIntKind : ikind -> ikind -> ikindval intKindForSize : int -> bool -> ikindval floatKindForSize : int -> fkindval bytesSizeOfInt : ikind -> intval bitsSizeOf : typ -> intCil.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 truncateCilint : ikind -> Cilint.cilint -> Cilint.cilint * Cilint.truncationval fitsInInt : ikind -> Cilint.cilint -> boolval intKindForValue : Cilint.cilint -> bool -> ikindval mkCilint : ikind -> int64 -> Cilint.cilintval sizeOf : typ -> expCil.initCIL.val alignOf_int : typ -> intCil.initCIL.val bitsOffset : typ -> offset -> int * intCil.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 refCil.initCILval little_endian : bool refCil.initCILval underscore_name : bool refCil.initCILval locUnknown : locationval get_instrLoc : instr -> locationval get_globalLoc : global -> locationval get_stmtLoc : stmtkind -> locationval dExp : Pretty.doc -> expCil.exp to be used in case of errors.val dInstr : Pretty.doc -> location -> instrCil.instr to be used in case of errors.val dGlobal : Pretty.doc -> location -> globalCil.global to be used in case of errors.val mapNoCopy : ('a -> 'a) -> 'a list -> 'a listval mapNoCopyList : ('a -> 'a list) -> 'a list -> 'a listval startsWith : string -> string -> boolval endsWith : string -> string -> boolval stripUnderscores : string -> stringtype 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.docval warnTruncate : bool refval envMachine : Machdep.mach option refval convertInts : int64 -> ikind -> int64 -> ikind -> int64 * int64 * ikindval isInteger : exp -> int64 optionval truncateInteger64 : ikind -> int64 -> int64 * boolval gccBuiltins : (string, typ * typ list * bool) Hashtbl.t
val msvcBuiltins : (string, typ * typ list * bool) Hashtbl.t