| // asmcheck | |
| // Copyright 2019 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| // These tests check code generation of switch statements. | |
| package codegen | |
| // see issue 33934 | |
| func f(x string) int { | |
| // amd64:-`cmpstring` | |
| switch x { | |
| case "": | |
| return -1 | |
| case "1", "2", "3": | |
| return -2 | |
| default: | |
| return -3 | |
| } | |
| } | |
| // use jump tables for 8+ int cases | |
| func square(x int) int { | |
| // amd64:`JMP\s\(.*\)\(.*\)$` | |
| // arm64:`MOVD\s\(R.*\)\(R.*<<3\)`,`JMP\s\(R.*\)$` | |
| switch x { | |
| case 1: | |
| return 1 | |
| case 2: | |
| return 4 | |
| case 3: | |
| return 9 | |
| case 4: | |
| return 16 | |
| case 5: | |
| return 25 | |
| case 6: | |
| return 36 | |
| case 7: | |
| return 49 | |
| case 8: | |
| return 64 | |
| default: | |
| return x * x | |
| } | |
| } | |
| // use jump tables for 8+ string lengths | |
| func length(x string) int { | |
| // amd64:`JMP\s\(.*\)\(.*\)$` | |
| // arm64:`MOVD\s\(R.*\)\(R.*<<3\)`,`JMP\s\(R.*\)$` | |
| switch x { | |
| case "a": | |
| return 1 | |
| case "bb": | |
| return 2 | |
| case "ccc": | |
| return 3 | |
| case "dddd": | |
| return 4 | |
| case "eeeee": | |
| return 5 | |
| case "ffffff": | |
| return 6 | |
| case "ggggggg": | |
| return 7 | |
| case "hhhhhhhh": | |
| return 8 | |
| default: | |
| return len(x) | |
| } | |
| } | |
| // Use single-byte ordered comparisons for binary searching strings. | |
| // See issue 53333. | |
| func mimetype(ext string) string { | |
| // amd64: `CMPB\s1\(.*\), \$104$`,-`cmpstring` | |
| // arm64: `MOVB\s1\(R.*\), R.*$`, `CMPW\s\$104, R.*$`, -`cmpstring` | |
| switch ext { | |
| // amd64: `CMPL\s\(.*\), \$1836345390$` | |
| // arm64: `MOVD\s\$1836345390`, `CMPW\sR.*, R.*$` | |
| case ".htm": | |
| return "A" | |
| // amd64: `CMPL\s\(.*\), \$1953457454$` | |
| // arm64: `MOVD\s\$1953457454`, `CMPW\sR.*, R.*$` | |
| case ".eot": | |
| return "B" | |
| // amd64: `CMPL\s\(.*\), \$1735815982$` | |
| // arm64: `MOVD\s\$1735815982`, `CMPW\sR.*, R.*$` | |
| case ".svg": | |
| return "C" | |
| // amd64: `CMPL\s\(.*\), \$1718907950$` | |
| // arm64: `MOVD\s\$1718907950`, `CMPW\sR.*, R.*$` | |
| case ".ttf": | |
| return "D" | |
| default: | |
| return "" | |
| } | |
| } | |
| // use jump tables for type switches to concrete types. | |
| func typeSwitch(x any) int { | |
| // amd64:`JMP\s\(.*\)\(.*\)$` | |
| // arm64:`MOVD\s\(R.*\)\(R.*<<3\)`,`JMP\s\(R.*\)$` | |
| switch x.(type) { | |
| case int: | |
| return 0 | |
| case int8: | |
| return 1 | |
| case int16: | |
| return 2 | |
| case int32: | |
| return 3 | |
| case int64: | |
| return 4 | |
| } | |
| return 7 | |
| } | |
| type I interface { | |
| foo() | |
| } | |
| type J interface { | |
| bar() | |
| } | |
| type IJ interface { | |
| I | |
| J | |
| } | |
| type K interface { | |
| baz() | |
| } | |
| // use a runtime call for type switches to interface types. | |
| func interfaceSwitch(x any) int { | |
| // amd64:`CALL\truntime.interfaceSwitch`,`MOVL\t16\(AX\)`,`MOVQ\t8\(.*\)(.*\*8)` | |
| // arm64:`CALL\truntime.interfaceSwitch`,`LDAR`,`MOVWU\t16\(R0\)`,`MOVD\t\(R.*\)\(R.*\)` | |
| switch x.(type) { | |
| case I: | |
| return 1 | |
| case J: | |
| return 2 | |
| default: | |
| return 3 | |
| } | |
| } | |
| func interfaceSwitch2(x K) int { | |
| // amd64:`CALL\truntime.interfaceSwitch`,`MOVL\t16\(AX\)`,`MOVQ\t8\(.*\)(.*\*8)` | |
| // arm64:`CALL\truntime.interfaceSwitch`,`LDAR`,`MOVWU\t16\(R0\)`,`MOVD\t\(R.*\)\(R.*\)` | |
| switch x.(type) { | |
| case I: | |
| return 1 | |
| case J: | |
| return 2 | |
| default: | |
| return 3 | |
| } | |
| } | |
| func interfaceCast(x any) int { | |
| // amd64:`CALL\truntime.typeAssert`,`MOVL\t16\(AX\)`,`MOVQ\t8\(.*\)(.*\*1)` | |
| // arm64:`CALL\truntime.typeAssert`,`LDAR`,`MOVWU\t16\(R0\)`,`MOVD\t\(R.*\)\(R.*\)` | |
| if _, ok := x.(I); ok { | |
| return 3 | |
| } | |
| return 5 | |
| } | |
| func interfaceCast2(x K) int { | |
| // amd64:`CALL\truntime.typeAssert`,`MOVL\t16\(AX\)`,`MOVQ\t8\(.*\)(.*\*1)` | |
| // arm64:`CALL\truntime.typeAssert`,`LDAR`,`MOVWU\t16\(R0\)`,`MOVD\t\(R.*\)\(R.*\)` | |
| if _, ok := x.(I); ok { | |
| return 3 | |
| } | |
| return 5 | |
| } | |
| func interfaceConv(x IJ) I { | |
| // amd64:`CALL\truntime.typeAssert`,`MOVL\t16\(AX\)`,`MOVQ\t8\(.*\)(.*\*1)` | |
| // arm64:`CALL\truntime.typeAssert`,`LDAR`,`MOVWU\t16\(R0\)`,`MOVD\t\(R.*\)\(R.*\)` | |
| return x | |
| } | |
| // Make sure we can constant fold after inlining. See issue 71699. | |
| func stringSwitchInlineable(s string) { | |
| switch s { | |
| case "foo", "bar", "baz", "goo": | |
| default: | |
| println("no") | |
| } | |
| } | |
| func stringSwitch() { | |
| // amd64:-"CMP",-"CALL" | |
| // arm64:-"CMP",-"CALL" | |
| stringSwitchInlineable("foo") | |
| } |