chore(library/init/lean/ir/ssa_check): use format for error messages
This commit is contained in:
parent
9373133800
commit
00147df082
1 changed files with 13 additions and 24 deletions
|
|
@ -4,25 +4,19 @@ Released under Apache 2.0 license as described in the file LICENSE.
|
|||
Authors: Leonardo de Moura
|
||||
-/
|
||||
prelude
|
||||
import init.lean.ir.ir
|
||||
import init.lean.ir.ir init.lean.ir.format
|
||||
|
||||
namespace lean
|
||||
namespace ir
|
||||
/-
|
||||
SSA validator
|
||||
-/
|
||||
inductive ssa_error
|
||||
| already_defined (b : blockid) (x : var) -- variable `x` has already been defined at basic block `b`
|
||||
| undefined (b : blockid) (x : var) -- undefined variable `x` at basic block `b`
|
||||
| phi_multiple_entries (b : blockid) (x : var) (pred : blockid) -- `x := phi y_1 ... y_n` at basic block `b`, where there are `y_i` and `y_j` defined in the same basic block `pred`
|
||||
| phi_missing_predecessor (b : blockid) (x : var) -- `x := phi ys` has a missing predecessor at basic block `b`
|
||||
| no_block
|
||||
|
||||
@[reducible] def ssa_decl_m := except_t ssa_error (state_t var2blockid id)
|
||||
@[reducible] def ssa_decl_m := except_t format (state_t var2blockid id)
|
||||
|
||||
def var.declare_at (b : blockid) (x : var) : ssa_decl_m unit :=
|
||||
do m ← get,
|
||||
if m.contains x then throw (ssa_error.already_defined b x)
|
||||
if m.contains x then throw ("already defined " ++ to_fmt x)
|
||||
else put (m.insert x b)
|
||||
|
||||
def instr.declare_vars_at (b : blockid) : instr → ssa_decl_m unit
|
||||
|
|
@ -63,15 +57,15 @@ def decl.declare_vars : decl → ssa_decl_m unit
|
|||
as.mmap' (arg.declare_at b.id) >>
|
||||
b.declare_vars >>
|
||||
bs.mmap' block.declare_vars
|
||||
| (decl.defn _ []) := throw ssa_error.no_block
|
||||
| (decl.defn _ []) := throw "declaration must have at least one basic block"
|
||||
| _ := return ()
|
||||
|
||||
/- Generate the mapping from variable to blockid for the given declaration.
|
||||
This function assumes `d` is in SSA. -/
|
||||
def decl.var2blockid (d : decl) : except_t ssa_error id var2blockid :=
|
||||
def decl.var2blockid (d : decl) : except_t format id var2blockid :=
|
||||
run_state (d.declare_vars >> get) mk_var2blockid
|
||||
|
||||
@[reducible] def ssa_valid_m := except_t ssa_error (reader_t (var2blockid × block) (state_t var_set id))
|
||||
@[reducible] def ssa_valid_m := except_t format (reader_t (var2blockid × block) (state_t var_set id))
|
||||
|
||||
def read_var2blockid : ssa_valid_m var2blockid :=
|
||||
prod.fst <$> read
|
||||
|
|
@ -87,17 +81,14 @@ modify $ λ s, s.insert x
|
|||
def var.defined (x : var) : ssa_valid_m unit :=
|
||||
do s ← get,
|
||||
if s.contains x then return ()
|
||||
else do b ← read_block,
|
||||
throw (ssa_error.undefined b.id x)
|
||||
else throw ("undefined " ++ to_fmt x)
|
||||
|
||||
/- Given, x := phi ys,
|
||||
check whether every ys is declared at the var2blockid mapping,
|
||||
and update the set of already defined variables in the basic block with `x`. -/
|
||||
def phi.valid_ssa (p : phi) : ssa_valid_m unit :=
|
||||
do m ← read_var2blockid,
|
||||
p.ys.mmap' (λ y, if m.contains y then return ()
|
||||
else do b ← read_block,
|
||||
throw (ssa_error.undefined b.id y)),
|
||||
p.ys.mmap' $ λ y, unless (m.contains y) $ throw ("undefined " ++ to_fmt y),
|
||||
p.x.define
|
||||
|
||||
def instr.valid_ssa : instr → ssa_valid_m unit
|
||||
|
|
@ -133,10 +124,9 @@ p.ys.mfoldl (λ s y,
|
|||
do m ← read_var2blockid,
|
||||
match m.find y with
|
||||
| some bid := if s.contains bid
|
||||
then do b ← read_block,
|
||||
throw (ssa_error.phi_multiple_entries b.id p.x bid)
|
||||
then throw ("multiple predecessors at '" ++ to_fmt p ++ "'")
|
||||
else return $ (s.insert bid)
|
||||
| none := do b ← read_block, throw (ssa_error.undefined b.id y))
|
||||
| none := throw ("undefined '" ++ to_fmt y ++ "' at '" ++ to_fmt p ++ "'"))
|
||||
mk_blockid_set
|
||||
|
||||
def phis.check_predecessors (ps : list phi) : ssa_valid_m unit :=
|
||||
|
|
@ -144,8 +134,7 @@ do ps.mfoldl (λ (os : option blockid_set) (p : phi),
|
|||
do s' ← p.predecessors,
|
||||
match os with
|
||||
| (some s) := if s.seteq s' then return os
|
||||
else do b ← read_block,
|
||||
throw (ssa_error.phi_missing_predecessor b.id p.x)
|
||||
else throw ("missing predecessor '" ++ to_fmt p.x ++ "' at '" ++ to_fmt p ++ "'")
|
||||
| none := return (some s'))
|
||||
none,
|
||||
return ()
|
||||
|
|
@ -157,7 +146,7 @@ do b ← read_block,
|
|||
b.instrs.mmap' instr.valid_ssa,
|
||||
b.term.valid_ssa
|
||||
|
||||
def block.valid_ssa : except_t ssa_error (reader_t (var2blockid × block) id) unit :=
|
||||
def block.valid_ssa : except_t format (reader_t (var2blockid × block) id) unit :=
|
||||
run_state block.valid_ssa_core mk_var_set
|
||||
|
||||
/-
|
||||
|
|
@ -166,7 +155,7 @@ and store the blockid where `x` is defined (action: `decl.declare_vars`).
|
|||
Then, we check whether every used variable in basic block has been
|
||||
defined before being used.
|
||||
-/
|
||||
def decl.valid_ssa (d : decl) : except_t ssa_error id var2blockid :=
|
||||
def decl.valid_ssa (d : decl) : except_t format id var2blockid :=
|
||||
do m ← d.var2blockid,
|
||||
match d with
|
||||
| decl.defn _ bs := do
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue