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
CHAPTER 9. TYPE QUALIFIER INFERENCE 76 The function findColorNodes invokes the nodeColorFinder visitor on the le f with the graph g. let findColoredNodes (f : file) (g : graph) : unit = let vis = new nodeColorFinder g in visitCilFile vis f The function colors equal ensures that every color of c1 is somewhere in c2 and that every color of c2 is somewhere in c1. That is it checks that the lists have the same elements. let colors equal (c1 : colors) (c2 : colors) : bool = L.for all (fun c → L.mem c c2) c1 ∧ L.for all (fun c → L.mem c c1) c2 Now that the graph has been seeded by a few type qualiers, we can see where else in the graph they must ow. We'll accomplish this by doing the following. First, we put all the nodes in the graph into a queue. Then, for each node that we pop o the queue, we'll nd the least-upper-bound of the qualier on the node itself along with the qualiers on the nodes for incoming edges; these are the types that it must include. If the least-upper-bound qualier is dierent, we'll assign the new qualier to the node, and then add the nodes on outgoing edges to the end of the queue. When the qualier lattice has nite height, as it does here, we can be sure that the algorithm will terminate. The function enqueueNodes places each of the nodes in our graph on a queue and returns the queue. let enqueueNodes (g : graph) : int Q.t = let q = Q.create () in A.iteri (fun i → Q.add i q) g; q The function processNode folds over the incoming edges of a node, computing the least-upperbound of the types on the origin nodes. If the result is dierent from the starting type, it adds the new type to the graph and return true. Otherwise it returns false. let processNode (g : graph) (id : int) : bool = let c' = L.fold left (fun c id' → list union c g.(id').ncolors) g.(id).ncolors g.(id).incoming in if ¬(colors equal g.(id).ncolors c') then begin g.(id).ncolors ← c'; true end else false The function processQueue applies processNode to each node of the graph g on queue q. If processNode for some node returns true, it adds the destinations of the node's outgoing edges to the end of the queue.
CHAPTER 9. TYPE QUALIFIER INFERENCE 77 let processQueue (g : graph) (q : int Q.t) : unit = while ¬(Q.is empty q) do let id = Q.pop q in if processNode g id then begin L.iter (fun id' → Q.add id' q) g.(id).outgoing end done The function attr of color builds a new type attribute from the color c. let attr of color (c : T.color) : attribute = Attr(T.string of color c, [ ]) Once the inference algorithm is nished, we can add its results to the types in the program. If an inferred type qualier disagrees with one that the programmer has added explicitly, we keep the programmer's annotation, but issue a warning. The visitor colorAdder visits typ nodes in the AST. It reads the inferred color type using the typ's "Node" attribute, and adds it to the typ, respecting the above policy. class colorAdder (g : graph) = object(self) inherit nopCilVisitor method vtype (t : typ) = let oc = T.colors of type t in let ic = (t | > node of type | > A.get g).ncolors in if oc ≠ [ ] ∧ ¬(colors equal ic oc) then DoChildren else if list equal (=) ic oc then DoChildren else let nattr = L.map attr of color ic in ChangeTo (typeAddAttributes nattr t) end The function addInferredColors invokes the visitor colorAdder on the le f using the inference results in graph g. let addInferredColors (f : file) (g : graph) : unit = let vis = new colorAdder g in visitCilFile vis f Finally, we tie everything together with the function tut9, which is the entry point into the module. We must also remember to remove the node attributes we added for building the graph. We leave the inferred colors since these will need to be checked by a type-checking pass like the one in Chapter 7.
- Page 27 and 28: CHAPTER 3. DATAFLOW ANALYSIS 25 let
- Page 29 and 30: CHAPTER 3. DATAFLOW ANALYSIS 27 and
- Page 31 and 32: CHAPTER 3. DATAFLOW ANALYSIS 29 let
- Page 33 and 34: CHAPTER 3. DATAFLOW ANALYSIS 31 DoC
- Page 35 and 36: CHAPTER 3. DATAFLOW ANALYSIS 33 tes
- Page 37 and 38: References [1] Aws Albarghouthi, Ra
- Page 39 and 40: CHAPTER 4. INSTRUMENTATION 37 type
- Page 41 and 42: CHAPTER 4. INSTRUMENTATION 39 metho
- Page 43 and 44: CHAPTER 4. INSTRUMENTATION 41 $ cil
- Page 45 and 46: CHAPTER 5. INTERPRETED CONSTRUCTORS
- Page 47 and 48: CHAPTER 5. INTERPRETED CONSTRUCTORS
- Page 49 and 50: Chapter 6 Overriding Functions When
- Page 51 and 52: CHAPTER 6. OVERRIDING FUNCTIONS 49
- Page 53 and 54: References [1] Kumar Avijit, Pratee
- Page 55 and 56: CHAPTER 7. TYPE QUALIFIERS 53 let c
- Page 57 and 58: CHAPTER 7. TYPE QUALIFIERS 55 let w
- Page 59 and 60: CHAPTER 7. TYPE QUALIFIERS 57 $ cil
- Page 61 and 62: Chapter 8 Dependant Type Qualiers O
- Page 63 and 64: CHAPTER 8. DEPENDANT TYPE QUALIFIER
- Page 65 and 66: CHAPTER 8. DEPENDANT TYPE QUALIFIER
- Page 67 and 68: CHAPTER 8. DEPENDANT TYPE QUALIFIER
- Page 69 and 70: CHAPTER 8. DEPENDANT TYPE QUALIFIER
- Page 71 and 72: CHAPTER 8. DEPENDANT TYPE QUALIFIER
- Page 73 and 74: Chapter 9 Type Qualier Inference In
- Page 75 and 76: CHAPTER 9. TYPE QUALIFIER INFERENCE
- Page 77: CHAPTER 9. TYPE QUALIFIER INFERENCE
- Page 81 and 82: CHAPTER 9. TYPE QUALIFIER INFERENCE
- Page 83 and 84: Chapter 10 Adding a New Kind of Sta
- Page 85 and 86: CHAPTER 10. ADDING A NEW KIND OF ST
- Page 87 and 88: CHAPTER 10. ADDING A NEW KIND OF ST
- Page 89 and 90: CHAPTER 10. ADDING A NEW KIND OF ST
- Page 91 and 92: CHAPTER 10. ADDING A NEW KIND OF ST
- Page 93 and 94: Chapter 11 Program Verication In th
- Page 95 and 96: CHAPTER 11. PROGRAM VERIFICATION 93
- Page 97 and 98: CHAPTER 11. PROGRAM VERIFICATION 95
- Page 99 and 100: CHAPTER 11. PROGRAM VERIFICATION 97
- Page 101 and 102: CHAPTER 11. PROGRAM VERIFICATION 99
- Page 103 and 104: CHAPTER 11. PROGRAM VERIFICATION 10
- Page 105 and 106: CHAPTER 11. PROGRAM VERIFICATION 10
- Page 107 and 108: Chapter 12 Comments CIL has a very
- Page 109 and 110: CHAPTER 12. COMMENTS 107 let printC
- Page 111 and 112: References [1] Lin Tan, Ding Yuan,
- Page 113 and 114: CHAPTER 13. WHOLE-PROGRAM ANALYSIS
- Page 115 and 116: CHAPTER 13. WHOLE-PROGRAM ANALYSIS
- Page 117 and 118: CHAPTER 14. IMPLEMENTING A SIMPLE D
- Page 119 and 120: CHAPTER 14. IMPLEMENTING A SIMPLE D
- Page 121 and 122: CHAPTER 14. IMPLEMENTING A SIMPLE D
- Page 123 and 124: CHAPTER 14. IMPLEMENTING A SIMPLE D
- Page 125 and 126: CHAPTER 14. IMPLEMENTING A SIMPLE D
- Page 127 and 128: Chapter 15 Automated Test Generatio
CHAPTER 9. TYPE QUALIFIER INFERENCE 77<br />
let processQueue (g : graph) (q : int Q.t) : unit =<br />
while ¬(Q.is empty q) do<br />
let id = Q.pop q in<br />
if processNode g id then begin<br />
L.iter (fun id' → Q.add id' q) g.(id).outgoing<br />
end<br />
done<br />
The function attr <strong>of</strong> color builds a new type attribute from the color c.<br />
let attr <strong>of</strong> color (c : T.color) : attribute = Attr(T.string <strong>of</strong> color c, [ ])<br />
Once the inference algorithm is nished, we can add its results to the types in the program. If an<br />
inferred type qualier disagrees with one that the programmer has added explicitly, we keep the<br />
programmer's annotation, but issue a warning.<br />
The visitor colorAdder visits typ nodes in the AST. It reads the inferred color type using the<br />
typ's "Node" attribute, and adds it to the typ, respecting the above policy.<br />
class colorAdder (g : graph) = object(self)<br />
inherit nopCilVisitor<br />
method vtype (t : typ) =<br />
let oc = T.colors <strong>of</strong> type t in<br />
let ic = (t | > node <strong>of</strong> type | > A.get g).ncolors in<br />
if oc ≠ [ ] ∧ ¬(colors equal ic oc) then DoChildren<br />
else if list equal (=) ic oc then DoChildren else<br />
let nattr = L.map attr <strong>of</strong> color ic in<br />
ChangeTo (typeAddAttributes nattr t)<br />
end<br />
The function addInferredColors invokes the visitor colorAdder on the le f using the inference<br />
results in graph g.<br />
let addInferredColors (f : file) (g : graph) : unit =<br />
let vis = new colorAdder g in<br />
visitCilFile vis f<br />
Finally, we tie everything together with the function tut9, which is the entry point into the module.<br />
We must also remember to remove the node attributes we added for building the graph. We leave the<br />
inferred colors since these will need to be checked by a type-checking pass like the one in Chapter 7.