Implements (extended) λPure and λRc proposed in the article "Counting Immutable Beans", Sebastian Ullrich and Leonardo de Moura.
The Lean to IR transformation produces λPure code, and this part is implemented in C++. The procedures described in the paper above are implemented in Lean.
Equations
- Lean.IR.instInhabitedVarId = { default := { idx := default } }
Equations
- Lean.IR.instInhabitedJoinPointId = { default := { idx := default } }
Equations
- Lean.IR.Index.lt a b = decide (a < b)
Equations
- Lean.IR.instBEqVarId = { beq := fun a b => a.idx == b.idx }
Equations
- Lean.IR.instToStringVarId = { toString := fun a => "x_" ++ toString a.idx }
Equations
- Lean.IR.instToFormatVarId = { format := fun a => Std.Format.text (toString a) }
Equations
- Lean.IR.instHashableVarId = { hash := fun a => hash a.idx }
Equations
- Lean.IR.instBEqJoinPointId = { beq := fun a b => a.idx == b.idx }
Equations
- Lean.IR.instToStringJoinPointId = { toString := fun a => "block_" ++ toString a.idx }
Equations
- Lean.IR.instToFormatJoinPointId = { format := fun a => Std.Format.text (toString a) }
Equations
- Lean.IR.instHashableJoinPointId = { hash := fun a => hash a.idx }
Equations
- Lean.IR.MData.empty = { entries := [] }
- float: Lean.IR.IRType
- uint8: Lean.IR.IRType
- uint16: Lean.IR.IRType
- uint32: Lean.IR.IRType
- uint64: Lean.IR.IRType
- usize: Lean.IR.IRType
- irrelevant: Lean.IR.IRType
- object: Lean.IR.IRType
- tobject: Lean.IR.IRType
- struct: Option Lean.Name → Array Lean.IR.IRType → Lean.IR.IRType
- union: Lean.Name → Array Lean.IR.IRType → Lean.IR.IRType
Low Level IR types. Most are self explanatory.
-
usize
represents the C++size_t
Type. We have it here because it is 32-bit in 32-bit machines, and 64-bit in 64-bit machines, and we want the C++ backend for our Compiler to generate platform independent code. -
irrelevant
for Lean types, propositions and proofs. -
object
a pointer to a value in the heap. -
tobject
a pointer to a value in the heap or tagged pointer (i.e., the least significant bit is 1) storing a scalar value. -
struct
andunion
are used to return small values (e.g.,Option
,Prod
,Except
) on the stack.
Remark: the RC operations for tobject
are slightly more expensive because we
first need to test whether the tobject
is really a pointer or not.
Remark: the Lean runtime assumes that sizeof(void*) == sizeof(sizeT). Lean cannot be compiled on old platforms where this is not True.
Since values of type struct
and union
are only used to return values,
We assume they must be used/consumed "linearly". We use the term "linear" here
to mean "exactly once" in each execution. That is, given x : S
, where S
is a struct,
then one of the following must hold in each (execution) branch.
1- x
occurs only at a single ret x
instruction. That is, it is being consumed by being returned.
2- x
occurs only at a single ctor
. That is, it is being "consumed" by being stored into another struct/union
.
3- We extract (aka project) every single field of x
exactly once. That is, we are consuming x
by consuming each
of one of its components. Minor refinement: we don't need to consume scalar fields or struct/union
fields that do not contain object fields.
Instances For
Equations
- Lean.IR.instInhabitedIRType = { default := Lean.IR.IRType.float }
Equations
- Lean.IR.IRType.instBEqIRType = { beq := Lean.IR.IRType.beq }
Equations
- One or more equations did not get rendered due to their size.
Equations
- Lean.IR.IRType.isObj x = match x with | Lean.IR.IRType.object => true | Lean.IR.IRType.tobject => true | x => false
Equations
- Lean.IR.IRType.isIrrelevant x = match x with | Lean.IR.IRType.irrelevant => true | x => false
Equations
- Lean.IR.IRType.isStruct x = match x with | Lean.IR.IRType.struct leanTypeName types => true | x => false
Equations
- Lean.IR.IRType.isUnion x = match x with | Lean.IR.IRType.union leanTypeName types => true | x => false
- var: Lean.IR.VarId → Lean.IR.Arg
- irrelevant: Lean.IR.Arg
Arguments to applications, constructors, etc.
We use irrelevant
for Lean types, propositions and proofs that have been erased.
Recall that for a Function f
, we also generate f._rarg
which does not take
irrelevant
arguments. However, f._rarg
is only safe to be used in full applications.
Instances For
Equations
- Lean.IR.instInhabitedArg = { default := Lean.IR.Arg.var default }
Equations
- Lean.IR.Arg.beq x x = match x, x with | Lean.IR.Arg.var x, Lean.IR.Arg.var y => x == y | Lean.IR.Arg.irrelevant, Lean.IR.Arg.irrelevant => true | x, x_1 => false
Equations
- Lean.IR.instBEqArg = { beq := Lean.IR.Arg.beq }
Equations
- Lean.IR.mkVarArg id = Lean.IR.Arg.var id
- num: Nat → Lean.IR.LitVal
- str: String → Lean.IR.LitVal
Instances For
Equations
- Lean.IR.LitVal.beq x x = match x, x with | Lean.IR.LitVal.num v₁, Lean.IR.LitVal.num v₂ => v₁ == v₂ | Lean.IR.LitVal.str v₁, Lean.IR.LitVal.str v₂ => v₁ == v₂ | x, x_1 => false
Equations
- Lean.IR.instBEqLitVal = { beq := Lean.IR.LitVal.beq }
Constructor information.
name
is the Name of the Constructor in Lean.cidx
is the Constructor index (aka tag).size
is the number of arguments of typeobject/tobject
.usize
is the number of arguments of typeusize
.ssize
is the number of bytes used to store scalar values.
Recall that a Constructor object contains a header, then a sequence of
pointers to other Lean objects, a sequence of USize
(i.e., size_t
)
scalar values, and a sequence of other scalar values.
Instances For
Equations
- Lean.IR.instReprCtorInfo = { reprPrec := Lean.IR.reprCtorInfo✝ }
Equations
- One or more equations did not get rendered due to their size.
Equations
- Lean.IR.instBEqCtorInfo = { beq := Lean.IR.CtorInfo.beq }
Equations
- ctor: Lean.IR.CtorInfo → Array Lean.IR.Arg → Lean.IR.Expr
We use
ctor
mainly for constructing Lean object/tobject valueslean_ctor_object
in the runtime. This instruction is also used to creatstruct
andunion
return values. Forunion
, onlyi.cidx
is relevant. Forstruct
,i
is irrelevant. - reset: Nat → Lean.IR.VarId → Lean.IR.Expr
- reuse: Lean.IR.VarId → Lean.IR.CtorInfo → Bool → Array Lean.IR.Arg → Lean.IR.Expr
reuse x in ctor_i ys
instruction in the paper. - proj: Nat → Lean.IR.VarId → Lean.IR.Expr
Extract the
tobject
value at Positionsizeof(void*)*i
fromx
. We also useproj
for extracting fields fromstruct
return values, and castingunion
return values. - uproj: Nat → Lean.IR.VarId → Lean.IR.Expr
Extract the
Usize
value at Positionsizeof(void*)*i
fromx
. - sproj: Nat → Nat → Lean.IR.VarId → Lean.IR.Expr
Extract the scalar value at Position
sizeof(void*)*n + offset
fromx
. - fap: Lean.IR.FunId → Array Lean.IR.Arg → Lean.IR.Expr
Full application.
- pap: Lean.IR.FunId → Array Lean.IR.Arg → Lean.IR.Expr
Partial application that creates a
pap
value (aka closure in our nonstandard terminology). - ap: Lean.IR.VarId → Array Lean.IR.Arg → Lean.IR.Expr
Application.
x
must be apap
value. - box: Lean.IR.IRType → Lean.IR.VarId → Lean.IR.Expr
Given
x : ty
wherety
is a scalar type, this operation returns a value of Typetobject
. For small scalar values, the Result is a tagged pointer, and no memory allocation is performed. - unbox: Lean.IR.VarId → Lean.IR.Expr
Given
x : [t]object
, obtain the scalar value. - lit: Lean.IR.LitVal → Lean.IR.Expr
- isTaggedPtr: Lean.IR.VarId → Lean.IR.Expr
Return
1 : uint8
Iffx : tobject
is a tagged pointer (storing a scalar value).
Instances For
Equations
- Lean.IR.mkCtorExpr n cidx size usize ssize ys = Lean.IR.Expr.ctor { name := n, cidx := cidx, size := size, usize := usize, ssize := ssize } ys
Equations
- Lean.IR.mkProjExpr i x = Lean.IR.Expr.proj i x
Equations
- Lean.IR.mkUProjExpr i x = Lean.IR.Expr.uproj i x
Equations
- Lean.IR.mkSProjExpr n offset x = Lean.IR.Expr.sproj n offset x
Equations
- Lean.IR.mkFAppExpr c ys = Lean.IR.Expr.fap c ys
Equations
- Lean.IR.mkPAppExpr c ys = Lean.IR.Expr.pap c ys
Equations
- Lean.IR.mkAppExpr x ys = Lean.IR.Expr.ap x ys
Equations
Equations
Equations
- Lean.IR.instInhabitedParam = { default := { x := default, borrow := default, ty := default } }
Equations
- Lean.IR.mkParam x borrow ty = { x := x, borrow := borrow, ty := ty }
- ctor: {FnBody : Type} → Lean.IR.CtorInfo → FnBody → Lean.IR.AltCore FnBody
- default: {FnBody : Type} → FnBody → Lean.IR.AltCore FnBody
Instances For
- vdecl: Lean.IR.VarId → Lean.IR.IRType → Lean.IR.Expr → Lean.IR.FnBody → Lean.IR.FnBody
let x : ty := e; b
- jdecl: Lean.IR.JoinPointId → Array Lean.IR.Param → Lean.IR.FnBody → Lean.IR.FnBody → Lean.IR.FnBody
Join point Declaration
block_j (xs) := e; b
- set: Lean.IR.VarId → Nat → Lean.IR.Arg → Lean.IR.FnBody → Lean.IR.FnBody
Store
y
at Positionsizeof(void*)*i
inx
.x
must be a Constructor object andRC(x)
must be 1. This operation is not part of λPure is only used during optimization. - setTag: Lean.IR.VarId → Nat → Lean.IR.FnBody → Lean.IR.FnBody
- uset: Lean.IR.VarId → Nat → Lean.IR.VarId → Lean.IR.FnBody → Lean.IR.FnBody
Store
y : Usize
at Positionsizeof(void*)*i
inx
.x
must be a Constructor object andRC(x)
must be 1. - sset: Lean.IR.VarId → Nat → Nat → Lean.IR.VarId → Lean.IR.IRType → Lean.IR.FnBody → Lean.IR.FnBody
Store
y : ty
at Positionsizeof(void*)*i + offset
inx
.x
must be a Constructor object andRC(x)
must be 1.ty
must not beobject
,tobject
,irrelevant
norUsize
. - inc: Lean.IR.VarId → Nat → Bool → Bool → Lean.IR.FnBody → Lean.IR.FnBody
RC increment for
object
. If c ==true
, theninc
must check whetherx
is a tagged pointer or not. Ifpersistent == true
thenx
is statically known to be a persistent object. - dec: Lean.IR.VarId → Nat → Bool → Bool → Lean.IR.FnBody → Lean.IR.FnBody
RC decrement for
object
. If c ==true
, theninc
must check whetherx
is a tagged pointer or not. Ifpersistent == true
thenx
is statically known to be a persistent object. - del: Lean.IR.VarId → Lean.IR.FnBody → Lean.IR.FnBody
- mdata: Lean.IR.MData → Lean.IR.FnBody → Lean.IR.FnBody
- case: Lean.Name → Lean.IR.VarId → Lean.IR.IRType → Array (Lean.IR.AltCore Lean.IR.FnBody) → Lean.IR.FnBody
- ret: Lean.IR.Arg → Lean.IR.FnBody
- jmp: Lean.IR.JoinPointId → Array Lean.IR.Arg → Lean.IR.FnBody
Jump to join point
j
- unreachable: Lean.IR.FnBody
Instances For
Equations
- Lean.IR.instInhabitedFnBody = { default := Lean.IR.FnBody.unreachable }
Equations
- Lean.IR.mkVDecl x ty e b = Lean.IR.FnBody.vdecl x ty e b
Equations
- Lean.IR.mkJDecl j xs v b = Lean.IR.FnBody.jdecl j xs v b
Equations
- Lean.IR.mkUSet x i y b = Lean.IR.FnBody.uset x i y b
Equations
- Lean.IR.mkSSet x i offset y ty b = Lean.IR.FnBody.sset x i offset y ty b
Equations
- Lean.IR.mkCase tid x cs = Lean.IR.FnBody.case tid x Lean.IR.IRType.object cs
Equations
Equations
- Lean.IR.mkJmp j ys = Lean.IR.FnBody.jmp j ys
Equations
Equations
- Lean.IR.Alt.ctor = Lean.IR.AltCore.ctor
Equations
- Lean.IR.Alt.default = Lean.IR.AltCore.default
Equations
- Lean.IR.instInhabitedAlt = { default := Lean.IR.Alt.default default }
Equations
- One or more equations did not get rendered due to their size.
Equations
- One or more equations did not get rendered due to their size.
Equations
- One or more equations did not get rendered due to their size.
If b is a non terminal, then return a pair (c, b')
s.t. b == c <;> b'
,
and c.body == FnBody.nil
Equations
- Lean.IR.FnBody.split b = let b' := Lean.IR.FnBody.body b; let c := Lean.IR.FnBody.resetBody b; (c, b')
Equations
- Lean.IR.AltCore.body x = match x with | Lean.IR.AltCore.ctor info b => b | Lean.IR.AltCore.default b => b
Equations
- Lean.IR.AltCore.setBody x x = match x, x with | Lean.IR.AltCore.ctor c b, b_1 => Lean.IR.Alt.ctor c b_1 | Lean.IR.AltCore.default b, b_1 => Lean.IR.Alt.default b_1
Equations
- Lean.IR.AltCore.modifyBody f x = match x with | Lean.IR.AltCore.ctor c b => Lean.IR.Alt.ctor c (f b) | Lean.IR.AltCore.default b => Lean.IR.Alt.default (f b)
Equations
- Lean.IR.AltCore.mmodifyBody f x = match x with | Lean.IR.AltCore.ctor c b => Lean.IR.Alt.ctor c <$> f b | Lean.IR.AltCore.default b => Lean.IR.Alt.default <$> f b
Equations
- Lean.IR.Alt.isDefault x = match x with | Lean.IR.AltCore.ctor info b => false | Lean.IR.AltCore.default b => true
Equations
- Lean.IR.push bs b = let b := Lean.IR.FnBody.resetBody b; Array.push bs b
Equations
Equations
- Lean.IR.reshape bs term = Lean.IR.reshapeAux bs (Array.size bs) term
Equations
- Lean.IR.modifyJPs bs f = Array.map (fun b => match b with | Lean.IR.FnBody.jdecl j xs v k => Lean.IR.FnBody.jdecl j xs (f v) k | other => other) bs
Equations
- One or more equations did not get rendered due to their size.
Equations
- Lean.IR.mkAlt n cidx size usize ssize b = Lean.IR.Alt.ctor { name := n, cidx := cidx, size := size, usize := usize, ssize := ssize } b
If
some
, then declaration depends on
which uses asorry
axiom.
Extra information associated with a declaration.
Instances For
- fdecl: Lean.IR.FunId → Array Lean.IR.Param → Lean.IR.IRType → Lean.IR.FnBody → Lean.IR.DeclInfo → Lean.IR.Decl
- extern: Lean.IR.FunId → Array Lean.IR.Param → Lean.IR.IRType → Lean.ExternAttrData → Lean.IR.Decl
Instances For
Equations
- Lean.IR.instInhabitedDecl = { default := Lean.IR.Decl.extern default default default default }
Equations
- Lean.IR.Decl.name x = match x with | Lean.IR.Decl.fdecl f xs type body info => f | Lean.IR.Decl.extern f xs type ext => f
Equations
- Lean.IR.Decl.params x = match x with | Lean.IR.Decl.fdecl f xs type body info => xs | Lean.IR.Decl.extern f xs type ext => xs
Equations
- Lean.IR.Decl.resultType x = match x with | Lean.IR.Decl.fdecl f xs t body info => t | Lean.IR.Decl.extern f xs t ext => t
Equations
- Lean.IR.Decl.isExtern x = match x with | Lean.IR.Decl.extern f xs type ext => true | x => false
Equations
- Lean.IR.Decl.getInfo x = match x with | Lean.IR.Decl.fdecl f xs type body info => info | x => { sorryDep? := none }
Equations
- One or more equations did not get rendered due to their size.
Equations
- Lean.IR.mkDecl f xs ty b = Lean.IR.Decl.fdecl f xs ty b { sorryDep? := none }
Equations
- Lean.IR.mkExternDecl f xs ty e = Lean.IR.Decl.extern f xs ty e
Equations
- Lean.IR.mkDummyExternDecl f xs ty = Lean.IR.Decl.fdecl f xs ty Lean.IR.FnBody.unreachable { sorryDep? := none }
Set of variable and join point names
Equations
- Lean.IR.IndexSet = Lean.RBTree Lean.IR.Index compare
Equations
- Lean.IR.instInhabitedIndexSet = { default := ∅ }
Equations
- Lean.IR.mkIndexSet idx = Lean.RBTree.insert Lean.RBTree.empty idx
- param: Lean.IR.IRType → Lean.IR.LocalContextEntry
- localVar: Lean.IR.IRType → Lean.IR.Expr → Lean.IR.LocalContextEntry
- joinPoint: Array Lean.IR.Param → Lean.IR.FnBody → Lean.IR.LocalContextEntry
Instances For
Equations
Equations
- Lean.IR.LocalContext.addLocal ctx x t v = Lean.RBMap.insert ctx x.idx (Lean.IR.LocalContextEntry.localVar t v)
Equations
- Lean.IR.LocalContext.addJP ctx j xs b = Lean.RBMap.insert ctx j.idx (Lean.IR.LocalContextEntry.joinPoint xs b)
Equations
- Lean.IR.LocalContext.addParam ctx p = Lean.RBMap.insert ctx p.x.idx (Lean.IR.LocalContextEntry.param p.ty)
Equations
- Lean.IR.LocalContext.addParams ctx ps = Array.foldl Lean.IR.LocalContext.addParam ctx ps 0 (Array.size ps)
Equations
- Lean.IR.LocalContext.isJP ctx idx = match Lean.RBMap.find? ctx idx with | some (Lean.IR.LocalContextEntry.joinPoint a a_1) => true | x => false
Equations
- Lean.IR.LocalContext.getJPBody ctx j = match Lean.RBMap.find? ctx j.idx with | some (Lean.IR.LocalContextEntry.joinPoint a b) => some b | x => none
Equations
- Lean.IR.LocalContext.getJPParams ctx j = match Lean.RBMap.find? ctx j.idx with | some (Lean.IR.LocalContextEntry.joinPoint ys a) => some ys | x => none
Equations
- Lean.IR.LocalContext.isParam ctx idx = match Lean.RBMap.find? ctx idx with | some (Lean.IR.LocalContextEntry.param a) => true | x => false
Equations
- Lean.IR.LocalContext.isLocalVar ctx idx = match Lean.RBMap.find? ctx idx with | some (Lean.IR.LocalContextEntry.localVar a a_1) => true | x => false
Equations
- Lean.IR.LocalContext.contains ctx idx = Lean.RBMap.contains ctx idx
Equations
- Lean.IR.LocalContext.eraseJoinPointDecl ctx j = Lean.RBMap.erase ctx j.idx
Equations
- One or more equations did not get rendered due to their size.
Equations
- Lean.IR.LocalContext.getValue ctx x = match Lean.RBMap.find? ctx x.idx with | some (Lean.IR.LocalContextEntry.localVar a v) => some v | x => none
Equations
Equations
- Lean.IR.VarId.alphaEqv ρ v₁ v₂ = match Lean.RBMap.find? ρ v₁.idx with | some v => v == v₂.idx | none => v₁ == v₂
Equations
- Lean.IR.instAlphaEqvVarId = { aeqv := Lean.IR.VarId.alphaEqv }
Equations
- Lean.IR.Arg.alphaEqv ρ x x = match x, x with | Lean.IR.Arg.var v₁, Lean.IR.Arg.var v₂ => Lean.IR.aeqv ρ v₁ v₂ | Lean.IR.Arg.irrelevant, Lean.IR.Arg.irrelevant => true | x, x_1 => false
Equations
- Lean.IR.instAlphaEqvArg = { aeqv := Lean.IR.Arg.alphaEqv }
Equations
- Lean.IR.args.alphaEqv ρ args₁ args₂ = Array.isEqv args₁ args₂ fun a b => Lean.IR.aeqv ρ a b
Equations
- Lean.IR.instAlphaEqvArrayArg = { aeqv := Lean.IR.args.alphaEqv }
Equations
- One or more equations did not get rendered due to their size.
Equations
- Lean.IR.instAlphaEqvExpr = { aeqv := Lean.IR.Expr.alphaEqv }
Equations
- Lean.IR.addVarRename ρ x₁ x₂ = if (x₁ == x₂) = true then ρ else Lean.RBMap.insert ρ x₁ x₂
Equations
- Lean.IR.addParamRename ρ p₁ p₂ = if (p₁.ty == p₂.ty && decide (p₁.borrow = p₂.borrow)) = true then some (Lean.IR.addVarRename ρ p₁.x.idx p₂.x.idx) else none
Equations
- One or more equations did not get rendered due to their size.
Equations
- Lean.IR.FnBody.beq b₁ b₂ = Lean.IR.FnBody.alphaEqv ∅ b₁ b₂
Equations
- Lean.IR.instBEqFnBody = { beq := Lean.IR.FnBody.beq }
Equations
- Lean.IR.VarIdSet = Lean.RBTree Lean.IR.VarId fun x y => compare x.idx y.idx
Equations
- Lean.IR.instInhabitedVarIdSet = { default := ∅ }
Equations
- One or more equations did not get rendered due to their size.
Equations
- One or more equations did not get rendered due to their size.