mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-11-07 13:39:32 -06:00
[chore]: Bump github.com/gin-contrib/gzip from 1.0.0 to 1.0.1 (#2899)
Bumps [github.com/gin-contrib/gzip](https://github.com/gin-contrib/gzip) from 1.0.0 to 1.0.1. - [Release notes](https://github.com/gin-contrib/gzip/releases) - [Changelog](https://github.com/gin-contrib/gzip/blob/master/.goreleaser.yaml) - [Commits](https://github.com/gin-contrib/gzip/compare/v1.0.0...v1.0.1) --- updated-dependencies: - dependency-name: github.com/gin-contrib/gzip dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
parent
c98ec6f89d
commit
a5f28fe0c9
372 changed files with 130601 additions and 52424 deletions
584
vendor/github.com/cloudwego/iasm/x86_64/program.go
generated
vendored
Normal file
584
vendor/github.com/cloudwego/iasm/x86_64/program.go
generated
vendored
Normal file
|
|
@ -0,0 +1,584 @@
|
|||
//
|
||||
// Copyright 2024 CloudWeGo Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
package x86_64
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/bits"
|
||||
|
||||
"github.com/cloudwego/iasm/expr"
|
||||
)
|
||||
|
||||
type (
|
||||
_PseudoType int
|
||||
_InstructionEncoder func(*Program, ...interface{}) *Instruction
|
||||
)
|
||||
|
||||
const (
|
||||
_PseudoNop _PseudoType = iota + 1
|
||||
_PseudoByte
|
||||
_PseudoWord
|
||||
_PseudoLong
|
||||
_PseudoQuad
|
||||
_PseudoData
|
||||
_PseudoAlign
|
||||
)
|
||||
|
||||
func (self _PseudoType) String() string {
|
||||
switch self {
|
||||
case _PseudoNop:
|
||||
return ".nop"
|
||||
case _PseudoByte:
|
||||
return ".byte"
|
||||
case _PseudoWord:
|
||||
return ".word"
|
||||
case _PseudoLong:
|
||||
return ".long"
|
||||
case _PseudoQuad:
|
||||
return ".quad"
|
||||
case _PseudoData:
|
||||
return ".data"
|
||||
case _PseudoAlign:
|
||||
return ".align"
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
type _Pseudo struct {
|
||||
kind _PseudoType
|
||||
data []byte
|
||||
uint uint64
|
||||
expr *expr.Expr
|
||||
}
|
||||
|
||||
func (self *_Pseudo) free() {
|
||||
if self.expr != nil {
|
||||
self.expr.Free()
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_Pseudo) encode(m *[]byte, pc uintptr) int {
|
||||
switch self.kind {
|
||||
case _PseudoNop:
|
||||
return 0
|
||||
case _PseudoByte:
|
||||
self.encodeByte(m)
|
||||
return 1
|
||||
case _PseudoWord:
|
||||
self.encodeWord(m)
|
||||
return 2
|
||||
case _PseudoLong:
|
||||
self.encodeLong(m)
|
||||
return 4
|
||||
case _PseudoQuad:
|
||||
self.encodeQuad(m)
|
||||
return 8
|
||||
case _PseudoData:
|
||||
self.encodeData(m)
|
||||
return len(self.data)
|
||||
case _PseudoAlign:
|
||||
self.encodeAlign(m, pc)
|
||||
return self.alignSize(pc)
|
||||
default:
|
||||
panic("invalid pseudo instruction")
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_Pseudo) evalExpr(low int64, high int64) int64 {
|
||||
if v, err := self.expr.Evaluate(); err != nil {
|
||||
panic(err)
|
||||
} else if v < low || v > high {
|
||||
panic(fmt.Sprintf("expression out of range [%d, %d]: %d", low, high, v))
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_Pseudo) alignSize(pc uintptr) int {
|
||||
if !ispow2(self.uint) {
|
||||
panic(fmt.Sprintf("aligment should be a power of 2, not %d", self.uint))
|
||||
} else {
|
||||
return align(int(pc), bits.TrailingZeros64(self.uint)) - int(pc)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_Pseudo) encodeData(m *[]byte) {
|
||||
if m != nil {
|
||||
*m = append(*m, self.data...)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_Pseudo) encodeByte(m *[]byte) {
|
||||
if m != nil {
|
||||
append8(m, byte(self.evalExpr(math.MinInt8, math.MaxUint8)))
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_Pseudo) encodeWord(m *[]byte) {
|
||||
if m != nil {
|
||||
append16(m, uint16(self.evalExpr(math.MinInt16, math.MaxUint16)))
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_Pseudo) encodeLong(m *[]byte) {
|
||||
if m != nil {
|
||||
append32(m, uint32(self.evalExpr(math.MinInt32, math.MaxUint32)))
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_Pseudo) encodeQuad(m *[]byte) {
|
||||
if m != nil {
|
||||
if v, err := self.expr.Evaluate(); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
append64(m, uint64(v))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_Pseudo) encodeAlign(m *[]byte, pc uintptr) {
|
||||
if m != nil {
|
||||
if self.expr == nil {
|
||||
expandmm(m, self.alignSize(pc), 0)
|
||||
} else {
|
||||
expandmm(m, self.alignSize(pc), byte(self.evalExpr(math.MinInt8, math.MaxUint8)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Operands represents a sequence of operand required by an instruction.
|
||||
type Operands [_N_args]interface{}
|
||||
|
||||
// InstructionDomain represents the domain of an instruction.
|
||||
type InstructionDomain uint8
|
||||
|
||||
const (
|
||||
DomainGeneric InstructionDomain = iota
|
||||
DomainMMXSSE
|
||||
DomainAVX
|
||||
DomainFMA
|
||||
DomainCrypto
|
||||
DomainMask
|
||||
DomainAMDSpecific
|
||||
DomainMisc
|
||||
DomainPseudo
|
||||
)
|
||||
|
||||
type (
|
||||
_BranchType uint8
|
||||
)
|
||||
|
||||
const (
|
||||
_B_none _BranchType = iota
|
||||
_B_conditional
|
||||
_B_unconditional
|
||||
)
|
||||
|
||||
// Instruction represents an unencoded instruction.
|
||||
type Instruction struct {
|
||||
next *Instruction
|
||||
pc uintptr
|
||||
nb int
|
||||
len int
|
||||
argc int
|
||||
name string
|
||||
argv Operands
|
||||
forms [_N_forms]_Encoding
|
||||
pseudo _Pseudo
|
||||
branch _BranchType
|
||||
domain InstructionDomain
|
||||
prefix []byte
|
||||
}
|
||||
|
||||
func (self *Instruction) add(flags int, encoder func(m *_Encoding, v []interface{})) {
|
||||
self.forms[self.len].flags = flags
|
||||
self.forms[self.len].encoder = encoder
|
||||
self.len++
|
||||
}
|
||||
|
||||
func (self *Instruction) free() {
|
||||
self.clear()
|
||||
self.pseudo.free()
|
||||
//freeInstruction(self)
|
||||
}
|
||||
|
||||
func (self *Instruction) clear() {
|
||||
for i := 0; i < self.argc; i++ {
|
||||
if v, ok := self.argv[i].(Disposable); ok {
|
||||
v.Free()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Instruction) check(e *_Encoding) bool {
|
||||
if (e.flags & _F_rel1) != 0 {
|
||||
return isRel8(self.argv[0])
|
||||
} else if (e.flags & _F_rel4) != 0 {
|
||||
return isRel32(self.argv[0]) || isLabel(self.argv[0])
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Instruction) encode(m *[]byte) int {
|
||||
n := math.MaxInt64
|
||||
p := (*_Encoding)(nil)
|
||||
|
||||
/* encode prefixes if any */
|
||||
if self.nb = len(self.prefix); m != nil {
|
||||
*m = append(*m, self.prefix...)
|
||||
}
|
||||
|
||||
/* check for pseudo-instructions */
|
||||
if self.pseudo.kind != 0 {
|
||||
self.nb += self.pseudo.encode(m, self.pc)
|
||||
return self.nb
|
||||
}
|
||||
|
||||
/* find the shortest encoding */
|
||||
for i := 0; i < self.len; i++ {
|
||||
if e := &self.forms[i]; self.check(e) {
|
||||
if v := e.encode(self.argv[:self.argc]); v < n {
|
||||
n = v
|
||||
p = e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* add to buffer if needed */
|
||||
if m != nil {
|
||||
*m = append(*m, p.bytes[:n]...)
|
||||
}
|
||||
|
||||
/* update the instruction length */
|
||||
self.nb += n
|
||||
return self.nb
|
||||
}
|
||||
|
||||
/** Instruction Prefixes **/
|
||||
|
||||
const (
|
||||
_P_cs = 0x2e
|
||||
_P_ds = 0x3e
|
||||
_P_es = 0x26
|
||||
_P_fs = 0x64
|
||||
_P_gs = 0x65
|
||||
_P_ss = 0x36
|
||||
_P_lock = 0xf0
|
||||
)
|
||||
|
||||
// CS overrides the memory operation of this instruction to CS.
|
||||
func (self *Instruction) CS() *Instruction {
|
||||
self.prefix = append(self.prefix, _P_cs)
|
||||
return self
|
||||
}
|
||||
|
||||
// DS overrides the memory operation of this instruction to DS,
|
||||
// this is the default section for most instructions if not specified.
|
||||
func (self *Instruction) DS() *Instruction {
|
||||
self.prefix = append(self.prefix, _P_ds)
|
||||
return self
|
||||
}
|
||||
|
||||
// ES overrides the memory operation of this instruction to ES.
|
||||
func (self *Instruction) ES() *Instruction {
|
||||
self.prefix = append(self.prefix, _P_es)
|
||||
return self
|
||||
}
|
||||
|
||||
// FS overrides the memory operation of this instruction to FS.
|
||||
func (self *Instruction) FS() *Instruction {
|
||||
self.prefix = append(self.prefix, _P_fs)
|
||||
return self
|
||||
}
|
||||
|
||||
// GS overrides the memory operation of this instruction to GS.
|
||||
func (self *Instruction) GS() *Instruction {
|
||||
self.prefix = append(self.prefix, _P_gs)
|
||||
return self
|
||||
}
|
||||
|
||||
// SS overrides the memory operation of this instruction to SS.
|
||||
func (self *Instruction) SS() *Instruction {
|
||||
self.prefix = append(self.prefix, _P_ss)
|
||||
return self
|
||||
}
|
||||
|
||||
// LOCK causes the processor's LOCK# signal to be asserted during execution of
|
||||
// the accompanying instruction (turns the instruction into an atomic instruction).
|
||||
// In a multiprocessor environment, the LOCK# signal insures that the processor
|
||||
// has exclusive use of any shared memory while the signal is asserted.
|
||||
func (self *Instruction) LOCK() *Instruction {
|
||||
self.prefix = append(self.prefix, _P_lock)
|
||||
return self
|
||||
}
|
||||
|
||||
/** Basic Instruction Properties **/
|
||||
|
||||
// Name returns the instruction name.
|
||||
func (self *Instruction) Name() string {
|
||||
return self.name
|
||||
}
|
||||
|
||||
// Domain returns the domain of this instruction.
|
||||
func (self *Instruction) Domain() InstructionDomain {
|
||||
return self.domain
|
||||
}
|
||||
|
||||
// Operands returns the operands of this instruction.
|
||||
func (self *Instruction) Operands() []interface{} {
|
||||
return self.argv[:self.argc]
|
||||
}
|
||||
|
||||
// Program represents a sequence of instructions.
|
||||
type Program struct {
|
||||
arch *Arch
|
||||
head *Instruction
|
||||
tail *Instruction
|
||||
}
|
||||
|
||||
const (
|
||||
_N_near = 2 // near-branch (-128 ~ +127) takes 2 bytes to encode
|
||||
_N_far_cond = 6 // conditional far-branch takes 6 bytes to encode
|
||||
_N_far_uncond = 5 // unconditional far-branch takes 5 bytes to encode
|
||||
)
|
||||
|
||||
func (self *Program) clear() {
|
||||
for p, q := self.head, self.head; p != nil; p = q {
|
||||
q = p.next
|
||||
p.free()
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Program) alloc(name string, argc int, argv Operands) *Instruction {
|
||||
p := self.tail
|
||||
q := newInstruction(name, argc, argv)
|
||||
|
||||
/* attach to tail if any */
|
||||
if p != nil {
|
||||
p.next = q
|
||||
} else {
|
||||
self.head = q
|
||||
}
|
||||
|
||||
/* set the new tail */
|
||||
self.tail = q
|
||||
return q
|
||||
}
|
||||
|
||||
func (self *Program) pseudo(kind _PseudoType) (p *Instruction) {
|
||||
p = self.alloc(kind.String(), 0, Operands{})
|
||||
p.domain = DomainPseudo
|
||||
p.pseudo.kind = kind
|
||||
return
|
||||
}
|
||||
|
||||
func (self *Program) require(isa ISA) {
|
||||
if !self.arch.HasISA(isa) {
|
||||
panic("ISA '" + isa.String() + "' was not enabled")
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Program) branchSize(p *Instruction) int {
|
||||
switch p.branch {
|
||||
case _B_none:
|
||||
panic("p is not a branch")
|
||||
case _B_conditional:
|
||||
return _N_far_cond
|
||||
case _B_unconditional:
|
||||
return _N_far_uncond
|
||||
default:
|
||||
panic("invalid instruction")
|
||||
}
|
||||
}
|
||||
|
||||
/** Pseudo-Instructions **/
|
||||
|
||||
// Byte is a pseudo-instruction to add raw byte to the assembled code.
|
||||
func (self *Program) Byte(v *expr.Expr) (p *Instruction) {
|
||||
p = self.pseudo(_PseudoByte)
|
||||
p.pseudo.expr = v
|
||||
return
|
||||
}
|
||||
|
||||
// Word is a pseudo-instruction to add raw uint16 as little-endian to the assembled code.
|
||||
func (self *Program) Word(v *expr.Expr) (p *Instruction) {
|
||||
p = self.pseudo(_PseudoWord)
|
||||
p.pseudo.expr = v
|
||||
return
|
||||
}
|
||||
|
||||
// Long is a pseudo-instruction to add raw uint32 as little-endian to the assembled code.
|
||||
func (self *Program) Long(v *expr.Expr) (p *Instruction) {
|
||||
p = self.pseudo(_PseudoLong)
|
||||
p.pseudo.expr = v
|
||||
return
|
||||
}
|
||||
|
||||
// Quad is a pseudo-instruction to add raw uint64 as little-endian to the assembled code.
|
||||
func (self *Program) Quad(v *expr.Expr) (p *Instruction) {
|
||||
p = self.pseudo(_PseudoQuad)
|
||||
p.pseudo.expr = v
|
||||
return
|
||||
}
|
||||
|
||||
// Data is a pseudo-instruction to add raw bytes to the assembled code.
|
||||
func (self *Program) Data(v []byte) (p *Instruction) {
|
||||
p = self.pseudo(_PseudoData)
|
||||
p.pseudo.data = v
|
||||
return
|
||||
}
|
||||
|
||||
// Align is a pseudo-instruction to ensure the PC is aligned to a certain value.
|
||||
func (self *Program) Align(align uint64, padding *expr.Expr) (p *Instruction) {
|
||||
p = self.pseudo(_PseudoAlign)
|
||||
p.pseudo.uint = align
|
||||
p.pseudo.expr = padding
|
||||
return
|
||||
}
|
||||
|
||||
/** Program Assembler **/
|
||||
|
||||
// Free returns the Program object into pool.
|
||||
// Any operation performed after Free is undefined behavior.
|
||||
//
|
||||
// NOTE: This also frees all the instructions, labels, memory
|
||||
//
|
||||
// operands and expressions associated with this program.
|
||||
func (self *Program) Free() {
|
||||
self.clear()
|
||||
//freeProgram(self)
|
||||
}
|
||||
|
||||
// Link pins a label at the current position.
|
||||
func (self *Program) Link(p *Label) {
|
||||
if p.Dest != nil {
|
||||
panic("lable was alreay linked")
|
||||
} else {
|
||||
p.Dest = self.pseudo(_PseudoNop)
|
||||
}
|
||||
}
|
||||
|
||||
// Assemble assembles and links the entire program into machine code.
|
||||
func (self *Program) Assemble(pc uintptr) (ret []byte) {
|
||||
orig := pc
|
||||
next := true
|
||||
offs := uintptr(0)
|
||||
|
||||
/* Pass 0: PC-precompute, assume all labeled branches are far-branches. */
|
||||
for p := self.head; p != nil; p = p.next {
|
||||
if p.pc = pc; !isLabel(p.argv[0]) || p.branch == _B_none {
|
||||
pc += uintptr(p.encode(nil))
|
||||
} else {
|
||||
pc += uintptr(self.branchSize(p))
|
||||
}
|
||||
}
|
||||
|
||||
/* allocate space for the machine code */
|
||||
nb := int(pc - orig)
|
||||
ret = make([]byte, 0, nb)
|
||||
|
||||
/* Pass 1: adjust all the jumps */
|
||||
for next {
|
||||
next = false
|
||||
offs = uintptr(0)
|
||||
|
||||
/* scan all the branches */
|
||||
for p := self.head; p != nil; p = p.next {
|
||||
var ok bool
|
||||
var lb *Label
|
||||
|
||||
/* re-calculate the alignment here */
|
||||
if nb = p.nb; p.pseudo.kind == _PseudoAlign {
|
||||
p.pc -= offs
|
||||
offs += uintptr(nb - p.encode(nil))
|
||||
continue
|
||||
}
|
||||
|
||||
/* adjust the program counter */
|
||||
p.pc -= offs
|
||||
lb, ok = p.argv[0].(*Label)
|
||||
|
||||
/* only care about labeled far-branches */
|
||||
if !ok || p.nb == _N_near || p.branch == _B_none {
|
||||
continue
|
||||
}
|
||||
|
||||
/* calculate the jump offset */
|
||||
size := self.branchSize(p)
|
||||
diff := lb.offset(p.pc, size)
|
||||
|
||||
/* too far to be a near jump */
|
||||
if diff > 127 || diff < -128 {
|
||||
p.nb = size
|
||||
continue
|
||||
}
|
||||
|
||||
/* a far jump becomes a near jump, calculate
|
||||
* the PC adjustment value and assemble again */
|
||||
next = true
|
||||
p.nb = _N_near
|
||||
offs += uintptr(size - _N_near)
|
||||
}
|
||||
}
|
||||
|
||||
/* Pass 3: link all the cross-references */
|
||||
for p := self.head; p != nil; p = p.next {
|
||||
for i := 0; i < p.argc; i++ {
|
||||
var ok bool
|
||||
var lb *Label
|
||||
var op *MemoryOperand
|
||||
|
||||
/* resolve labels */
|
||||
if lb, ok = p.argv[i].(*Label); ok {
|
||||
p.argv[i] = lb.offset(p.pc, p.nb)
|
||||
continue
|
||||
}
|
||||
|
||||
/* check for memory operands */
|
||||
if op, ok = p.argv[i].(*MemoryOperand); !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
/* check for label references */
|
||||
if op.Addr.Type != Reference {
|
||||
continue
|
||||
}
|
||||
|
||||
/* replace the label with the real offset */
|
||||
op.Addr.Type = Offset
|
||||
op.Addr.Offset = op.Addr.Reference.offset(p.pc, p.nb)
|
||||
}
|
||||
}
|
||||
|
||||
/* Pass 4: actually encode all the instructions */
|
||||
for p := self.head; p != nil; p = p.next {
|
||||
p.encode(&ret)
|
||||
}
|
||||
|
||||
/* all done */
|
||||
return ret
|
||||
}
|
||||
|
||||
// AssembleAndFree is like Assemble, but it frees the Program after assembling.
|
||||
func (self *Program) AssembleAndFree(pc uintptr) (ret []byte) {
|
||||
ret = self.Assemble(pc)
|
||||
self.Free()
|
||||
return
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue