]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: add sign-extension operators on wasm
authorRichard Musiol <mail@richard-musiol.de>
Sat, 23 Mar 2019 14:25:42 +0000 (15:25 +0100)
committerRichard Musiol <neelance@gmail.com>
Thu, 28 Mar 2019 20:23:05 +0000 (20:23 +0000)
This change adds the GOWASM option "signext" to enable
the generation of experimental sign-extension operators.

The feature is in phase 4 of the WebAssembly proposal process:
https://github.com/WebAssembly/meetings/blob/master/process/phases.md

More information on the feature can be found at:
https://github.com/WebAssembly/sign-extension-ops/blob/master/proposals/sign-extension-ops/Overview.md

Change-Id: I6b30069390a8699fbecd9fb4d1d61e13c59b0333
Reviewed-on: https://go-review.googlesource.com/c/go/+/168882
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>

12 files changed:
doc/install-source.html
src/cmd/compile/internal/ssa/gen/Wasm.rules
src/cmd/compile/internal/ssa/gen/WasmOps.go
src/cmd/compile/internal/ssa/opGen.go
src/cmd/compile/internal/ssa/rewriteWasm.go
src/cmd/compile/internal/wasm/ssa.go
src/cmd/go/alldocs.go
src/cmd/go/internal/help/helpdoc.go
src/cmd/internal/obj/wasm/a.out.go
src/cmd/internal/obj/wasm/anames.go
src/cmd/internal/obj/wasm/wasmobj.go
src/cmd/internal/objabi/util.go

index 46dc618a9c74b21b2f26cc06c28ce61d4df63746..9c73b925b1b3e28a770f1403b6587a0e92bdbd4a 100644 (file)
@@ -645,7 +645,7 @@ for which the compiler will target. The default is <code>power8</code>.
        The default is to use no experimental features.
        </p>
        <ul>
-               <li>(no features yet)</li>
+               <li><code>GOWASM=signext</code>: generate <a href="https://github.com/WebAssembly/sign-extension-ops/blob/master/proposals/sign-extension-ops/Overview.md">sign-extension operators</a></li>
        </ul>
 </li>
 
index 83e1be798e8afa9d0576aa78e7dd65486ccb644c..72f4805edf213dc54dbebc34777372d720bf75af 100644 (file)
@@ -56,6 +56,9 @@
 (ZeroExt32to64        x:(I64Load32U _ _)) -> x
 (ZeroExt16to(64|32)   x:(I64Load16U _ _)) -> x
 (ZeroExt8to(64|32|16) x:(I64Load8U  _ _)) -> x
+(SignExt32to64        x) && objabi.GOWASM.SignExt -> (I64Extend32S x)
+(SignExt8to(64|32|16) x) && objabi.GOWASM.SignExt -> (I64Extend8S x)
+(SignExt16to(64|32)   x) && objabi.GOWASM.SignExt -> (I64Extend16S x)
 (SignExt32to64        x) -> (I64ShrS (I64Shl x (I64Const [32])) (I64Const [32]))
 (SignExt16to(64|32)   x) -> (I64ShrS (I64Shl x (I64Const [48])) (I64Const [48]))
 (SignExt8to(64|32|16) x) -> (I64ShrS (I64Shl x (I64Const [56])) (I64Const [56]))
index 4a01bf6c2811d48c2aa096fd0e0da72c14b0b29d..4e5f0765750d6078e032c31cd3d4f669111fc567 100644 (file)
@@ -192,6 +192,10 @@ func init() {
                {name: "F64ConvertI64S", asm: "F64ConvertI64S", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{fp}}, typ: "Float64"}, // converts the signed integer arg0 to a float
                {name: "F64ConvertI64U", asm: "F64ConvertI64U", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{fp}}, typ: "Float64"}, // converts the unsigned integer arg0 to a float
 
