High-Level Abstractions for Low-Level Programming Iavor Sotirov Diatchki M.Sc. Computer Science, OGI School of Science & Engineering at Oregon Health & Science University (2007) B.Sc. Mathematics and Computer Science, University of Cape Town (1999) A dissertation presented to the faculty of the OGI School of Science & Engineering at Oregon Health & Science University in partial fulfillment of the requirements for the degree Doctor of Philosophy in Computer Science May 2007 The dissertation “High-Level Abstractions for Low-Level Programming” by Iavor Sotirov Diatchki has been examined and approved by the following Examination Committee: Dr. Mark P. Jones, Associate Professor Dept. of Computer Science and Engineering Thesis Research Adviser Dr. Andrew Tolmach, Associate Professor Dept. of Computer Science Portland State University Dr. Greg Morrisett, Professor Division of Engineering and Applied Science Harvard University Dr. Peter A. Heeman, Assistant Professor Dept. of Computer Science and Engineering ii Acknowledgments The writing of this dissertation would not have been possible without the helpofmanypeople, andIwouldliketothankallofthemfortheircontinuous support. In particular: - Many thanks to my family—my mum, my dad, and my sister—for always believing in me, and for exposing me to the world. - Special thanks to my advisor, Mark P. Jones, whose help and guidance have been invaluable, and are really appreciated. I am looking forward to many future collaborations! - Thanks to all my friends in Portland for their support, and for remind- ing me to have fun. - Last but not least, many thanks to the faculty and staff at OGI for creating an excellent research environment, and for always being ready to help. This work was supported, in part, by the National Science Foundation award number 0205737, “ITR: Advanced Programming Languages for Em- bedded Systems.” iii iv Contents 1 Introduction 1 1.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.2 Systems Programming . . . . . . . . . . . . . . . . . . . . . . 2 1.2.1 Bitdata . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.2.2 Memory Areas . . . . . . . . . . . . . . . . . . . . . . 6 1.3 Working with Low-Level Data . . . . . . . . . . . . . . . . . . 9 1.3.1 Bit Twiddling . . . . . . . . . . . . . . . . . . . . . . . 9 1.3.2 Low-level Representations for Bitdata . . . . . . . . . . 11 1.3.3 External Specifications . . . . . . . . . . . . . . . . . . 13 1.4 This Dissertation . . . . . . . . . . . . . . . . . . . . . . . . . 14 I Background and Related Work 19 2 Related Work 21 2.1 Imperative Languages . . . . . . . . . . . . . . . . . . . . . . 21 2.2 Functional Languages . . . . . . . . . . . . . . . . . . . . . . . 25 2.3 Domain Specific Languages . . . . . . . . . . . . . . . . . . . 29 2.4 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 3 Background: Type Systems 33 3.1 The λ-calculus . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 3.2 Hindley-Milner Polymorphism . . . . . . . . . . . . . . . . . . 36 3.3 Qualified Types . . . . . . . . . . . . . . . . . . . . . . . . . . 37 3.3.1 Overloading in Haskell . . . . . . . . . . . . . . . . . . 40 3.4 Improvement . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 3.4.1 Functional Dependencies . . . . . . . . . . . . . . . . . 43 3.5 Using Kinds . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 v 3.6 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 4 Natural Number Types 49 4.1 Basic Axioms . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 4.2 Computation With Improvement . . . . . . . . . . . . . . . . 51 4.3 Rules for Equality . . . . . . . . . . . . . . . . . . . . . . . . . 52 4.3.1 Expressiveness of the System . . . . . . . . . . . . . . 53 4.4 Other Operations . . . . . . . . . . . . . . . . . . . . . . . . . 55 4.4.1 Predicate Synonyms . . . . . . . . . . . . . . . . . . . 55 5 Notation for Functional Predicates 57 5.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 5.2 Type Signatures and Instances . . . . . . . . . . . . . . . . . . 59 5.3 Contexts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 5.4 Type Synonyms . . . . . . . . . . . . . . . . . . . . . . . . . . 63 5.4.1 Type Synonyms with Contexts . . . . . . . . . . . . . 65 5.5 Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 5.5.1 Constructor Contexts . . . . . . . . . . . . . . . . . . . 67 5.5.2 Storing Evidence . . . . . . . . . . . . . . . . . . . . . 68 5.6 Associated Type Synonyms . . . . . . . . . . . . . . . . . . . 70 5.7 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 6 A Calculus for Definitions 73 6.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 6.2 Matches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 6.3 Qualifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 6.4 Patterns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 6.5 Expressions and Declarations . . . . . . . . . . . . . . . . . . 81 6.5.1 Simplifying Function Definitions . . . . . . . . . . . . . 82 6.5.2 Pattern Bindings . . . . . . . . . . . . . . . . . . . . . 84 6.6 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 II Language Design 87 7 Working With Bitdata 89 7.1 Overview of the Approach . . . . . . . . . . . . . . . . . . . . 90 7.2 Bit Vectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 vi 7.2.1 Literals . . . . . . . . . . . . . . . . . . . . . . . . . . 94 7.2.2 Joining and Splitting Bit Vectors . . . . . . . . . . . . 96 7.2.3 Semantics of the (#) Pattern . . . . . . . . . . . . . . 98 7.3 User-Defined Bitdata . . . . . . . . . . . . . . . . . . . . . . . 99 7.3.1 Constructors . . . . . . . . . . . . . . . . . . . . . . . 100 7.3.2 Product Types . . . . . . . . . . . . . . . . . . . . . . 102 7.3.3 The ‘as’ Clause . . . . . . . . . . . . . . . . . . . . . . 104 7.3.4 The ‘if’ Clause . . . . . . . . . . . . . . . . . . . . . . 107 7.4 Bitdata and Bit Vectors . . . . . . . . . . . . . . . . . . . . . 109 7.4.1 Conversion Functions . . . . . . . . . . . . . . . . . . . 109 7.4.2 Instances for ‘BitRep’ and ‘BitData’ . . . . . . . . . . 110 7.4.3 The Type of ‘fromBits’ . . . . . . . . . . . . . . . . . . 112 7.5 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 8 Static Analysis of Bitdata 117 8.1 Junk and Confusion! . . . . . . . . . . . . . . . . . . . . . . . 117 8.2 Checking Bitdata Declarations . . . . . . . . . . . . . . . . . . 120 8.2.1 ‘as’ clauses . . . . . . . . . . . . . . . . . . . . . . . . . 121 8.2.2 ‘if’ clauses . . . . . . . . . . . . . . . . . . . . . . . . . 123 8.2.3 Working with Sets of Bit Vectors . . . . . . . . . . . . 124 8.3 Checking Function Declarations . . . . . . . . . . . . . . . . . 130 8.3.1 The Language . . . . . . . . . . . . . . . . . . . . . . . 130 8.3.2 The Logic . . . . . . . . . . . . . . . . . . . . . . . . . 131 8.3.3 The Algorithm . . . . . . . . . . . . . . . . . . . . . . 132 8.3.4 Unreachable Definitions . . . . . . . . . . . . . . . . . 133 8.3.5 Simplifying Conditions . . . . . . . . . . . . . . . . . . 134 8.4 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 9 Memory Areas 137 9.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 9.1.1 Our Approach: Strongly Typed Memory Areas . . . . 139 9.2 Describing Memory Areas . . . . . . . . . . . . . . . . . . . . 141 9.3 References and Pointers . . . . . . . . . . . . . . . . . . . . . 143 9.3.1 Relations to Bitdata . . . . . . . . . . . . . . . . . . . 145 9.3.2 Manipulating Memory . . . . . . . . . . . . . . . . . . 146 9.4 Representations of Stored Values . . . . . . . . . . . . . . . . 148 9.5 Area Declarations . . . . . . . . . . . . . . . . . . . . . . . . . 150 9.5.1 External Areas . . . . . . . . . . . . . . . . . . . . . . 153 vii 9.6 Alternative Design Choices . . . . . . . . . . . . . . . . . . . . 154 9.6.1 Initialization . . . . . . . . . . . . . . . . . . . . . . . . 154 9.6.2 Dynamic Areas . . . . . . . . . . . . . . . . . . . . . . 157 9.7 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 10 Structures and Arrays 159 10.1 User Defined Structures . . . . . . . . . . . . . . . . . . . . . 159 10.1.1 Accessing Fields . . . . . . . . . . . . . . . . . . . . . . 160 10.1.2 Alignment . . . . . . . . . . . . . . . . . . . . . . . . . 161 10.1.3 Padding . . . . . . . . . . . . . . . . . . . . . . . . . . 164 10.2 Working with Arrays . . . . . . . . . . . . . . . . . . . . . . . 165 10.2.1 Index Operations . . . . . . . . . . . . . . . . . . . . . 166 10.2.2 Iterating over Arrays . . . . . . . . . . . . . . . . . . . 167 10.2.3 Related Work . . . . . . . . . . . . . . . . . . . . . . . 169 10.3 Casting Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . 172 10.3.1 Arrays of Bytes . . . . . . . . . . . . . . . . . . . . . . 173 10.3.2 Reindexing Operations . . . . . . . . . . . . . . . . . . 174 10.4 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178 III Examples and Implementation 181 11 Example: Fragments of a Kernel 183 11.1 A Text Console Driver . . . . . . . . . . . . . . . . . . . . . . 183 11.2 Overview of IA-32 . . . . . . . . . . . . . . . . . . . . . . . . . 188 11.3 Segments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189 11.3.1 Segment Selectors . . . . . . . . . . . . . . . . . . . . . 189 11.3.2 Segment Descriptors . . . . . . . . . . . . . . . . . . . 190 11.3.3 Task-State Segment . . . . . . . . . . . . . . . . . . . . 193 11.4 Interrupts and Exceptions . . . . . . . . . . . . . . . . . . . . 194 11.5 User Mode Execution . . . . . . . . . . . . . . . . . . . . . . . 195 11.6 Paging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198 11.7 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202 12 Implementation 203 12.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203 12.2 Computation Values . . . . . . . . . . . . . . . . . . . . . . . 204 12.3 Representations for Bitdata . . . . . . . . . . . . . . . . . . . 213 viii 12.4 Run Time System . . . . . . . . . . . . . . . . . . . . . . . . . 216 12.4.1 Calling Convention . . . . . . . . . . . . . . . . . . . . 216 12.4.2 Stack Frames . . . . . . . . . . . . . . . . . . . . . . . 217 12.4.3 Traversing the Stack . . . . . . . . . . . . . . . . . . . 219 12.5 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 13 Conclusions and Future Work 223 13.1 Summary of Contributions . . . . . . . . . . . . . . . . . . . . 223 13.2 Future Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224 13.2.1 Parameterized Bitdata . . . . . . . . . . . . . . . . . . 225 13.2.2 Computed Bitfields . . . . . . . . . . . . . . . . . . . . 227 13.2.3 Views on Memory Areas . . . . . . . . . . . . . . . . . 231 13.2.4 Reference Fields . . . . . . . . . . . . . . . . . . . . . . 234 13.2.5 Implementation and Additional Evaluation . . . . . . . 237 ix x
Description: