250 likes | 499 Views
STAL. David Walker (joint work with Karl Crary, Neal Glew and Greg Morrisett) http://www.cs.cornell.edu/home/walker/talnet/tal.html. Compiling With Typed ILs [Flint, GHC, TIL(T), ...]. Terms. Types. Source. IL. Machine. TIL Advantages. Security (JVM) Optimization (unboxing)
E N D
STAL David Walker (joint work with Karl Crary, Neal Glew and Greg Morrisett) http://www.cs.cornell.edu/home/walker/talnet/tal.html
Compiling With Typed ILs [Flint, GHC, TIL(T), ...] Terms Types Source IL Machine
TIL Advantages • Security (JVM) • Optimization (unboxing) • Proofs of Correctness (closure conversion) • Semantics (Harper & Stone) • Debugging (TIL) • Explicit Compiler Invariants
The Gap Terms Types Source IL Register Allocation Instruction Selection Instruction Scheduling Low level Optimization Machine
TAL Advantages • Security, Optimization, Proofs • Debugging, Semantics, and Invariants Terms Types Source IL Machine
Outline • Front-end: What is TAL? • Middle-end: Adding Stacks • Back-end: Typed Code Generation
TAL Instructions • standard RISC: mov, ld, st, add, jmp, beq … • few macros: malloc r1[1, …, n] • type annotations: unpack [, r1], r1
TAL Types • ints and other base types • tuples with initialization flags: • polymorphic code types: • existential types: <int0, int1> [].{ r1:, r2:int, r3:{r1: } } .<[].{r1:}1, 1>
TAL Example: Sum % sum: r1 + 1 + 2 + ... + r2 % r1: Accumulator % r2: Counter % r3: Continuation sum: { r1:int, r2:int, r3:{r1:int} } beq r2, r3 % if r2 = 0, jump to cont. add r1, r2 % r1 := r1 + r2 sub r2, 1 % decrement counter jmp sum % iterate loop
TAL Example: Mkpair mkpair: { r1:int, r2:{r1:<int1, int1>} } malloc r3[int, int] % r3:<int0, int0> st r3[0], r1 % r3:<int1, int0> st r3[1], r1 % r3:<int1, int1> mov r1, r3 jmp r2 % jump to cont. call site: { r2:{r1:<int1, int1>}, r5: <int1, int1, int1> } mov r1, 17 jmp mkpair
renv Heap-Allocated Environments mkpair: [].{ r1:int, r2:{r1:<int1,int1>, renv :}, renv: } call site: malloc renv[3, ..., n] st renv[0], r3 ... st renv[n], rn jmp mkpair[<31, ..., n1>]
simple, efficient 1st-class continuations better environment sharing unified memory management better locality benefits from hardware bias GC-independent Stack- vs Heap-Allocation Heaps Stacks
STAL • new dedicated register: sp • stack types: • instructions: • uninitialized stack slots have nonsense type (ns) := | nil | :: salloc n | sfree n | sld r, sp[i] | sst sp[i], r
STAL Example: Mkpair mkpair: [].{ sp:, r1:int, r2:{sp:int::int::} } salloc 2 % sp: ns::ns:: sst sp[0], r1 % sp: int::ns:: sst sp[1], r1 % sp: int::int:: jmp r2 % jump to cont.
STAL Example: Sum % accumulator: on stack % counter: in r1 % return address: in r2 sum: [].{ sp:int::, r1:int, r2:{sp:int::} } beq r1, r2 % if r1 = 0, jump to cont. sld r2, sp[0] % load from stack add r2, r1 % r2 := r2 + r1 sst sp[0], r2 % store to stack sub r1, 1 % decrement counter jmp sum[]% iterate loop
sp : int : 2 . . . : n ’ . . . Sum Example Cont’d sum: [].{ sp:int::, r1:int, r2:{sp:int::} } call site: [’].{ sp:’, r1:int, r2:{sp:int::2:: ... ::n::’} } salloc n sst sp[1], r2 ... sst sp[k], rn % k = n-1 sst sp[0], 0 % accumulator jmp sum[2:: ... ::n::’]
Key Points • Code types specify stack state • Code can be stack-polymorphic • Abstract stack type variables protect the caller’s stack from the callee • Stack-based code passes continuations
sp renv Stack- vs. Heap-Allocated Activation Records • Stack-allocated activation records: • Heap-allocated activation records: [].{ r1:int, r2:{r1:int, sp:}, sp: } [].{ r1:int, r2:{r1:int, renv:}, renv: }
Calling Conventions • Caller boxes continuation: • Multiple continuations: [].{ r1:int, r2:<{r1:, r2:int}1, 1> } [,].{ r1:int, rret:<{r1:, r2:int}1, 1>, rexn:<{r1:, r2:int}1, 1> }
More Calling Conventions • Closed function type: • Stack-Based Calling Conventions: C: [].{ sp:{r1:int, sp:char::}::char:: } Pascal/Win32: [].{ sp:{r1:int, sp:}::char:: } KML: ... char int
Simple Stacks Compound Stacks sp : 1 ::2 Restricted Stack Pointers r3 : ptr(::2) Efficient exceptions, displays, ... Not & The Paper
Implementation KML F-omega++ Scheme-- Popcorn Additional Contributers: Chris Hawblitzel Fred Smith Stephanie Weirich Steve Zdancewic STALx86
Summary • we can type both stacks and heaps • types can specify code generation invariants • types explain connections between different compilation strategies
• • • • • • Stack Allocated Data sp -4 1 17 r3 [1, 2]. {sp: (int::1) (int::int::2 ), r3: ptr(int::int::2 )} 5 2
PCC 1st-order predicate logic LF type checking of embedded proofs Low-level abstractions (addr, read, write, ...) TAL Higher-order type theory Type checking of assembly language objects directly High-level abstractions (, , <1, ...,1>, ...) PCC vs TAL • Use logic to build enforceable abstractions on • top of machine language • Admit almost all optimizations