+               {name: "I64Extend8S", asm: "I64Extend8S", argLength: 1, reg: gp11, typ: "Int64"},   // sign-extend arg0 from 8 to 64 bit
+               {name: "I64Extend16S", asm: "I64Extend16S", argLength: 1, reg: gp11, typ: "Int64"}, // sign-extend arg0 from 16 to 64 bit
+               {name: "I64Extend32S", asm: "I64Extend32S", argLength: 1, reg: gp11, typ: "Int64"}, // sign-extend arg0 from 32 to 64 bit
+
                {name: "F64Sqrt", asm: "F64Sqrt", argLength: 1, reg: fp11, typ: "Float64"},         // sqrt(arg0)
                {name: "F64Trunc", asm: "F64Trunc", argLength: 1, reg: fp11, typ: "Float64"},       // trunc(arg0)
                {name: "F64Ceil", asm: "F64Ceil", argLength: 1, reg: fp11, typ: "Float64"},         // ceil(arg0)
index d71d6146d13c5250fc81e67302a69659e03fbd11..214d68757c447ed898a652ddd4ad343977291149 100644 (file)
@@ -2136,6 +2136,9 @@ const (
        OpWasmI64TruncF64U
        OpWasmF64ConvertI64S
        OpWasmF64ConvertI64U
+       OpWasmI64Extend8S
+       OpWasmI64Extend16S
+       OpWasmI64Extend32S
        OpWasmF64Sqrt
        OpWasmF64Trunc
        OpWasmF64Ceil
@@ -28724,6 +28727,45 @@ var opcodeTable = [...]opInfo{
                        },
                },
        },
