-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy pathStackSafeAbi.lean
More file actions
57 lines (45 loc) · 2.45 KB
/
Copy pathStackSafeAbi.lean
File metadata and controls
57 lines (45 loc) · 2.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import Compiler.ABI.Frame
namespace Compiler.Lowering.StackSafeAbi
open Compiler.ABI.Frame
open Compiler.Yul
structure LoweredFrame where
prologue : List YulStmt
args : List YulExpr
layout : FrameLayout
deriving Repr
def eventNameTopicWord (eventName : String) : Nat :=
UInt64.toNat (hash eventName)
def lowerFrameSpilled (base : String) (fields : List FrameField) : Except String LoweredFrame := do
let l := layout fields
if !layoutSourcesSupported l then
throw s!"ABI frame '{base}' uses an unsupported source"
let prologue :=
match l.mode with
| .pointer => spillPayloadToMemory base l
| .inlineWords => []
pure { prologue, args := loweredArgs base l, layout := l }
def lowerFrameAsMemoryPayload (base : String) (fields : List FrameField) : Except String (List YulStmt × List YulExpr × FrameLayout) := do
let lowered ← lowerFrameSpilled base fields
let (prologue, args) := materializePayloadToMemory base lowered.layout
pure (prologue, args, lowered.layout)
def lowerEventWithTopic (base : String) (topic0 : YulExpr) (fields : List FrameField) : Except String (List YulStmt) := do
let (prologue, payloadArgs, _) ← lowerFrameAsMemoryPayload base fields
pure (prologue ++
[YulStmt.expr (YulExpr.call "log1" (payloadArgs ++ [topic0]))])
def lowerEvent (eventName : String) (fields : List FrameField) : Except String (List YulStmt) := do
lowerEventWithTopic eventName (YulExpr.lit (eventNameTopicWord eventName)) fields
def lowerExternalCall (callName : String) (target value : YulExpr) (fields : List FrameField) : Except String (List YulStmt) := do
let (prologue, payloadArgs, _) ← lowerFrameAsMemoryPayload callName fields
let callArgs := [YulExpr.call "gas" [], target, value] ++ payloadArgs ++ [YulExpr.lit 0, YulExpr.lit 0]
pure (prologue ++ [YulStmt.let_ ("__" ++ callName ++ "_ok") (YulExpr.call "call" callArgs)])
def lowerDynamicReturn (returnName : String) (fields : List FrameField) : Except String (List YulStmt) := do
let (prologue, payloadArgs, _) ← lowerFrameAsMemoryPayload returnName fields
pure (prologue ++ [YulStmt.expr (YulExpr.call "return" payloadArgs)])
def usesPointerAbi (stmts : List YulStmt) : Bool :=
stmts.any fun stmt =>
match stmt with
| .expr (.call "return" [_ptr, _size]) => true
| .expr (.call "log1" [_ptr, _size, _topic]) => true
| .let_ _ (.call "call" [_gas, _target, _value, _ptr, _size, _out, _outSize]) => true
| _ => false
end Compiler.Lowering.StackSafeAbi