ssa: makeSlice both len/cap be non-nil

This commit is contained in:
visualfc
2024-06-26 06:49:48 +08:00
parent c90703dc13
commit dc4b933000
6 changed files with 30 additions and 33 deletions

View File

@@ -543,12 +543,9 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
x := p.compileValue(b, v.X) x := p.compileValue(b, v.X)
ret = b.MakeInterface(t, x) ret = b.MakeInterface(t, x)
case *ssa.MakeSlice: case *ssa.MakeSlice:
var nCap llssa.Expr
t := p.prog.Type(v.Type(), llssa.InGo) t := p.prog.Type(v.Type(), llssa.InGo)
nLen := p.compileValue(b, v.Len) nLen := p.compileValue(b, v.Len)
if v.Cap != nil { nCap := p.compileValue(b, v.Cap)
nCap = p.compileValue(b, v.Cap)
}
ret = b.MakeSlice(t, nLen, nCap) ret = b.MakeSlice(t, nLen, nCap)
case *ssa.MakeMap: case *ssa.MakeMap:
var nReserve llssa.Expr var nReserve llssa.Expr

View File

@@ -0,0 +1,3 @@
package goarch
const PtrSize = 4 << (^uintptr(0) >> 63)

View File

@@ -0,0 +1,15 @@
package math
import "github.com/goplus/llgo/internal/runtime/goarch"
const MaxUintptr = ^uintptr(0)
// MulUintptr returns a * b and whether the multiplication overflowed.
// On supported platforms this is an intrinsic lowered by the compiler.
func MulUintptr(a, b uintptr) (uintptr, bool) {
if a|b < 1<<(4*goarch.PtrSize) || a == 0 {
return a * b, false
}
overflow := b > MaxUintptr/a
return a * b, overflow
}

View File

@@ -36,3 +36,10 @@ func fastrand() uint32 {
return s0 + s1 return s0 + s1
} }
*/ */
const (
// _64bit = 1 on 64-bit systems, 0 on 32-bit systems
_64bit = 1 << (^uintptr(0) >> 63) / 2
heapAddrBits = (_64bit)*48 + (1-_64bit)*(32)
maxAlloc = (1 << heapAddrBits) - (1-_64bit)*1
)

View File

@@ -20,6 +20,7 @@ import (
"unsafe" "unsafe"
"github.com/goplus/llgo/c" "github.com/goplus/llgo/c"
"github.com/goplus/llgo/internal/runtime/math"
) )
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@@ -120,32 +121,10 @@ func SliceCopy(dst Slice, data unsafe.Pointer, num int, etSize int) int {
return n return n
} }
const (
// _64bit = 1 on 64-bit systems, 0 on 32-bit systems
_64bit = 1 << (^uintptr(0) >> 63) / 2
heapAddrBits = (_64bit)*48 + (1-_64bit)*(32)
maxAlloc = (1 << heapAddrBits) - (1-_64bit)*1
)
const (
PtrSize = 4 << (^uintptr(0) >> 63)
MaxUintptr = ^uintptr(0)
)
// MulUintptr returns a * b and whether the multiplication overflowed.
// On supported platforms this is an intrinsic lowered by the compiler.
func MulUintptr(a, b uintptr) (uintptr, bool) {
if a|b < 1<<(4*PtrSize) || a == 0 {
return a * b, false
}
overflow := b > MaxUintptr/a
return a * b, overflow
}
func MakeSlice(len, cap int, etSize int) Slice { func MakeSlice(len, cap int, etSize int) Slice {
mem, overflow := MulUintptr(uintptr(etSize), uintptr(cap)) mem, overflow := math.MulUintptr(uintptr(etSize), uintptr(cap))
if overflow || mem > maxAlloc || len < 0 || len > cap { if overflow || mem > maxAlloc || len < 0 || len > cap {
mem, overflow := MulUintptr(uintptr(etSize), uintptr(len)) mem, overflow := math.MulUintptr(uintptr(etSize), uintptr(len))
if overflow || mem > maxAlloc || len < 0 { if overflow || mem > maxAlloc || len < 0 {
panicmakeslicelen() panicmakeslicelen()
} }

View File

@@ -417,11 +417,7 @@ func (b Builder) MakeSlice(t Type, len, cap Expr) (ret Expr) {
} }
prog := b.Prog prog := b.Prog
len = b.fitIntSize(len) len = b.fitIntSize(len)
if cap.IsNil() { cap = b.fitIntSize(cap)
cap = len
} else {
cap = b.fitIntSize(cap)
}
telem := prog.Index(t) telem := prog.Index(t)
ret = b.InlineCall(b.Pkg.rtFunc("MakeSlice"), len, cap, prog.IntVal(prog.SizeOf(telem), prog.Int())) ret = b.InlineCall(b.Pkg.rtFunc("MakeSlice"), len, cap, prog.IntVal(prog.SizeOf(telem), prog.Int()))
ret.Type = t ret.Type = t