compiler: update integer type sizes
* Use 64-bit integers on 64-bit platforms, just like gc and gccgo: https://golang.org/doc/go1.1#int * Do not use a separate length type. Instead, use uintptr everywhere a length is expected.
Этот коммит содержится в:
родитель
101d41dc58
коммит
ee7c276493
10 изменённых файлов: 68 добавлений и 80 удалений
|
@ -54,7 +54,6 @@ type Compiler struct {
|
||||||
intType llvm.Type
|
intType llvm.Type
|
||||||
i8ptrType llvm.Type // for convenience
|
i8ptrType llvm.Type // for convenience
|
||||||
uintptrType llvm.Type
|
uintptrType llvm.Type
|
||||||
lenType llvm.Type
|
|
||||||
coroIdFunc llvm.Value
|
coroIdFunc llvm.Value
|
||||||
coroSizeFunc llvm.Value
|
coroSizeFunc llvm.Value
|
||||||
coroBeginFunc llvm.Value
|
coroBeginFunc llvm.Value
|
||||||
|
@ -128,14 +127,15 @@ func NewCompiler(pkgName string, config Config) (*Compiler, error) {
|
||||||
c.builder = c.ctx.NewBuilder()
|
c.builder = c.ctx.NewBuilder()
|
||||||
c.dibuilder = llvm.NewDIBuilder(c.mod)
|
c.dibuilder = llvm.NewDIBuilder(c.mod)
|
||||||
|
|
||||||
// Depends on platform (32bit or 64bit), but fix it here for now.
|
|
||||||
c.intType = c.ctx.Int32Type()
|
|
||||||
c.uintptrType = c.ctx.IntType(c.targetData.PointerSize() * 8)
|
c.uintptrType = c.ctx.IntType(c.targetData.PointerSize() * 8)
|
||||||
if c.targetData.PointerSize() < 4 {
|
if c.targetData.PointerSize() <= 4 {
|
||||||
// 16 or 8 bits target with smaller length type
|
// 8, 16, 32 bits targets
|
||||||
c.lenType = c.uintptrType
|
c.intType = c.ctx.Int32Type()
|
||||||
|
} else if c.targetData.PointerSize() == 8 {
|
||||||
|
// 64 bits target
|
||||||
|
c.intType = c.ctx.Int64Type()
|
||||||
} else {
|
} else {
|
||||||
c.lenType = c.ctx.Int32Type() // also defined as runtime.lenType
|
panic("unknown pointer size")
|
||||||
}
|
}
|
||||||
c.i8ptrType = llvm.PointerType(c.ctx.Int8Type(), 0)
|
c.i8ptrType = llvm.PointerType(c.ctx.Int8Type(), 0)
|
||||||
|
|
||||||
|
@ -668,8 +668,8 @@ func (c *Compiler) getLLVMType(goType types.Type) (llvm.Type, error) {
|
||||||
}
|
}
|
||||||
members := []llvm.Type{
|
members := []llvm.Type{
|
||||||
llvm.PointerType(elemType, 0),
|
llvm.PointerType(elemType, 0),
|
||||||
c.lenType, // len
|
c.uintptrType, // len
|
||||||
c.lenType, // cap
|
c.uintptrType, // cap
|
||||||
}
|
}
|
||||||
return c.ctx.StructType(members, false), nil
|
return c.ctx.StructType(members, false), nil
|
||||||
case *types.Struct:
|
case *types.Struct:
|
||||||
|
@ -1077,12 +1077,12 @@ func (c *Compiler) getInterpretedValue(prefix string, value ir.Value) (llvm.Valu
|
||||||
bucketPtr := llvm.ConstInBoundsGEP(firstBucketGlobal, []llvm.Value{zero})
|
bucketPtr := llvm.ConstInBoundsGEP(firstBucketGlobal, []llvm.Value{zero})
|
||||||
hashmapType := c.mod.GetTypeByName("runtime.hashmap")
|
hashmapType := c.mod.GetTypeByName("runtime.hashmap")
|
||||||
hashmap := llvm.ConstNamedStruct(hashmapType, []llvm.Value{
|
hashmap := llvm.ConstNamedStruct(hashmapType, []llvm.Value{
|
||||||
llvm.ConstPointerNull(llvm.PointerType(hashmapType, 0)), // next
|
llvm.ConstPointerNull(llvm.PointerType(hashmapType, 0)), // next
|
||||||
llvm.ConstBitCast(bucketPtr, c.i8ptrType), // buckets
|
llvm.ConstBitCast(bucketPtr, c.i8ptrType), // buckets
|
||||||
llvm.ConstInt(c.lenType, uint64(len(value.Keys)), false), // count
|
llvm.ConstInt(c.uintptrType, uint64(len(value.Keys)), false), // count
|
||||||
llvm.ConstInt(c.ctx.Int8Type(), keySize, false), // keySize
|
llvm.ConstInt(c.ctx.Int8Type(), keySize, false), // keySize
|
||||||
llvm.ConstInt(c.ctx.Int8Type(), valueSize, false), // valueSize
|
llvm.ConstInt(c.ctx.Int8Type(), valueSize, false), // valueSize
|
||||||
llvm.ConstInt(c.ctx.Int8Type(), 0, false), // bucketBits
|
llvm.ConstInt(c.ctx.Int8Type(), 0, false), // bucketBits
|
||||||
})
|
})
|
||||||
|
|
||||||
// Create a pointer to this hashmap.
|
// Create a pointer to this hashmap.
|
||||||
|
@ -1163,7 +1163,7 @@ func (c *Compiler) getInterpretedValue(prefix string, value ir.Value) (llvm.Valu
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return llvm.Value{}, err
|
return llvm.Value{}, err
|
||||||
}
|
}
|
||||||
llvmLen := llvm.ConstInt(c.lenType, arrayLength, false)
|
llvmLen := llvm.ConstInt(c.uintptrType, arrayLength, false)
|
||||||
slice := llvm.ConstNamedStruct(sliceTyp, []llvm.Value{
|
slice := llvm.ConstNamedStruct(sliceTyp, []llvm.Value{
|
||||||
globalPtr, // ptr
|
globalPtr, // ptr
|
||||||
llvmLen, // len
|
llvmLen, // len
|
||||||
|
@ -2260,7 +2260,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
|
||||||
|
|
||||||
// Check bounds.
|
// Check bounds.
|
||||||
arrayLen := expr.X.Type().(*types.Array).Len()
|
arrayLen := expr.X.Type().(*types.Array).Len()
|
||||||
arrayLenLLVM := llvm.ConstInt(c.lenType, uint64(arrayLen), false)
|
arrayLenLLVM := llvm.ConstInt(c.uintptrType, uint64(arrayLen), false)
|
||||||
c.emitBoundsCheck(frame, arrayLenLLVM, index, expr.Index.Type())
|
c.emitBoundsCheck(frame, arrayLenLLVM, index, expr.Index.Type())
|
||||||
|
|
||||||
// Can't load directly from array (as index is non-constant), so have to
|
// Can't load directly from array (as index is non-constant), so have to
|
||||||
|
@ -2288,7 +2288,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
|
||||||
switch typ := typ.(type) {
|
switch typ := typ.(type) {
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
bufptr = val
|
bufptr = val
|
||||||
buflen = llvm.ConstInt(c.lenType, uint64(typ.Len()), false)
|
buflen = llvm.ConstInt(c.uintptrType, uint64(typ.Len()), false)
|
||||||
default:
|
default:
|
||||||
return llvm.Value{}, errors.New("todo: indexaddr: " + typ.String())
|
return llvm.Value{}, errors.New("todo: indexaddr: " + typ.String())
|
||||||
}
|
}
|
||||||
|
@ -2412,16 +2412,16 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
|
||||||
slicePtr := c.createRuntimeCall("alloc", []llvm.Value{sliceSize}, "makeslice.buf")
|
slicePtr := c.createRuntimeCall("alloc", []llvm.Value{sliceSize}, "makeslice.buf")
|
||||||
slicePtr = c.builder.CreateBitCast(slicePtr, llvm.PointerType(llvmElemType, 0), "makeslice.array")
|
slicePtr = c.builder.CreateBitCast(slicePtr, llvm.PointerType(llvmElemType, 0), "makeslice.array")
|
||||||
|
|
||||||
if c.targetData.TypeAllocSize(sliceLen.Type()) > c.targetData.TypeAllocSize(c.lenType) {
|
if c.targetData.TypeAllocSize(sliceLen.Type()) > c.targetData.TypeAllocSize(c.uintptrType) {
|
||||||
sliceLen = c.builder.CreateTrunc(sliceLen, c.lenType, "")
|
sliceLen = c.builder.CreateTrunc(sliceLen, c.uintptrType, "")
|
||||||
sliceCap = c.builder.CreateTrunc(sliceCap, c.lenType, "")
|
sliceCap = c.builder.CreateTrunc(sliceCap, c.uintptrType, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the slice.
|
// Create the slice.
|
||||||
slice := c.ctx.ConstStruct([]llvm.Value{
|
slice := c.ctx.ConstStruct([]llvm.Value{
|
||||||
llvm.Undef(slicePtr.Type()),
|
llvm.Undef(slicePtr.Type()),
|
||||||
llvm.Undef(c.lenType),
|
llvm.Undef(c.uintptrType),
|
||||||
llvm.Undef(c.lenType),
|
llvm.Undef(c.uintptrType),
|
||||||
}, false)
|
}, false)
|
||||||
slice = c.builder.CreateInsertValue(slice, slicePtr, 0, "")
|
slice = c.builder.CreateInsertValue(slice, slicePtr, 0, "")
|
||||||
slice = c.builder.CreateInsertValue(slice, sliceLen, 1, "")
|
slice = c.builder.CreateInsertValue(slice, sliceLen, 1, "")
|
||||||
|
@ -2513,7 +2513,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
|
||||||
case *types.Pointer: // pointer to array
|
case *types.Pointer: // pointer to array
|
||||||
// slice an array
|
// slice an array
|
||||||
length := typ.Elem().(*types.Array).Len()
|
length := typ.Elem().(*types.Array).Len()
|
||||||
llvmLen := llvm.ConstInt(c.lenType, uint64(length), false)
|
llvmLen := llvm.ConstInt(c.uintptrType, uint64(length), false)
|
||||||
llvmLenInt := llvm.ConstInt(c.intType, uint64(length), false)
|
llvmLenInt := llvm.ConstInt(c.intType, uint64(length), false)
|
||||||
if high.IsNil() {
|
if high.IsNil() {
|
||||||
high = llvmLenInt
|
high = llvmLenInt
|
||||||
|
@ -2529,15 +2529,15 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
|
||||||
// This check is optimized away in most cases.
|
// This check is optimized away in most cases.
|
||||||
c.emitSliceBoundsCheck(frame, llvmLen, low, high)
|
c.emitSliceBoundsCheck(frame, llvmLen, low, high)
|
||||||
|
|
||||||
if c.targetData.TypeAllocSize(sliceLen.Type()) > c.targetData.TypeAllocSize(c.lenType) {
|
if c.targetData.TypeAllocSize(sliceLen.Type()) > c.targetData.TypeAllocSize(c.uintptrType) {
|
||||||
sliceLen = c.builder.CreateTrunc(sliceLen, c.lenType, "")
|
sliceLen = c.builder.CreateTrunc(sliceLen, c.uintptrType, "")
|
||||||
sliceCap = c.builder.CreateTrunc(sliceCap, c.lenType, "")
|
sliceCap = c.builder.CreateTrunc(sliceCap, c.uintptrType, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
slice := c.ctx.ConstStruct([]llvm.Value{
|
slice := c.ctx.ConstStruct([]llvm.Value{
|
||||||
llvm.Undef(slicePtr.Type()),
|
llvm.Undef(slicePtr.Type()),
|
||||||
llvm.Undef(c.lenType),
|
llvm.Undef(c.uintptrType),
|
||||||
llvm.Undef(c.lenType),
|
llvm.Undef(c.uintptrType),
|
||||||
}, false)
|
}, false)
|
||||||
slice = c.builder.CreateInsertValue(slice, slicePtr, 0, "")
|
slice = c.builder.CreateInsertValue(slice, slicePtr, 0, "")
|
||||||
slice = c.builder.CreateInsertValue(slice, sliceLen, 1, "")
|
slice = c.builder.CreateInsertValue(slice, sliceLen, 1, "")
|
||||||
|
@ -2555,11 +2555,11 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
|
||||||
|
|
||||||
c.emitSliceBoundsCheck(frame, oldCap, low, high)
|
c.emitSliceBoundsCheck(frame, oldCap, low, high)
|
||||||
|
|
||||||
if c.targetData.TypeAllocSize(low.Type()) > c.targetData.TypeAllocSize(c.lenType) {
|
if c.targetData.TypeAllocSize(low.Type()) > c.targetData.TypeAllocSize(c.uintptrType) {
|
||||||
low = c.builder.CreateTrunc(low, c.lenType, "")
|
low = c.builder.CreateTrunc(low, c.uintptrType, "")
|
||||||
}
|
}
|
||||||
if c.targetData.TypeAllocSize(high.Type()) > c.targetData.TypeAllocSize(c.lenType) {
|
if c.targetData.TypeAllocSize(high.Type()) > c.targetData.TypeAllocSize(c.uintptrType) {
|
||||||
high = c.builder.CreateTrunc(high, c.lenType, "")
|
high = c.builder.CreateTrunc(high, c.uintptrType, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
newPtr := c.builder.CreateGEP(oldPtr, []llvm.Value{low}, "")
|
newPtr := c.builder.CreateGEP(oldPtr, []llvm.Value{low}, "")
|
||||||
|
@ -2567,8 +2567,8 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
|
||||||
newCap := c.builder.CreateSub(oldCap, low, "")
|
newCap := c.builder.CreateSub(oldCap, low, "")
|
||||||
slice := c.ctx.ConstStruct([]llvm.Value{
|
slice := c.ctx.ConstStruct([]llvm.Value{
|
||||||
llvm.Undef(newPtr.Type()),
|
llvm.Undef(newPtr.Type()),
|
||||||
llvm.Undef(c.lenType),
|
llvm.Undef(c.uintptrType),
|
||||||
llvm.Undef(c.lenType),
|
llvm.Undef(c.uintptrType),
|
||||||
}, false)
|
}, false)
|
||||||
slice = c.builder.CreateInsertValue(slice, newPtr, 0, "")
|
slice = c.builder.CreateInsertValue(slice, newPtr, 0, "")
|
||||||
slice = c.builder.CreateInsertValue(slice, newLen, 1, "")
|
slice = c.builder.CreateInsertValue(slice, newLen, 1, "")
|
||||||
|
@ -2881,7 +2881,7 @@ func (c *Compiler) parseConst(prefix string, expr *ssa.Const) (llvm.Value, error
|
||||||
return llvm.ConstInt(llvmType, n, false), nil
|
return llvm.ConstInt(llvmType, n, false), nil
|
||||||
} else if typ.Info()&types.IsString != 0 {
|
} else if typ.Info()&types.IsString != 0 {
|
||||||
str := constant.StringVal(expr.Value)
|
str := constant.StringVal(expr.Value)
|
||||||
strLen := llvm.ConstInt(c.lenType, uint64(len(str)), false)
|
strLen := llvm.ConstInt(c.uintptrType, uint64(len(str)), false)
|
||||||
objname := prefix + "$string"
|
objname := prefix + "$string"
|
||||||
global := llvm.AddGlobal(c.mod, llvm.ArrayType(c.ctx.Int8Type(), len(str)), objname)
|
global := llvm.AddGlobal(c.mod, llvm.ArrayType(c.ctx.Int8Type(), len(str)), objname)
|
||||||
global.SetInitializer(c.ctx.ConstString(str, false))
|
global.SetInitializer(c.ctx.ConstString(str, false))
|
||||||
|
@ -2961,7 +2961,7 @@ func (c *Compiler) parseConst(prefix string, expr *ssa.Const) (llvm.Value, error
|
||||||
return llvm.Value{}, err
|
return llvm.Value{}, err
|
||||||
}
|
}
|
||||||
llvmPtr := llvm.ConstPointerNull(llvm.PointerType(elemType, 0))
|
llvmPtr := llvm.ConstPointerNull(llvm.PointerType(elemType, 0))
|
||||||
llvmLen := llvm.ConstInt(c.lenType, 0, false)
|
llvmLen := llvm.ConstInt(c.uintptrType, 0, false)
|
||||||
slice := c.ctx.ConstStruct([]llvm.Value{
|
slice := c.ctx.ConstStruct([]llvm.Value{
|
||||||
llvmPtr, // backing array
|
llvmPtr, // backing array
|
||||||
llvmLen, // len
|
llvmLen, // len
|
||||||
|
|
|
@ -4,8 +4,5 @@ package runtime
|
||||||
|
|
||||||
const GOARCH = "amd64"
|
const GOARCH = "amd64"
|
||||||
|
|
||||||
// The length type used inside strings and slices.
|
|
||||||
type lenType uint32
|
|
||||||
|
|
||||||
// The bitness of the CPU (e.g. 8, 32, 64).
|
// The bitness of the CPU (e.g. 8, 32, 64).
|
||||||
const TargetBits = 64
|
const TargetBits = 64
|
||||||
|
|
|
@ -8,9 +8,6 @@ import (
|
||||||
|
|
||||||
const GOARCH = "avr"
|
const GOARCH = "avr"
|
||||||
|
|
||||||
// The length type used inside strings and slices.
|
|
||||||
type lenType uint16
|
|
||||||
|
|
||||||
// The bitness of the CPU (e.g. 8, 32, 64).
|
// The bitness of the CPU (e.g. 8, 32, 64).
|
||||||
const TargetBits = 8
|
const TargetBits = 8
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,6 @@ import (
|
||||||
|
|
||||||
const GOARCH = "arm"
|
const GOARCH = "arm"
|
||||||
|
|
||||||
// The length type used inside strings and slices.
|
|
||||||
type lenType uint32
|
|
||||||
|
|
||||||
// The bitness of the CPU (e.g. 8, 32, 64).
|
// The bitness of the CPU (e.g. 8, 32, 64).
|
||||||
const TargetBits = 32
|
const TargetBits = 32
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,6 @@ import (
|
||||||
|
|
||||||
const GOARCH = "wasm"
|
const GOARCH = "wasm"
|
||||||
|
|
||||||
// The length type used inside strings and slices.
|
|
||||||
type lenType uint32
|
|
||||||
|
|
||||||
// The bitness of the CPU (e.g. 8, 32, 64).
|
// The bitness of the CPU (e.g. 8, 32, 64).
|
||||||
const TargetBits = 32
|
const TargetBits = 32
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
type hashmap struct {
|
type hashmap struct {
|
||||||
next *hashmap // hashmap after evacuate (for iterators)
|
next *hashmap // hashmap after evacuate (for iterators)
|
||||||
buckets unsafe.Pointer // pointer to array of buckets
|
buckets unsafe.Pointer // pointer to array of buckets
|
||||||
count lenType
|
count uintptr
|
||||||
keySize uint8 // maybe this can store the key type as well? E.g. keysize == 5 means string?
|
keySize uint8 // maybe this can store the key type as well? E.g. keysize == 5 means string?
|
||||||
valueSize uint8
|
valueSize uint8
|
||||||
bucketBits uint8
|
bucketBits uint8
|
||||||
|
|
|
@ -28,7 +28,7 @@ func _recover() interface{} {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for bounds in *ssa.Index, *ssa.IndexAddr and *ssa.Lookup.
|
// Check for bounds in *ssa.Index, *ssa.IndexAddr and *ssa.Lookup.
|
||||||
func lookupBoundsCheck(length lenType, index int) {
|
func lookupBoundsCheck(length uintptr, index int) {
|
||||||
if index < 0 || index >= int(length) {
|
if index < 0 || index >= int(length) {
|
||||||
runtimePanic("index out of range")
|
runtimePanic("index out of range")
|
||||||
}
|
}
|
||||||
|
@ -36,21 +36,21 @@ func lookupBoundsCheck(length lenType, index int) {
|
||||||
|
|
||||||
// Check for bounds in *ssa.Index, *ssa.IndexAddr and *ssa.Lookup.
|
// Check for bounds in *ssa.Index, *ssa.IndexAddr and *ssa.Lookup.
|
||||||
// Supports 64-bit indexes.
|
// Supports 64-bit indexes.
|
||||||
func lookupBoundsCheckLong(length lenType, index int64) {
|
func lookupBoundsCheckLong(length uintptr, index int64) {
|
||||||
if index < 0 || index >= int64(length) {
|
if index < 0 || index >= int64(length) {
|
||||||
runtimePanic("index out of range")
|
runtimePanic("index out of range")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for bounds in *ssa.Slice.
|
// Check for bounds in *ssa.Slice.
|
||||||
func sliceBoundsCheck(capacity lenType, low, high uint) {
|
func sliceBoundsCheck(capacity uintptr, low, high uint) {
|
||||||
if !(0 <= low && low <= high && high <= uint(capacity)) {
|
if !(0 <= low && low <= high && high <= uint(capacity)) {
|
||||||
runtimePanic("slice out of range")
|
runtimePanic("slice out of range")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for bounds in *ssa.Slice. Supports 64-bit indexes.
|
// Check for bounds in *ssa.Slice. Supports 64-bit indexes.
|
||||||
func sliceBoundsCheckLong(capacity lenType, low, high uint64) {
|
func sliceBoundsCheckLong(capacity uintptr, low, high uint64) {
|
||||||
if !(0 <= low && low <= high && high <= uint64(capacity)) {
|
if !(0 <= low && low <= high && high <= uint64(capacity)) {
|
||||||
runtimePanic("slice out of range")
|
runtimePanic("slice out of range")
|
||||||
}
|
}
|
||||||
|
|
|
@ -217,7 +217,7 @@ func printmap(m *hashmap) {
|
||||||
if m == nil {
|
if m == nil {
|
||||||
print("nil")
|
print("nil")
|
||||||
} else {
|
} else {
|
||||||
print(m.count)
|
print(uint(m.count))
|
||||||
}
|
}
|
||||||
putchar(']')
|
putchar(']')
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
|
|
||||||
// Builtin append(src, elements...) function: append elements to src and return
|
// Builtin append(src, elements...) function: append elements to src and return
|
||||||
// the modified (possibly expanded) slice.
|
// the modified (possibly expanded) slice.
|
||||||
func sliceAppend(srcBuf, elemsBuf unsafe.Pointer, srcLen, srcCap, elemsLen lenType, elemSize uintptr) (unsafe.Pointer, lenType, lenType) {
|
func sliceAppend(srcBuf, elemsBuf unsafe.Pointer, srcLen, srcCap, elemsLen uintptr, elemSize uintptr) (unsafe.Pointer, uintptr, uintptr) {
|
||||||
if elemsLen == 0 {
|
if elemsLen == 0 {
|
||||||
// Nothing to append, return the input slice.
|
// Nothing to append, return the input slice.
|
||||||
return srcBuf, srcLen, srcCap
|
return srcBuf, srcLen, srcCap
|
||||||
|
@ -27,27 +27,27 @@ func sliceAppend(srcBuf, elemsBuf unsafe.Pointer, srcLen, srcCap, elemsLen lenTy
|
||||||
// programs).
|
// programs).
|
||||||
srcCap *= 2
|
srcCap *= 2
|
||||||
}
|
}
|
||||||
buf := alloc(uintptr(srcCap) * elemSize)
|
buf := alloc(srcCap * elemSize)
|
||||||
|
|
||||||
// Copy the old slice to the new slice.
|
// Copy the old slice to the new slice.
|
||||||
if srcLen != 0 {
|
if srcLen != 0 {
|
||||||
memmove(buf, srcBuf, uintptr(srcLen)*elemSize)
|
memmove(buf, srcBuf, srcLen*elemSize)
|
||||||
}
|
}
|
||||||
srcBuf = buf
|
srcBuf = buf
|
||||||
}
|
}
|
||||||
|
|
||||||
// The slice fits (after possibly allocating a new one), append it in-place.
|
// The slice fits (after possibly allocating a new one), append it in-place.
|
||||||
memmove(unsafe.Pointer(uintptr(srcBuf)+uintptr(srcLen)*elemSize), elemsBuf, uintptr(elemsLen)*elemSize)
|
memmove(unsafe.Pointer(uintptr(srcBuf)+srcLen*elemSize), elemsBuf, elemsLen*elemSize)
|
||||||
return srcBuf, srcLen + elemsLen, srcCap
|
return srcBuf, srcLen + elemsLen, srcCap
|
||||||
}
|
}
|
||||||
|
|
||||||
// Builtin copy(dst, src) function: copy bytes from dst to src.
|
// Builtin copy(dst, src) function: copy bytes from dst to src.
|
||||||
func sliceCopy(dst, src unsafe.Pointer, dstLen, srcLen lenType, elemSize uintptr) lenType {
|
func sliceCopy(dst, src unsafe.Pointer, dstLen, srcLen uintptr, elemSize uintptr) uintptr {
|
||||||
// n = min(srcLen, dstLen)
|
// n = min(srcLen, dstLen)
|
||||||
n := srcLen
|
n := srcLen
|
||||||
if n > dstLen {
|
if n > dstLen {
|
||||||
n = dstLen
|
n = dstLen
|
||||||
}
|
}
|
||||||
memmove(dst, src, uintptr(n)*elemSize)
|
memmove(dst, src, n*elemSize)
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,13 +9,13 @@ import (
|
||||||
// The underlying struct for the Go string type.
|
// The underlying struct for the Go string type.
|
||||||
type _string struct {
|
type _string struct {
|
||||||
ptr *byte
|
ptr *byte
|
||||||
length lenType
|
length uintptr
|
||||||
}
|
}
|
||||||
|
|
||||||
// The iterator state for a range over a string.
|
// The iterator state for a range over a string.
|
||||||
type stringIterator struct {
|
type stringIterator struct {
|
||||||
byteindex lenType
|
byteindex uintptr
|
||||||
rangeindex lenType
|
rangeindex uintptr
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return true iff the strings match.
|
// Return true iff the strings match.
|
||||||
|
@ -57,33 +57,33 @@ func stringConcat(x, y _string) _string {
|
||||||
} else if y.length == 0 {
|
} else if y.length == 0 {
|
||||||
return x
|
return x
|
||||||
} else {
|
} else {
|
||||||
length := uintptr(x.length + y.length)
|
length := x.length + y.length
|
||||||
buf := alloc(length)
|
buf := alloc(length)
|
||||||
memcpy(buf, unsafe.Pointer(x.ptr), uintptr(x.length))
|
memcpy(buf, unsafe.Pointer(x.ptr), x.length)
|
||||||
memcpy(unsafe.Pointer(uintptr(buf)+uintptr(x.length)), unsafe.Pointer(y.ptr), uintptr(y.length))
|
memcpy(unsafe.Pointer(uintptr(buf)+x.length), unsafe.Pointer(y.ptr), y.length)
|
||||||
return _string{ptr: (*byte)(buf), length: lenType(length)}
|
return _string{ptr: (*byte)(buf), length: length}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a string from a []byte slice.
|
// Create a string from a []byte slice.
|
||||||
func stringFromBytes(x struct {
|
func stringFromBytes(x struct {
|
||||||
ptr *byte
|
ptr *byte
|
||||||
len lenType
|
len uintptr
|
||||||
cap lenType
|
cap uintptr
|
||||||
}) _string {
|
}) _string {
|
||||||
buf := alloc(uintptr(x.len))
|
buf := alloc(x.len)
|
||||||
memcpy(buf, unsafe.Pointer(x.ptr), uintptr(x.len))
|
memcpy(buf, unsafe.Pointer(x.ptr), x.len)
|
||||||
return _string{ptr: (*byte)(buf), length: lenType(x.len)}
|
return _string{ptr: (*byte)(buf), length: x.len}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a string to a []byte slice.
|
// Convert a string to a []byte slice.
|
||||||
func stringToBytes(x _string) (slice struct {
|
func stringToBytes(x _string) (slice struct {
|
||||||
ptr *byte
|
ptr *byte
|
||||||
len lenType
|
len uintptr
|
||||||
cap lenType
|
cap uintptr
|
||||||
}) {
|
}) {
|
||||||
buf := alloc(uintptr(x.length))
|
buf := alloc(x.length)
|
||||||
memcpy(buf, unsafe.Pointer(x.ptr), uintptr(x.length))
|
memcpy(buf, unsafe.Pointer(x.ptr), x.length)
|
||||||
slice.ptr = (*byte)(buf)
|
slice.ptr = (*byte)(buf)
|
||||||
slice.len = x.length
|
slice.len = x.length
|
||||||
slice.cap = x.length
|
slice.cap = x.length
|
||||||
|
@ -112,7 +112,7 @@ func stringNext(s string, it *stringIterator) (bool, int, rune) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a Unicode code point into an array of bytes and its length.
|
// Convert a Unicode code point into an array of bytes and its length.
|
||||||
func encodeUTF8(x rune) ([4]byte, lenType) {
|
func encodeUTF8(x rune) ([4]byte, uintptr) {
|
||||||
// https://stackoverflow.com/questions/6240055/manually-converting-unicode-codepoints-into-utf-8-and-utf-16
|
// https://stackoverflow.com/questions/6240055/manually-converting-unicode-codepoints-into-utf-8-and-utf-16
|
||||||
// Note: this code can probably be optimized (in size and speed).
|
// Note: this code can probably be optimized (in size and speed).
|
||||||
switch {
|
switch {
|
||||||
|
@ -141,8 +141,8 @@ func encodeUTF8(x rune) ([4]byte, lenType) {
|
||||||
|
|
||||||
// Decode a single UTF-8 character from a string.
|
// Decode a single UTF-8 character from a string.
|
||||||
//go:nobounds
|
//go:nobounds
|
||||||
func decodeUTF8(s string, index lenType) (rune, lenType) {
|
func decodeUTF8(s string, index uintptr) (rune, uintptr) {
|
||||||
remaining := lenType(len(s)) - index // must be >= 1 before calling this function
|
remaining := uintptr(len(s)) - index // must be >= 1 before calling this function
|
||||||
x := s[index]
|
x := s[index]
|
||||||
switch {
|
switch {
|
||||||
case x&0x80 == 0x00: // 0xxxxxxx
|
case x&0x80 == 0x00: // 0xxxxxxx
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче