A CIL Tutorial - Department of Computer Science - ETH Zürich

A CIL Tutorial - Department of Computer Science - ETH Zürich A CIL Tutorial - Department of Computer Science - ETH Zürich

29.01.2014 Views

CHAPTER 8. DEPENDANT TYPE QUALIFIERS 66 let color includes (loc : location) (is this : color) (in this : color) : instr list = match is this, in this with | ExactRGB c1, ExactRGB c2 → [mkColorEqInst () loc c1 c2] | ExactRGB c1, LowerRGB c2 | LowerRGB c1, LowerRGB c2 → [mkColorLeInst () loc c2 c1] | ExactRGB c1, UpperRGB c2 | UpperRGB c1, UpperRGB c2 → [mkColorLeInst () loc c1 c2] | → E.error "%a: color inclusion test will always fail" d loc (!currentLoc); [ ] The function colors includes checks that every color of is this is included in every color of in this. Notice how the nested List.map functions perform this all-pairs check, and builds the resulting list of instructions with List.concat let colors includes (loc : location) (is this : colors) (in this : colors) : instr list = if (is this = [ ] ∧ in this ≠ [ ]) ∨ (is this ≠ [ ] ∧ in this = [ ]) then (∗ Either both have colors or neither do ∗) E.error "%a: color mismatch" d loc loc; L.concat ( L.map (fun c1 → L.concat(L.map (color includes loc c1) in this) ) is this ) 8.1.6 Type-checking Now, we can write the visitor that performs type-checking. First, we dene two functions that extract colors from lvals and exps using colors of type. The function colors of lval adds mappings to the context using context for struct in the case that lv accesses a structure eld. colors of exp rst checks whether the expression is for an lval, and if so uses colors of lval function. Otherwise it simply extracts the type of the expression and uses colors of type. let colors of lval (c : ctxt) (loc : location) (lv : lval) : colors = colors of type (context for struct c loc lv) loc (typeOfLval lv)

CHAPTER 8. DEPENDANT TYPE QUALIFIERS 67 let colors of exp (c : ctxt) (loc : location) (e : exp) : colors = match e with | Lval lv → colors of lval c loc lv | → colors of type c loc (typeOf e) colorCheckVisitor visits a function with a context c that contains mappings for the local variables and formal parameters. At assignments and function calls, it inserts function calls that the type of the destination lvalue or formal parameter includes the type of the right-hand-side or actual parameter. These instructions are inserted using self#queueInstr. This is yet another mechanism with which one can modify the AST. self#queueInstr can be called from any visitor method. Instructions queued up with self#queueInstr are dequeued (i.e. inserted) at the latest possible point before the AST node currently being visited. So, if we queue up an instruction while visiting an instruction, the new instruction will be inserted immediately before the one currently being visited. The case for checking function calls is ommitted because of its length, but it is a very useful pattern, and might help with one of the exercises from a previous chapter. class colorCheckVisitor (c : ctxt) = object(self) inherit nopCilVisitor method vinst (i : instr) = match i with | Set(lv, e, loc) → let lvc = colors of lval c loc lv in let ec = colors of exp c loc e in self#queueInstr (colors includes loc ec lvc); DoChildren | → DoChildren end The function checkColorTypes invokes the visitor colorCHeckVisitor on function fd using context c. let checkColorTypes (c : ctxt) (fd : fundec) (loc : location) : unit = let c = context for locals c fd in let vis = new colorCheckVisitor c in ignore(visitCilFunction vis fd) The function tut8 is the entry point to the code in this tutorial. It rst initializes our dynamic type-checking functions (tut8 init), then builds a global context for compiling type attributes (context for globals), performs the type-check, and nally erases the color attributes.

CHAPTER 8. DEPENDANT TYPE QUALIFIERS 66<br />

let color includes (loc : location)<br />

(is this : color) (in this : color)<br />

: instr list<br />

=<br />

match is this, in this with<br />

| ExactRGB c1, ExactRGB c2 → [mkColorEqInst () loc c1 c2]<br />

| ExactRGB c1, LowerRGB c2<br />

| LowerRGB c1, LowerRGB c2 → [mkColorLeInst () loc c2 c1]<br />

| ExactRGB c1, UpperRGB c2<br />

| UpperRGB c1, UpperRGB c2 → [mkColorLeInst () loc c1 c2]<br />

| → E.error "%a: color inclusion test will always fail" d loc (!currentLoc);<br />

[ ]<br />

The function colors includes checks that every color <strong>of</strong> is this is included in every color <strong>of</strong><br />

in this. Notice how the nested List.map functions perform this all-pairs check, and builds the<br />

resulting list <strong>of</strong> instructions with List.concat<br />

let colors includes (loc : location)<br />

(is this : colors) (in this : colors)<br />

: instr list<br />

=<br />

if (is this = [ ] ∧ in this ≠ [ ]) ∨ (is this ≠ [ ] ∧ in this = [ ]) then<br />

(∗ Either both have colors or neither do ∗)<br />

E.error "%a: color mismatch" d loc loc;<br />

L.concat (<br />

L.map (fun c1 →<br />

L.concat(L.map (color includes loc c1) in this)<br />

) is this<br />

)<br />

8.1.6 Type-checking<br />

Now, we can write the visitor that performs type-checking. First, we dene two functions that<br />

extract colors from lvals and exps using colors <strong>of</strong> type. The function colors <strong>of</strong> lval adds<br />

mappings to the context using context for struct in the case that lv accesses a structure eld.<br />

colors <strong>of</strong> exp rst checks whether the expression is for an lval, and if so uses colors <strong>of</strong> lval<br />

function. Otherwise it simply extracts the type <strong>of</strong> the expression and uses colors <strong>of</strong> type.<br />

let colors <strong>of</strong> lval (c : ctxt) (loc : location) (lv : lval) : colors =<br />

colors <strong>of</strong> type (context for struct c loc lv) loc (typeOfLval lv)

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!