+       {
+               name:   "I64Extend8S",
+               argLen: 1,
+               asm:    wasm.AI64Extend8S,
+               reg: regInfo{
+                       inputs: []inputInfo{
+                               {0, 4295032831}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+                       },
+                       outputs: []outputInfo{
+                               {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+                       },
+               },
+       },
+       {
+               name:   "I64Extend16S",
+               argLen: 1,
+               asm:    wasm.AI64Extend16S,
+               reg: regInfo{
+                       inputs: []inputInfo{
+                               {0, 4295032831}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+                       },
+                       outputs: []outputInfo{
+                               {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+                       },
+               },
+       },
+       {
+               name:   "I64Extend32S",
+               argLen: 1,
+               asm:    wasm.AI64Extend32S,
+               reg: regInfo{
+                       inputs: []inputInfo{
+                               {0, 4295032831}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 SP
+                       },
+                       outputs: []outputInfo{
+                               {0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
+                       },
+               },
+       },
        {
                name:   "F64Sqrt",
                argLen: 1,
index 7796548ee427246ce3f397c747d398423db03054..fe85922e31b06128689d10351679b32f4a25d7e7 100644 (file)
@@ -4426,6 +4426,18 @@ func rewriteValueWasm_OpSignExt16to32_0(v *Value) bool {
                return true
        }
        // match: (SignExt16to32 x)
+       // cond: objabi.GOWASM.SignExt
+       // result: (I64Extend16S x)
+       for {
+               x := v.Args[0]
+               if !(objabi.GOWASM.SignExt) {
+                       break
+               }
+               v.reset(OpWasmI64Extend16S)
+               v.AddArg(x)
+               return true
+       }
+       // match: (SignExt16to32 x)
        // cond:
        // result: (I64ShrS (I64Shl x (I64Const [48])) (I64Const [48]))
        for {
@@ -4461,6 +4473,18 @@ func rewriteValueWasm_OpSignExt16to64_0(v *Value) bool {
                return true
        }
        // match: (SignExt16to64 x)
+       // cond: objabi.GOWASM.SignExt
+       // result: (I64Extend16S x)
+       for {
+               x := v.Args[0]
+               if !(objabi.GOWASM.SignExt) {
+                       break
+               }
+               v.reset(OpWasmI64Extend16S)
+               v.AddArg(x)
+               return true
+       }
+       // match: (SignExt16to64 x)
        // cond:
        // result: (I64ShrS (I64Shl x (I64Const [48])) (I64Const [48]))
        for {
@@ -4496,6 +4520,18 @@ func rewriteValueWasm_OpSignExt32to64_0(v *Value) bool {
                return true
        }
        // match: (SignExt32to64 x)
+       // cond: objabi.GOWASM.SignExt
+       // result: (I64Extend32S x)
+       for {
+               x := v.Args[0]
+               if !(objabi.GOWASM.SignExt) {
+                       break
+               }
+               v.reset(OpWasmI64Extend32S)
+               v.AddArg(x)
+               return true
+       }
+       // match: (SignExt32to64 x)
        // cond:
        // result: (I64ShrS (I64Shl x (I64Const [32])) (I64Const [32]))
        for {
@@ -4531,6 +4567,18 @@ func rewriteValueWasm_OpSignExt8to16_0(v *Value) bool {
                return true
        }
        // match: (SignExt8to16 x)
+       // cond: objabi.GOWASM.SignExt
+       // result: (I64Extend8S x)
+       for {
+               x := v.Args[0]
+               if !(objabi.GOWASM.SignExt) {
+                       break
+               }
+               v.reset(OpWasmI64Extend8S)
+               v.AddArg(x)
+               return true
+       }
+       // match: (SignExt8to16 x)
        // cond:
        // result: (I64ShrS (I64Shl x (I64Const [56])) (I64Const [56]))
        for {
@@ -4566,6 +4614,18 @@ func rewriteValueWasm_OpSignExt8to32_0(v *Value) bool {
                return true
        }
        // match: (SignExt8to32 x)
+       // cond: objabi.GOWASM.SignExt
+       // result: (I64Extend8S x)
+       for {
+               x := v.Args[0]
+               if !(objabi.GOWASM.SignExt) {
+                       break
+               }
+               v.reset(OpWasmI64Extend8S)
+               v.AddArg(x)
+               return true
+       }
+       // match: (SignExt8to32 x)
        // cond:
        // result: (I64ShrS (I64Shl x (I64Const [56])) (I64Const [56]))
        for {
@@ -4601,6 +4661,18 @@ func rewriteValueWasm_OpSignExt8to64_0(v *Value) bool {
                return true
        }
        // match: (SignExt8to64 x)
+       // cond: objabi.GOWASM.SignExt
+       // result: (I64Extend8S x)
+       for {
+               x := v.Args[0]
+               if !(objabi.GOWASM.SignExt) {
+                       break
+               }
+               v.reset(OpWasmI64Extend8S)
+               v.AddArg(x)
+               return true
+       }
+       // match: (SignExt8to64 x)
        // cond:
        // result: (I64ShrS (I64Shl x (I64Const [56])) (I64Const [56]))
        for {
index d2ac2df6132289cff2af66b3c3433d5cafce6aa8..7575df548aecee55cdd8165e8e519d21b012a76f 100644 (file)
@@ -317,7 +317,10 @@ func ssaGenValueOnStack(s *gc.SSAGenState, v *ssa.Value) {
                p := s.Prog(wasm.ACall)
                p.To = obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_EXTERN, Sym: gc.WasmTruncU}
 
-       case ssa.OpWasmF64Neg, ssa.OpWasmF64ConvertI64S, ssa.OpWasmF64ConvertI64U, ssa.OpWasmF64Sqrt, ssa.OpWasmF64Trunc, ssa.OpWasmF64Ceil, ssa.OpWasmF64Floor, ssa.OpWasmF64Nearest, ssa.OpWasmF64Abs, ssa.OpWasmI64Ctz, ssa.OpWasmI64Clz, ssa.OpWasmI64Popcnt:
+       case
+               ssa.OpWasmF64Neg, ssa.OpWasmF64ConvertI64S, ssa.OpWasmF64ConvertI64U,
+               ssa.OpWasmI64Extend8S, ssa.OpWasmI64Extend16S, ssa.OpWasmI64Extend32S,
+               ssa.OpWasmF64Sqrt, ssa.OpWasmF64Trunc, ssa.OpWasmF64Ceil, ssa.OpWasmF64Floor, ssa.OpWasmF64Nearest, ssa.OpWasmF64Abs, ssa.OpWasmI64Ctz, ssa.OpWasmI64Clz, ssa.OpWasmI64Popcnt:
                getValue64(s, v.Args[0])
                s.Prog(v.Op.Asm())
 
index 8dd3f8eb18b6a507514ebafa9131b4df98d6d417..f42635f6a87f1ee4f298abb4855e23c22101eb52 100644 (file)
 //     GOMIPS64
 //             For GOARCH=mips64{,le}, whether to use floating point instructions.
 //             Valid values are hardfloat (default), softfloat.
+//     GOWASM
+//             For GOARCH=wasm, comma-separated list of experimental WebAssembly features to use.
+//             Valid values are: signext.
 //
 // Special-purpose environment variables:
 //
index d931c9225bf3710d8b28e224b4cda5271ddf9ae8..777bd511b1c9b5db4167a4d1a9ce99cc3e28c4c7 100644 (file)
@@ -563,6 +563,9 @@ Architecture-specific environment variables:
        GOMIPS64
                For GOARCH=mips64{,le}, whether to use floating point instructions.
                Valid values are hardfloat (default), softfloat.
+       GOWASM
+               For GOARCH=wasm, comma-separated list of experimental WebAssembly features to use.
+               Valid values are: signext.
 
 Special-purpose environment variables:
 
index f1830ba0361143623e3dfb7a690d6d8ee266b080..29ea87f3b08806fc2fc0290c662a55851636ad8b 100644 (file)
@@ -210,8 +210,13 @@ const (
        AI64ReinterpretF64
        AF32ReinterpretI32
        AF64ReinterpretI64
+       AI32Extend8S
+       AI32Extend16S
+       AI64Extend8S
+       AI64Extend16S
+       AI64Extend32S
 
-       // End of low-level WebAssembly instructions.
+       ALast // Sentinel: End of low-level WebAssembly instructions.
 
        ARESUMEPOINT
        // ACALLNORESUME is a call which is not followed by a resume point.
index 7ef09d665edcabf1cb1af0d9fe1cb879defeddac..fb4b72c39872c1936f8dc43c5e583456a8893e37 100644 (file)
@@ -177,6 +177,12 @@ var Anames = []string{
        "I64ReinterpretF64",
        "F32ReinterpretI32",
        "F64ReinterpretI64",
+       "I32Extend8S",
+       "I32Extend16S",
+       "I64Extend8S",
+       "I64Extend16S",
+       "I64Extend32S",
+       "Last",
        "RESUMEPOINT",
        "CALLNORESUME",
        "RETUNWIND",
index ad98cfe90ac6eb3bb26e9fe8abc223d9ace4b643..dded62a4be24b3c3580fb1d9c70a59da2bcb2f31 100644 (file)
@@ -886,7 +886,7 @@ func assemble(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) {
                }
 
                switch {
-               case p.As < AUnreachable || p.As > AF64ReinterpretI64:
+               case p.As < AUnreachable || p.As >= ALast:
                        panic(fmt.Sprintf("unexpected assembler op: %s", p.As))
                case p.As < AEnd:
                        w.WriteByte(byte(p.As - AUnreachable + 0x00))
index c007f6c47535992c355f01a064a951d51718f3d3..02f9d9273ae677ef53d912ae80a1fd74893269e3 100644 (file)
@@ -78,19 +78,22 @@ func goppc64() int {
 }
 
 type gowasmFeatures struct {
-       // no features yet
+       SignExt bool
 }
 
 func (f *gowasmFeatures) String() string {
        var flags []string
-       // no features yet
+       if f.SignExt {
+               flags = append(flags, "signext")
+       }
        return strings.Join(flags, ",")
 }
 
 func gowasm() (f gowasmFeatures) {
        for _, opt := range strings.Split(envOr("GOWASM", ""), ",") {
                switch opt {
-               // no features yet
+               case "signext":
+                       f.SignExt = true
                case "":
                        // ignore
                default: