Skip to content

Commit 3ea43a8

Browse files
Robertorosmaninhotothtamas28juliankuners
authored
Introducing new MInt hooks to BYTES, LIST, and MINT modules (#4837)
This PR intends to add these new hooks described below to make it possible to translate our KEVM's `wordStack` to use MInt instead of Int to get a better performance from it. The new hooks proposed by this PR are: ```k 1. syntax {Width} MInt{Width} ::=MInt{Width} "^MInt" MInt{Width} 2. syntax {Width} Bytes ::= MInt2Bytes(MInt{Width}) 3. syntax {Width} MInt{Width} ::= Bytes2MInt(Bytes) 4. syntax {Width} MInt{Width} ::= lengthBytes(Bytes) 5. syntax {Width} Bytes ::= padRightBytes(Bytes, length: MInt{Width}, value: MInt{Width}) 6. syntax {Width} Bytes ::= padLeftBytes(Bytes, length: MInt{Width}, value: MInt{Width}) 7. syntax {Width} Bytes ::= replaceAtBytes(dest: Bytes, index: MInt{Width}, src: Bytes) 8. syntax {Width} Bytes ::= substrBytes(Bytes, startIndex: MInt{Width}, endIndex: MInt{Width}) 9. syntax {Width} MInt{Width} ::= Bytes "[" MInt{Width} "]" 10. syntax {Width} Bytes ::= Bytes "[" index: MInt{Width} "<-" value: MInt{Width} "]" 11. syntax {Width} MInt{Width} ::= size(List) 12. syntax {Width} List ::= List "[" index: MInt{Width} "<-" value: KItem "]" 13. syntax {Width} KItem ::= List "[" MInt{Width} "]" ``` Most of these hooks have an initial implementation for 64 and 256-bit integers, the necessary width for KEVM, but it's simple to add other bit widths as needed in the future! --------- Co-authored-by: Tamás Tóth <tothtamas28@users.noreply.github.com> Co-authored-by: Julian Kuners <julian.kuners@gmail.com>
1 parent 75b3b89 commit 3ea43a8

File tree

32 files changed

+240
-15
lines changed

32 files changed

+240
-15
lines changed

k-distribution/include/kframework/builtin/domains.md

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,7 @@ patterns for doing so, refer to K's
908908
```k
909909
module LIST
910910
imports private INT-SYNTAX
911+
imports private MINT-SYNTAX
911912
imports private BASIC-K
912913
913914
syntax List [hook(LIST.List)]
@@ -957,21 +958,25 @@ An element can be added to the front of a `List` using the `pushList` operator.
957958
### List indexing
958959

959960
You can get an element of a list by its integer offset in O(log(N)) time, or
960-
effectively constant. Positive indices are 0-indexed from the beginning of the
961+
effectively constant. Positive `Int` indices are 0-indexed from the beginning of the
961962
list, and negative indices are -1-indexed from the end of the list. In other
962-
words, 0 is the first element and -1 is the last element.
963+
words, 0 is the first element and -1 is the last element. The indice can also be
964+
`MInt`, which is interprested as an unsigned integer, and therefore, don't support
965+
negative indices feature. Currently, only 64-bit and 256-bit `MInt` types are supported.
963966

964967
```k
965968
syntax KItem ::= List "[" Int "]" [function, hook(LIST.get), symbol(List:get)]
969+
syntax {Width} KItem ::= List "[" MInt{Width} "]" [function, hook(LIST.getMInt), symbol(List:getMInt)]
966970
```
967971

968972
### List update
969973

970974
You can create a new `List` with a new value at a particular index in
971-
O(log(N)) time, or effectively constant.
975+
O(log(N)) time, or effectively constant. The index can be either as an `Int` or as an `MInt`. Currently, only 64-bit `MInt` type is supported.
972976

973977
```k
974978
syntax List ::= List "[" index: Int "<-" value: KItem "]" [function, hook(LIST.update), symbol(List:set)]
979+
syntax {Width} List ::= List "[" index: MInt{Width} "<-" value: KItem "]" [function, hook(LIST.updateMInt), symbol(List:setMInt)]
975980
```
976981

977982
### List of identical elements
@@ -1023,10 +1028,16 @@ comparisons, it is much better to first convert to a set using `List2Set`.
10231028

10241029
### List size
10251030

1026-
You can get the number of elements of a list in O(1) time.
1031+
You can get the number of elements of a list in O(1) time. The output
1032+
size can be either as an `Int` or as an `MInt`. Currently, only 64-bit
1033+
and 256-bit `MInt` types are supported. When using `MInt`, the size is
1034+
interpreted as an unsigned integer, and the size of the list must match
1035+
the bounds of this `MInt` type, that is the size can't be larger than
1036+
`2^64 - 1` for `MInt{64}` and `2^256 - 1` for `MInt{256}`.
10271037

10281038
```k
10291039
syntax Int ::= size(List) [function, total, hook(LIST.size), symbol(sizeList), smtlib(smt_seq_len)]
1040+
syntax {Width} MInt{Width} ::= size(List) [function, hook(LIST.sizeMInt), symbol(sizeMInt)]
10301041
```
10311042

10321043
```k
@@ -2010,6 +2021,7 @@ endmodule
20102021
module BYTES-HOOKED
20112022
imports STRING-SYNTAX
20122023
imports BYTES-SYNTAX
2024+
imports MINT-SYNTAX
20132025
imports BYTES-STRING-ENCODE
20142026
```
20152027

@@ -2085,22 +2097,25 @@ mutations of the input or output value.
20852097

20862098
### Bytes update
20872099

2088-
You can set the value of a particular byte in a `Bytes` object in O(1) time.
2089-
The result is `#False` if `value` is not in the range [0..255] or if `index`
2090-
is not a valid index (ie, less than zero or greater than or equal to the length
2091-
of the `Bytes` term).
2100+
You can set the value of a particular byte in a `Bytes` object in O(1) time,
2101+
either with index and value as `Int` or as an `MInt`. Currently, only 64-bit
2102+
and 256-bit `MInt` types are supported. The result is `#False` if `value` is
2103+
not in the range [0..255] or if `index` is not a valid index (ie, less than
2104+
zero or greater than or equal to the length of the `Bytes` term).
20922105

20932106
```k
20942107
syntax Bytes ::= Bytes "[" index: Int "<-" value: Int "]" [function, hook(BYTES.update)]
2108+
syntax {Width} Bytes ::= Bytes "[" index: MInt{Width} "<-" value: MInt{Width} "]" [function, hook(BYTES.updateMInt)]
20952109
```
20962110

20972111
### Bytes lookup
20982112

2099-
You can get the value of a particular byte in a `Bytes` object in O(1) time.
2113+
You can get the value of a particular byte in a `Bytes` object in O(1) time, either as an `Int` or as an `MInt`. Currently, only 64-bit and 256-bit `MInt` types are supported.
21002114
The result is `#False` if `index` is not a valid index (see above).
21012115

21022116
```k
21032117
syntax Int ::= Bytes "[" Int "]" [function, hook(BYTES.get)]
2118+
syntax {Width} MInt{Width} ::= Bytes "[" MInt{Width} "]" [function, hook(BYTES.getMInt)]
21042119
```
21052120

21062121
### Bytes substring
@@ -2109,9 +2124,12 @@ You can get a new `Bytes` object containing a range of bytes from the input
21092124
`Bytes` in O(N) time (where N is the length of the substring). The range
21102125
of bytes included is `[startIndex..endIndex)`. The resulting `Bytes` is
21112126
a copy and mutations to it do not affect mutations to the original `Bytes`.
2127+
Both `startIndex` and `endIndex` can be either `Int` or `MInt` values, but,
2128+
currently, only 64-bit and 256-bit `MInt` types are supported.
21122129

21132130
```k
21142131
syntax Bytes ::= substrBytes(Bytes, startIndex: Int, endIndex: Int) [function, hook(BYTES.substr)]
2132+
syntax {Width} Bytes ::= substrBytes(Bytes, startIndex: MInt{Width}, endIndex: MInt{Width}) [function, hook(BYTES.substrMInt)]
21152133
```
21162134

21172135
The function is not total: `substrBytes(B, startIndex, endIndex)` is `#Bottom` if
@@ -2125,10 +2143,13 @@ You can modify a `Bytes` to return a `Bytes` which is equal to `dest` except the
21252143
`N` elements starting at `index` are replaced with the contents of `src` in O(N)
21262144
time. If `--llvm-mutable-bytes` is active, this will not create a new `Bytes`
21272145
object and will instead modify the original on concrete backends. The result is
2128-
`#False` if `index` + `N` is not a valid index.
2146+
`#False` if `index` + `N` is not a valid index. This function accepts both
2147+
`Int` and `MInt` values for `index` and `N`. Currently, only 64-bit and
2148+
256-bit `MInt` types are supported.
21292149

21302150
```k
21312151
syntax Bytes ::= replaceAtBytes(dest: Bytes, index: Int, src: Bytes) [function, hook(BYTES.replaceAt)]
2152+
syntax {Width} Bytes ::= replaceAtBytes(dest: Bytes, index: MInt{Width}, src: Bytes) [function, hook(BYTES.replaceAtMInt)]
21322153
```
21332154

21342155
### Multiple bytes update
@@ -2153,10 +2174,15 @@ left) with the specified `value`. If `--llvm-mutable-bytes` is active, this does
21532174
not create a new `Bytes` object if the input is already at least `length` bytes
21542175
long, and will instead return the input unchanged. The result is `#False` if
21552176
`value` is not in the range `[0..255]`, or if the length is negative.
2177+
We also provide a variant of this function which takes an `MInt` for the
2178+
`length` and `value`. The current implementation only supports 64-bit and
2179+
256-bit `MInt` types.
21562180

21572181
```k
21582182
syntax Bytes ::= padRightBytes(Bytes, length: Int, value: Int) [function, hook(BYTES.padRight)]
21592183
| padLeftBytes(Bytes, length: Int, value: Int) [function, hook(BYTES.padLeft)]
2184+
syntax {Width} Bytes ::= padRightBytes(Bytes, length: MInt{Width}, value: MInt{Width}) [function, hook(BYTES.padRightMInt)]
2185+
| padLeftBytes(Bytes, length: MInt{Width}, value: MInt{Width}) [function, hook(BYTES.padLeftMInt)]
21602186
```
21612187

21622188
### Bytes reverse
@@ -2171,10 +2197,12 @@ original.
21712197

21722198
### Bytes length
21732199

2174-
You can get the length of a `Bytes` term in O(1) time.
2200+
You can get the length of a `Bytes` term in O(1) time. The lenghth can be either
2201+
an `Int` or an `MInt`. Currently, only 64-bit and 256-bit `MInt` types are supported.
21752202

21762203
```k
21772204
syntax Int ::= lengthBytes(Bytes) [function, total, hook(BYTES.length), smtlib(lengthBytes)]
2205+
syntax {Width} MInt{Width} ::= lengthBytes(Bytes) [function, total, hook(BYTES.lengthMInt)]
21782206
```
21792207

21802208

@@ -2865,6 +2893,7 @@ endmodule
28652893
module MINT
28662894
imports MINT-SYNTAX
28672895
imports private INT
2896+
imports private BYTES
28682897
imports private BOOL
28692898
```
28702899

@@ -2896,6 +2925,14 @@ has the correct bitwidth, as this will influence the width of the resulting
28962925
syntax {Width} MInt{Width} ::= Int2MInt(Int) [function, total, hook(MINT.integer), smt-hook(int2bv)]
28972926
```
28982927

2928+
### Mint and Bytes conversion
2929+
You can convert from an `MInt` to a `Bytes` using the `MInt2Bytes` function.
2930+
Currently we only support converting `MInt`s of width 256 to `Bytes` in a Big Endian format.
2931+
```k
2932+
syntax {Width} Bytes ::= MInt2Bytes(MInt{Width}) [function, total, hook(MINT.MInt2bytes)]
2933+
syntax {Width} MInt{Width} ::= Bytes2MInt(Bytes) [function, total, hook(MINT.bytes2MInt)]
2934+
```
2935+
28992936
### MInt min and max values
29002937

29012938
You can get the minimum and maximum values of a signed or unsigned `MInt`
@@ -2938,6 +2975,8 @@ You can:
29382975

29392976
* Compute the bitwise complement `~MInt` of an `MInt`.
29402977
* Compute the unary negation `--MInt` of an `MInt`.
2978+
* Compute the power `^MInt` of two `MInt`s interpreted as unsigned integers.
2979+
Currently, only 64 and 256-bits is supported.
29412980
* Compute the product `*MInt` of two `MInt`s.
29422981
* Compute the quotient `/sMInt` of two `MInt`s interpreted as signed integers.
29432982
* Compute the modulus `%sMInt` of two `MInt`s interpreted as signed integers.
@@ -2960,7 +2999,8 @@ You can:
29602999
syntax {Width} MInt{Width} ::= "~MInt" MInt{Width} [function, total, hook(MINT.not), smt-hook(bvnot)]
29613000
| "--MInt" MInt{Width} [function, total, hook(MINT.neg), smt-hook(bvuminus)]
29623001
> left:
2963-
MInt{Width} "*MInt" MInt{Width} [function, total, hook(MINT.mul), smt-hook(bvmul)]
3002+
MInt{Width} "^MInt" MInt{Width} [function, total, hook(MINT.pow)]
3003+
| MInt{Width} "*MInt" MInt{Width} [function, total, hook(MINT.mul), smt-hook(bvmul)]
29643004
| MInt{Width} "/sMInt" MInt{Width} [function, hook(MINT.sdiv), smt-hook(bvsdiv)]
29653005
| MInt{Width} "%sMInt" MInt{Width} [function, hook(MINT.srem), smt-hook(bvsrem)]
29663006
| MInt{Width} "/uMInt" MInt{Width} [function, hook(MINT.udiv), smt-hook(bvudiv)]
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[Error] Compiler: Inconsistent token precedence detected.
22
Source(domains.md)
3-
Location(1199,18,1199,52)
4-
1199 | syntax Int ::= r"[0-9]+" [prefer, token, prec(2)]
3+
Location(1210,18,1210,52)
4+
1210 | syntax Int ::= r"[0-9]+" [prefer, token, prec(2)]
55
. ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
testBytes2MInt
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<k>
2+
true ~> .K
3+
</k>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
testPadLeftBytes
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<k>
2+
true ~> .K
3+
</k>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
testPadRightBytes
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<k>
2+
true ~> .K
3+
</k>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
testSubstrBytes
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<k>
2+
true ~> .K
3+
</k>

0 commit comments

Comments
 (0)