Skip to content

Commit d61926e

Browse files
committed
implement sign-extension operators proposal
1 parent 4fb4da0 commit d61926e

File tree

3 files changed

+40
-1
lines changed

3 files changed

+40
-1
lines changed

src/Language/Wasm/Interpreter.hs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -873,6 +873,16 @@ eval budget store FunctionInstance { funcType, moduleInstance, code = Function {
873873
return $ Done ctx { stack = VI32 (fromIntegral $ countTrailingZeros v) : rest }
874874
step ctx@EvalCtx{ stack = (VI32 v:rest) } (IUnOp BS32 IPopcnt) =
875875
return $ Done ctx { stack = VI32 (fromIntegral $ popCount v) : rest }
876+
step ctx@EvalCtx{ stack = (VI32 v:rest) } (IUnOp BS32 IExtend8S) =
877+
let byte = v .&. 0xFF in
878+
let r = if byte >= 0x80 then asWord32 (fromIntegral byte - 0x100) else byte in
879+
return $ Done ctx { stack = VI32 r : rest }
880+
step ctx@EvalCtx{ stack = (VI32 v:rest) } (IUnOp BS32 IExtend16S) =
881+
let half = v .&. 0xFFFF in
882+
let r = if half >= 0x8000 then asWord32 (fromIntegral half - 0x10000) else half in
883+
return $ Done ctx { stack = VI32 r : rest }
884+
step ctx@EvalCtx{ stack = (VI32 v:rest) } (IUnOp BS32 IExtend32S) =
885+
return $ Done ctx { stack = VI32 v : rest }
876886
step ctx@EvalCtx{ stack = (VI64 v2:VI64 v1:rest) } (IBinOp BS64 IAdd) =
877887
return $ Done ctx { stack = VI64 (v1 + v2) : rest }
878888
step ctx@EvalCtx{ stack = (VI64 v2:VI64 v1:rest) } (IBinOp BS64 ISub) =
@@ -939,6 +949,18 @@ eval budget store FunctionInstance { funcType, moduleInstance, code = Function {
939949
return $ Done ctx { stack = VI64 (fromIntegral $ countTrailingZeros v) : rest }
940950
step ctx@EvalCtx{ stack = (VI64 v:rest) } (IUnOp BS64 IPopcnt) =
941951
return $ Done ctx { stack = VI64 (fromIntegral $ popCount v) : rest }
952+
step ctx@EvalCtx{ stack = (VI64 v:rest) } (IUnOp BS64 IExtend8S) =
953+
let byte = v .&. 0xFF in
954+
let r = if byte >= 0x80 then asWord64 (fromIntegral byte - 0x100) else byte in
955+
return $ Done ctx { stack = VI64 r : rest }
956+
step ctx@EvalCtx{ stack = (VI64 v:rest) } (IUnOp BS64 IExtend16S) =
957+
let quart = v .&. 0xFFFF in
958+
let r = if quart >= 0x8000 then asWord64 (fromIntegral quart - 0x10000) else quart in
959+
return $ Done ctx { stack = VI64 r : rest }
960+
step ctx@EvalCtx{ stack = (VI64 v:rest) } (IUnOp BS64 IExtend32S) =
961+
let half = v .&. 0xFFFFFFFF in
962+
let r = if half >= 0x80000000 then asWord64 (fromIntegral half - 0x100000000) else half in
963+
return $ Done ctx { stack = VI64 r : rest }
942964
step ctx@EvalCtx{ stack = (VF32 v:rest) } (FUnOp BS32 FAbs) =
943965
return $ Done ctx { stack = VF32 (abs v) : rest }
944966
step ctx@EvalCtx{ stack = (VF32 v:rest) } (FUnOp BS32 FNeg) =

src/Language/Wasm/Parser.y

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ import Language.Wasm.Lexer (
165165
'i32.clz' { Lexeme _ (TKeyword "i32.clz") }
166166
'i32.ctz' { Lexeme _ (TKeyword "i32.ctz") }
167167
'i32.popcnt' { Lexeme _ (TKeyword "i32.popcnt") }
168+
'i32.extend8_s' { Lexeme _ (TKeyword "i32.extend8_s") }
169+
'i32.extend16_s' { Lexeme _ (TKeyword "i32.extend16_s") }
168170
'i32.add' { Lexeme _ (TKeyword "i32.add") }
169171
'i32.sub' { Lexeme _ (TKeyword "i32.sub") }
170172
'i32.mul' { Lexeme _ (TKeyword "i32.mul") }
@@ -183,6 +185,9 @@ import Language.Wasm.Lexer (
183185
'i64.clz' { Lexeme _ (TKeyword "i64.clz") }
184186
'i64.ctz' { Lexeme _ (TKeyword "i64.ctz") }
185187
'i64.popcnt' { Lexeme _ (TKeyword "i64.popcnt") }
188+
'i64.extend8_s' { Lexeme _ (TKeyword "i64.extend8_s") }
189+
'i64.extend16_s' { Lexeme _ (TKeyword "i64.extend16_s") }
190+
'i64.extend32_s' { Lexeme _ (TKeyword "i64.extend32_s") }
186191
'i64.add' { Lexeme _ (TKeyword "i64.add") }
187192
'i64.sub' { Lexeme _ (TKeyword "i64.sub") }
188193
'i64.mul' { Lexeme _ (TKeyword "i64.mul") }
@@ -443,6 +448,8 @@ plaininstr :: { PlainInstr }
443448
| 'i32.clz' { IUnOp BS32 IClz }
444449
| 'i32.ctz' { IUnOp BS32 ICtz }
445450
| 'i32.popcnt' { IUnOp BS32 IPopcnt }
451+
| 'i32.extend8_s' { IUnOp BS32 IExtend8S }
452+
| 'i32.extend16_s' { IUnOp BS32 IExtend16S }
446453
| 'i32.add' { IBinOp BS32 IAdd }
447454
| 'i32.sub' { IBinOp BS32 ISub }
448455
| 'i32.mul' { IBinOp BS32 IMul }
@@ -461,6 +468,9 @@ plaininstr :: { PlainInstr }
461468
| 'i64.clz' { IUnOp BS64 IClz }
462469
| 'i64.ctz' { IUnOp BS64 ICtz }
463470
| 'i64.popcnt' { IUnOp BS64 IPopcnt }
471+
| 'i64.extend8_s' { IUnOp BS64 IExtend8S }
472+
| 'i64.extend16_s' { IUnOp BS64 IExtend16S }
473+
| 'i64.extend32_s' { IUnOp BS64 IExtend32S }
464474
| 'i64.add' { IBinOp BS64 IAdd }
465475
| 'i64.sub' { IBinOp BS64 ISub }
466476
| 'i64.mul' { IBinOp BS64 IMul }

src/Language/Wasm/Structure.hs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,14 @@ import GHC.Generics (Generic)
5757

5858
data BitSize = BS32 | BS64 deriving (Show, Eq, Generic, NFData)
5959

60-
data IUnOp = IClz | ICtz | IPopcnt deriving (Show, Eq, Generic, NFData)
60+
data IUnOp =
61+
IClz
62+
| ICtz
63+
| IPopcnt
64+
| IExtend8S
65+
| IExtend16S
66+
| IExtend32S
67+
deriving (Show, Eq, Generic, NFData)
6168

6269
data IBinOp =
6370
IAdd

0 commit comments

Comments
 (0)