mirror of
https://codeberg.org/superseriousbusiness/gotosocial.git
synced 2025-05-04 19:32:50 +03:00
[chore] Update gin to v1.9.0 (#1553)
This commit is contained in:
parent
689a10fe17
commit
ecdc8379fa
347 changed files with 166814 additions and 3671 deletions
vendor/github.com/twitchyliquid64/golang-asm/obj
598
vendor/github.com/twitchyliquid64/golang-asm/obj/util.go
generated
vendored
Normal file
598
vendor/github.com/twitchyliquid64/golang-asm/obj/util.go
generated
vendored
Normal file
|
@ -0,0 +1,598 @@
|
|||
// Copyright 2015 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.
|
||||
|
||||
package obj
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/twitchyliquid64/golang-asm/objabi"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const REG_NONE = 0
|
||||
|
||||
// Line returns a string containing the filename and line number for p
|
||||
func (p *Prog) Line() string {
|
||||
return p.Ctxt.OutermostPos(p.Pos).Format(false, true)
|
||||
}
|
||||
func (p *Prog) InnermostLine(w io.Writer) {
|
||||
p.Ctxt.InnermostPos(p.Pos).WriteTo(w, false, true)
|
||||
}
|
||||
|
||||
// InnermostLineNumber returns a string containing the line number for the
|
||||
// innermost inlined function (if any inlining) at p's position
|
||||
func (p *Prog) InnermostLineNumber() string {
|
||||
return p.Ctxt.InnermostPos(p.Pos).LineNumber()
|
||||
}
|
||||
|
||||
// InnermostLineNumberHTML returns a string containing the line number for the
|
||||
// innermost inlined function (if any inlining) at p's position
|
||||
func (p *Prog) InnermostLineNumberHTML() string {
|
||||
return p.Ctxt.InnermostPos(p.Pos).LineNumberHTML()
|
||||
}
|
||||
|
||||
// InnermostFilename returns a string containing the innermost
|
||||
// (in inlining) filename at p's position
|
||||
func (p *Prog) InnermostFilename() string {
|
||||
// TODO For now, this is only used for debugging output, and if we need more/better information, it might change.
|
||||
// An example of what we might want to see is the full stack of positions for inlined code, so we get some visibility into what is recorded there.
|
||||
pos := p.Ctxt.InnermostPos(p.Pos)
|
||||
if !pos.IsKnown() {
|
||||
return "<unknown file name>"
|
||||
}
|
||||
return pos.Filename()
|
||||
}
|
||||
|
||||
var armCondCode = []string{
|
||||
".EQ",
|
||||
".NE",
|
||||
".CS",
|
||||
".CC",
|
||||
".MI",
|
||||
".PL",
|
||||
".VS",
|
||||
".VC",
|
||||
".HI",
|
||||
".LS",
|
||||
".GE",
|
||||
".LT",
|
||||
".GT",
|
||||
".LE",
|
||||
"",
|
||||
".NV",
|
||||
}
|
||||
|
||||
/* ARM scond byte */
|
||||
const (
|
||||
C_SCOND = (1 << 4) - 1
|
||||
C_SBIT = 1 << 4
|
||||
C_PBIT = 1 << 5
|
||||
C_WBIT = 1 << 6
|
||||
C_FBIT = 1 << 7
|
||||
C_UBIT = 1 << 7
|
||||
C_SCOND_XOR = 14
|
||||
)
|
||||
|
||||
// CConv formats opcode suffix bits (Prog.Scond).
|
||||
func CConv(s uint8) string {
|
||||
if s == 0 {
|
||||
return ""
|
||||
}
|
||||
for i := range opSuffixSpace {
|
||||
sset := &opSuffixSpace[i]
|
||||
if sset.arch == objabi.GOARCH {
|
||||
return sset.cconv(s)
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("SC???%d", s)
|
||||
}
|
||||
|
||||
// CConvARM formats ARM opcode suffix bits (mostly condition codes).
|
||||
func CConvARM(s uint8) string {
|
||||
// TODO: could be great to move suffix-related things into
|
||||
// ARM asm backends some day.
|
||||
// obj/x86 can be used as an example.
|
||||
|
||||
sc := armCondCode[(s&C_SCOND)^C_SCOND_XOR]
|
||||
if s&C_SBIT != 0 {
|
||||
sc += ".S"
|
||||
}
|
||||
if s&C_PBIT != 0 {
|
||||
sc += ".P"
|
||||
}
|
||||
if s&C_WBIT != 0 {
|
||||
sc += ".W"
|
||||
}
|
||||
if s&C_UBIT != 0 { /* ambiguous with FBIT */
|
||||
sc += ".U"
|
||||
}
|
||||
return sc
|
||||
}
|
||||
|
||||
func (p *Prog) String() string {
|
||||
if p == nil {
|
||||
return "<nil Prog>"
|
||||
}
|
||||
if p.Ctxt == nil {
|
||||
return "<Prog without ctxt>"
|
||||
}
|
||||
return fmt.Sprintf("%.5d (%v)\t%s", p.Pc, p.Line(), p.InstructionString())
|
||||
}
|
||||
|
||||
func (p *Prog) InnermostString(w io.Writer) {
|
||||
if p == nil {
|
||||
io.WriteString(w, "<nil Prog>")
|
||||
return
|
||||
}
|
||||
if p.Ctxt == nil {
|
||||
io.WriteString(w, "<Prog without ctxt>")
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(w, "%.5d (", p.Pc)
|
||||
p.InnermostLine(w)
|
||||
io.WriteString(w, ")\t")
|
||||
p.WriteInstructionString(w)
|
||||
}
|
||||
|
||||
// InstructionString returns a string representation of the instruction without preceding
|
||||
// program counter or file and line number.
|
||||
func (p *Prog) InstructionString() string {
|
||||
buf := new(bytes.Buffer)
|
||||
p.WriteInstructionString(buf)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// WriteInstructionString writes a string representation of the instruction without preceding
|
||||
// program counter or file and line number.
|
||||
func (p *Prog) WriteInstructionString(w io.Writer) {
|
||||
if p == nil {
|
||||
io.WriteString(w, "<nil Prog>")
|
||||
return
|
||||
}
|
||||
|
||||
if p.Ctxt == nil {
|
||||
io.WriteString(w, "<Prog without ctxt>")
|
||||
return
|
||||
}
|
||||
|
||||
sc := CConv(p.Scond)
|
||||
|
||||
io.WriteString(w, p.As.String())
|
||||
io.WriteString(w, sc)
|
||||
sep := "\t"
|
||||
|
||||
if p.From.Type != TYPE_NONE {
|
||||
io.WriteString(w, sep)
|
||||
WriteDconv(w, p, &p.From)
|
||||
sep = ", "
|
||||
}
|
||||
if p.Reg != REG_NONE {
|
||||
// Should not happen but might as well show it if it does.
|
||||
fmt.Fprintf(w, "%s%v", sep, Rconv(int(p.Reg)))
|
||||
sep = ", "
|
||||
}
|
||||
for i := range p.RestArgs {
|
||||
io.WriteString(w, sep)
|
||||
WriteDconv(w, p, &p.RestArgs[i])
|
||||
sep = ", "
|
||||
}
|
||||
|
||||
if p.As == ATEXT {
|
||||
// If there are attributes, print them. Otherwise, skip the comma.
|
||||
// In short, print one of these two:
|
||||
// TEXT foo(SB), DUPOK|NOSPLIT, $0
|
||||
// TEXT foo(SB), $0
|
||||
s := p.From.Sym.Attribute.TextAttrString()
|
||||
if s != "" {
|
||||
fmt.Fprintf(w, "%s%s", sep, s)
|
||||
sep = ", "
|
||||
}
|
||||
}
|
||||
if p.To.Type != TYPE_NONE {
|
||||
io.WriteString(w, sep)
|
||||
WriteDconv(w, p, &p.To)
|
||||
}
|
||||
if p.RegTo2 != REG_NONE {
|
||||
fmt.Fprintf(w, "%s%v", sep, Rconv(int(p.RegTo2)))
|
||||
}
|
||||
}
|
||||
|
||||
func (ctxt *Link) NewProg() *Prog {
|
||||
p := new(Prog)
|
||||
p.Ctxt = ctxt
|
||||
return p
|
||||
}
|
||||
|
||||
func (ctxt *Link) CanReuseProgs() bool {
|
||||
return ctxt.Debugasm == 0
|
||||
}
|
||||
|
||||
func Dconv(p *Prog, a *Addr) string {
|
||||
buf := new(bytes.Buffer)
|
||||
WriteDconv(buf, p, a)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func WriteDconv(w io.Writer, p *Prog, a *Addr) {
|
||||
switch a.Type {
|
||||
default:
|
||||
fmt.Fprintf(w, "type=%d", a.Type)
|
||||
|
||||
case TYPE_NONE:
|
||||
if a.Name != NAME_NONE || a.Reg != 0 || a.Sym != nil {
|
||||
a.WriteNameTo(w)
|
||||
fmt.Fprintf(w, "(%v)(NONE)", Rconv(int(a.Reg)))
|
||||
}
|
||||
|
||||
case TYPE_REG:
|
||||
// TODO(rsc): This special case is for x86 instructions like
|
||||
// PINSRQ CX,$1,X6
|
||||
// where the $1 is included in the p->to Addr.
|
||||
// Move into a new field.
|
||||
if a.Offset != 0 && (a.Reg < RBaseARM64 || a.Reg >= RBaseMIPS) {
|
||||
fmt.Fprintf(w, "$%d,%v", a.Offset, Rconv(int(a.Reg)))
|
||||
return
|
||||
}
|
||||
|
||||
if a.Name != NAME_NONE || a.Sym != nil {
|
||||
a.WriteNameTo(w)
|
||||
fmt.Fprintf(w, "(%v)(REG)", Rconv(int(a.Reg)))
|
||||
} else {
|
||||
io.WriteString(w, Rconv(int(a.Reg)))
|
||||
}
|
||||
if (RBaseARM64+1<<10+1<<9) /* arm64.REG_ELEM */ <= a.Reg &&
|
||||
a.Reg < (RBaseARM64+1<<11) /* arm64.REG_ELEM_END */ {
|
||||
fmt.Fprintf(w, "[%d]", a.Index)
|
||||
}
|
||||
|
||||
case TYPE_BRANCH:
|
||||
if a.Sym != nil {
|
||||
fmt.Fprintf(w, "%s(SB)", a.Sym.Name)
|
||||
} else if a.Target() != nil {
|
||||
fmt.Fprint(w, a.Target().Pc)
|
||||
} else {
|
||||
fmt.Fprintf(w, "%d(PC)", a.Offset)
|
||||
}
|
||||
|
||||
case TYPE_INDIR:
|
||||
io.WriteString(w, "*")
|
||||
a.WriteNameTo(w)
|
||||
|
||||
case TYPE_MEM:
|
||||
a.WriteNameTo(w)
|
||||
if a.Index != REG_NONE {
|
||||
if a.Scale == 0 {
|
||||
// arm64 shifted or extended register offset, scale = 0.
|
||||
fmt.Fprintf(w, "(%v)", Rconv(int(a.Index)))
|
||||
} else {
|
||||
fmt.Fprintf(w, "(%v*%d)", Rconv(int(a.Index)), int(a.Scale))
|
||||
}
|
||||
}
|
||||
|
||||
case TYPE_CONST:
|
||||
io.WriteString(w, "$")
|
||||
a.WriteNameTo(w)
|
||||
if a.Reg != 0 {
|
||||
fmt.Fprintf(w, "(%v)", Rconv(int(a.Reg)))
|
||||
}
|
||||
|
||||
case TYPE_TEXTSIZE:
|
||||
if a.Val.(int32) == objabi.ArgsSizeUnknown {
|
||||
fmt.Fprintf(w, "$%d", a.Offset)
|
||||
} else {
|
||||
fmt.Fprintf(w, "$%d-%d", a.Offset, a.Val.(int32))
|
||||
}
|
||||
|
||||
case TYPE_FCONST:
|
||||
str := fmt.Sprintf("%.17g", a.Val.(float64))
|
||||
// Make sure 1 prints as 1.0
|
||||
if !strings.ContainsAny(str, ".e") {
|
||||
str += ".0"
|
||||
}
|
||||
fmt.Fprintf(w, "$(%s)", str)
|
||||
|
||||
case TYPE_SCONST:
|
||||
fmt.Fprintf(w, "$%q", a.Val.(string))
|
||||
|
||||
case TYPE_ADDR:
|
||||
io.WriteString(w, "$")
|
||||
a.WriteNameTo(w)
|
||||
|
||||
case TYPE_SHIFT:
|
||||
v := int(a.Offset)
|
||||
ops := "<<>>->@>"
|
||||
switch objabi.GOARCH {
|
||||
case "arm":
|
||||
op := ops[((v>>5)&3)<<1:]
|
||||
if v&(1<<4) != 0 {
|
||||
fmt.Fprintf(w, "R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15)
|
||||
} else {
|
||||
fmt.Fprintf(w, "R%d%c%c%d", v&15, op[0], op[1], (v>>7)&31)
|
||||
}
|
||||
if a.Reg != 0 {
|
||||
fmt.Fprintf(w, "(%v)", Rconv(int(a.Reg)))
|
||||
}
|
||||
case "arm64":
|
||||
op := ops[((v>>22)&3)<<1:]
|
||||
r := (v >> 16) & 31
|
||||
fmt.Fprintf(w, "%s%c%c%d", Rconv(r+RBaseARM64), op[0], op[1], (v>>10)&63)
|
||||
default:
|
||||
panic("TYPE_SHIFT is not supported on " + objabi.GOARCH)
|
||||
}
|
||||
|
||||
case TYPE_REGREG:
|
||||
fmt.Fprintf(w, "(%v, %v)", Rconv(int(a.Reg)), Rconv(int(a.Offset)))
|
||||
|
||||
case TYPE_REGREG2:
|
||||
fmt.Fprintf(w, "%v, %v", Rconv(int(a.Offset)), Rconv(int(a.Reg)))
|
||||
|
||||
case TYPE_REGLIST:
|
||||
io.WriteString(w, RLconv(a.Offset))
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Addr) WriteNameTo(w io.Writer) {
|
||||
switch a.Name {
|
||||
default:
|
||||
fmt.Fprintf(w, "name=%d", a.Name)
|
||||
|
||||
case NAME_NONE:
|
||||
switch {
|
||||
case a.Reg == REG_NONE:
|
||||
fmt.Fprint(w, a.Offset)
|
||||
case a.Offset == 0:
|
||||
fmt.Fprintf(w, "(%v)", Rconv(int(a.Reg)))
|
||||
case a.Offset != 0:
|
||||
fmt.Fprintf(w, "%d(%v)", a.Offset, Rconv(int(a.Reg)))
|
||||
}
|
||||
|
||||
// Note: a.Reg == REG_NONE encodes the default base register for the NAME_ type.
|
||||
case NAME_EXTERN:
|
||||
reg := "SB"
|
||||
if a.Reg != REG_NONE {
|
||||
reg = Rconv(int(a.Reg))
|
||||
}
|
||||
if a.Sym != nil {
|
||||
fmt.Fprintf(w, "%s%s(%s)", a.Sym.Name, offConv(a.Offset), reg)
|
||||
} else {
|
||||
fmt.Fprintf(w, "%s(%s)", offConv(a.Offset), reg)
|
||||
}
|
||||
|
||||
case NAME_GOTREF:
|
||||
reg := "SB"
|
||||
if a.Reg != REG_NONE {
|
||||
reg = Rconv(int(a.Reg))
|
||||
}
|
||||
if a.Sym != nil {
|
||||
fmt.Fprintf(w, "%s%s@GOT(%s)", a.Sym.Name, offConv(a.Offset), reg)
|
||||
} else {
|
||||
fmt.Fprintf(w, "%s@GOT(%s)", offConv(a.Offset), reg)
|
||||
}
|
||||
|
||||
case NAME_STATIC:
|
||||
reg := "SB"
|
||||
if a.Reg != REG_NONE {
|
||||
reg = Rconv(int(a.Reg))
|
||||
}
|
||||
if a.Sym != nil {
|
||||
fmt.Fprintf(w, "%s<>%s(%s)", a.Sym.Name, offConv(a.Offset), reg)
|
||||
} else {
|
||||
fmt.Fprintf(w, "<>%s(%s)", offConv(a.Offset), reg)
|
||||
}
|
||||
|
||||
case NAME_AUTO:
|
||||
reg := "SP"
|
||||
if a.Reg != REG_NONE {
|
||||
reg = Rconv(int(a.Reg))
|
||||
}
|
||||
if a.Sym != nil {
|
||||
fmt.Fprintf(w, "%s%s(%s)", a.Sym.Name, offConv(a.Offset), reg)
|
||||
} else {
|
||||
fmt.Fprintf(w, "%s(%s)", offConv(a.Offset), reg)
|
||||
}
|
||||
|
||||
case NAME_PARAM:
|
||||
reg := "FP"
|
||||
if a.Reg != REG_NONE {
|
||||
reg = Rconv(int(a.Reg))
|
||||
}
|
||||
if a.Sym != nil {
|
||||
fmt.Fprintf(w, "%s%s(%s)", a.Sym.Name, offConv(a.Offset), reg)
|
||||
} else {
|
||||
fmt.Fprintf(w, "%s(%s)", offConv(a.Offset), reg)
|
||||
}
|
||||
case NAME_TOCREF:
|
||||
reg := "SB"
|
||||
if a.Reg != REG_NONE {
|
||||
reg = Rconv(int(a.Reg))
|
||||
}
|
||||
if a.Sym != nil {
|
||||
fmt.Fprintf(w, "%s%s(%s)", a.Sym.Name, offConv(a.Offset), reg)
|
||||
} else {
|
||||
fmt.Fprintf(w, "%s(%s)", offConv(a.Offset), reg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func offConv(off int64) string {
|
||||
if off == 0 {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("%+d", off)
|
||||
}
|
||||
|
||||
// opSuffixSet is like regListSet, but for opcode suffixes.
|
||||
//
|
||||
// Unlike some other similar structures, uint8 space is not
|
||||
// divided by its own values set (because there are only 256 of them).
|
||||
// Instead, every arch may interpret/format all 8 bits as they like,
|
||||
// as long as they register proper cconv function for it.
|
||||
type opSuffixSet struct {
|
||||
arch string
|
||||
cconv func(suffix uint8) string
|
||||
}
|
||||
|
||||
var opSuffixSpace []opSuffixSet
|
||||
|
||||
// RegisterOpSuffix assigns cconv function for formatting opcode suffixes
|
||||
// when compiling for GOARCH=arch.
|
||||
//
|
||||
// cconv is never called with 0 argument.
|
||||
func RegisterOpSuffix(arch string, cconv func(uint8) string) {
|
||||
opSuffixSpace = append(opSuffixSpace, opSuffixSet{
|
||||
arch: arch,
|
||||
cconv: cconv,
|
||||
})
|
||||
}
|
||||
|
||||
type regSet struct {
|
||||
lo int
|
||||
hi int
|
||||
Rconv func(int) string
|
||||
}
|
||||
|
||||
// Few enough architectures that a linear scan is fastest.
|
||||
// Not even worth sorting.
|
||||
var regSpace []regSet
|
||||
|
||||
/*
|
||||
Each architecture defines a register space as a unique
|
||||
integer range.
|
||||
Here is the list of architectures and the base of their register spaces.
|
||||
*/
|
||||
|
||||
const (
|
||||
// Because of masking operations in the encodings, each register
|
||||
// space should start at 0 modulo some power of 2.
|
||||
RBase386 = 1 * 1024
|
||||
RBaseAMD64 = 2 * 1024
|
||||
RBaseARM = 3 * 1024
|
||||
RBasePPC64 = 4 * 1024 // range [4k, 8k)
|
||||
RBaseARM64 = 8 * 1024 // range [8k, 13k)
|
||||
RBaseMIPS = 13 * 1024 // range [13k, 14k)
|
||||
RBaseS390X = 14 * 1024 // range [14k, 15k)
|
||||
RBaseRISCV = 15 * 1024 // range [15k, 16k)
|
||||
RBaseWasm = 16 * 1024
|
||||
)
|
||||
|
||||
// RegisterRegister binds a pretty-printer (Rconv) for register
|
||||
// numbers to a given register number range. Lo is inclusive,
|
||||
// hi exclusive (valid registers are lo through hi-1).
|
||||
func RegisterRegister(lo, hi int, Rconv func(int) string) {
|
||||
regSpace = append(regSpace, regSet{lo, hi, Rconv})
|
||||
}
|
||||
|
||||
func Rconv(reg int) string {
|
||||
if reg == REG_NONE {
|
||||
return "NONE"
|
||||
}
|
||||
for i := range regSpace {
|
||||
rs := ®Space[i]
|
||||
if rs.lo <= reg && reg < rs.hi {
|
||||
return rs.Rconv(reg)
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("R???%d", reg)
|
||||
}
|
||||
|
||||
type regListSet struct {
|
||||
lo int64
|
||||
hi int64
|
||||
RLconv func(int64) string
|
||||
}
|
||||
|
||||
var regListSpace []regListSet
|
||||
|
||||
// Each architecture is allotted a distinct subspace: [Lo, Hi) for declaring its
|
||||
// arch-specific register list numbers.
|
||||
const (
|
||||
RegListARMLo = 0
|
||||
RegListARMHi = 1 << 16
|
||||
|
||||
// arm64 uses the 60th bit to differentiate from other archs
|
||||
RegListARM64Lo = 1 << 60
|
||||
RegListARM64Hi = 1<<61 - 1
|
||||
|
||||
// x86 uses the 61th bit to differentiate from other archs
|
||||
RegListX86Lo = 1 << 61
|
||||
RegListX86Hi = 1<<62 - 1
|
||||
)
|
||||
|
||||
// RegisterRegisterList binds a pretty-printer (RLconv) for register list
|
||||
// numbers to a given register list number range. Lo is inclusive,
|
||||
// hi exclusive (valid register list are lo through hi-1).
|
||||
func RegisterRegisterList(lo, hi int64, rlconv func(int64) string) {
|
||||
regListSpace = append(regListSpace, regListSet{lo, hi, rlconv})
|
||||
}
|
||||
|
||||
func RLconv(list int64) string {
|
||||
for i := range regListSpace {
|
||||
rls := ®ListSpace[i]
|
||||
if rls.lo <= list && list < rls.hi {
|
||||
return rls.RLconv(list)
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("RL???%d", list)
|
||||
}
|
||||
|
||||
type opSet struct {
|
||||
lo As
|
||||
names []string
|
||||
}
|
||||
|
||||
// Not even worth sorting
|
||||
var aSpace []opSet
|
||||
|
||||
// RegisterOpcode binds a list of instruction names
|
||||
// to a given instruction number range.
|
||||
func RegisterOpcode(lo As, Anames []string) {
|
||||
if len(Anames) > AllowedOpCodes {
|
||||
panic(fmt.Sprintf("too many instructions, have %d max %d", len(Anames), AllowedOpCodes))
|
||||
}
|
||||
aSpace = append(aSpace, opSet{lo, Anames})
|
||||
}
|
||||
|
||||
func (a As) String() string {
|
||||
if 0 <= a && int(a) < len(Anames) {
|
||||
return Anames[a]
|
||||
}
|
||||
for i := range aSpace {
|
||||
as := &aSpace[i]
|
||||
if as.lo <= a && int(a-as.lo) < len(as.names) {
|
||||
return as.names[a-as.lo]
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("A???%d", a)
|
||||
}
|
||||
|
||||
var Anames = []string{
|
||||
"XXX",
|
||||
"CALL",
|
||||
"DUFFCOPY",
|
||||
"DUFFZERO",
|
||||
"END",
|
||||
"FUNCDATA",
|
||||
"JMP",
|
||||
"NOP",
|
||||
"PCALIGN",
|
||||
"PCDATA",
|
||||
"RET",
|
||||
"GETCALLERPC",
|
||||
"TEXT",
|
||||
"UNDEF",
|
||||
}
|
||||
|
||||
func Bool2int(b bool) int {
|
||||
// The compiler currently only optimizes this form.
|
||||
// See issue 6011.
|
||||
var i int
|
||||
if b {
|
||||
i = 1
|
||||
} else {
|
||||
i = 0
|
||||
}
|
||||
return i
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue