cl: checkVArgs bugfix
This commit is contained in:
@@ -62,12 +62,14 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (p *context) funcKind(vfn ssa.Value) int {
|
func (p *context) funcKind(vfn ssa.Value) int {
|
||||||
if fn, ok := vfn.(*ssa.Function); ok && fn.Signature.Recv() == nil {
|
if fn, ok := vfn.(*ssa.Function); ok {
|
||||||
params := fn.Signature.Params()
|
params := fn.Signature.Params()
|
||||||
n := params.Len()
|
n := params.Len()
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
if fn.Name() == "init" && p.pkgNoInit(fn.Pkg.Pkg) {
|
if fn.Signature.Recv() == nil {
|
||||||
return fnIgnore
|
if fn.Name() == "init" && p.pkgNoInit(fn.Pkg.Pkg) {
|
||||||
|
return fnIgnore
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
last := params.At(n - 1)
|
last := params.At(n - 1)
|
||||||
@@ -356,9 +358,9 @@ func (p *context) isVArgs(vx ssa.Value) (ret []llssa.Expr, ok bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) checkVArgs(v *ssa.Alloc, t *types.Pointer) bool {
|
func (p *context) checkVArgs(v *ssa.Alloc, t *types.Pointer) bool {
|
||||||
if v.Comment == "varargs" { // this is a varargs allocation
|
if v.Comment == "varargs" { // this maybe a varargs allocation
|
||||||
if arr, ok := t.Elem().(*types.Array); ok {
|
if arr, ok := t.Elem().(*types.Array); ok {
|
||||||
if isAny(arr.Elem()) {
|
if isAny(arr.Elem()) && isVargs(p, v) {
|
||||||
p.vargs[v] = make([]llssa.Expr, arr.Len())
|
p.vargs[v] = make([]llssa.Expr, arr.Len())
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -367,6 +369,20 @@ func (p *context) checkVArgs(v *ssa.Alloc, t *types.Pointer) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isVargs(ctx *context, v *ssa.Alloc) bool {
|
||||||
|
refs := *v.Referrers()
|
||||||
|
n := len(refs)
|
||||||
|
lastref := refs[n-1]
|
||||||
|
if i, ok := lastref.(*ssa.Slice); ok {
|
||||||
|
if refs = *i.Referrers(); len(refs) == 1 {
|
||||||
|
if call, ok := refs[0].(*ssa.Call); ok {
|
||||||
|
return ctx.funcKind(call.Call.Value) == fnHasVArg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// func cstr(string) *int8
|
// func cstr(string) *int8
|
||||||
func cstr(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
|
func cstr(b llssa.Builder, args []ssa.Value) (ret llssa.Expr) {
|
||||||
if len(args) == 1 {
|
if len(args) == 1 {
|
||||||
@@ -468,42 +484,42 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
|
|||||||
}
|
}
|
||||||
switch v := iv.(type) {
|
switch v := iv.(type) {
|
||||||
case *ssa.Call:
|
case *ssa.Call:
|
||||||
call := v.Call
|
cv := v.Call.Value
|
||||||
cv := call.Value
|
|
||||||
kind := p.funcKind(cv)
|
kind := p.funcKind(cv)
|
||||||
if kind == fnIgnore {
|
if kind == fnIgnore {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
args := v.Call.Args
|
||||||
if debugGoSSA {
|
if debugGoSSA {
|
||||||
log.Println(">>> Call", cv, call.Args)
|
log.Println(">>> Call", cv, args)
|
||||||
}
|
}
|
||||||
switch cv := cv.(type) {
|
switch cv := cv.(type) {
|
||||||
case *ssa.Builtin:
|
case *ssa.Builtin:
|
||||||
fn := cv.Name()
|
fn := cv.Name()
|
||||||
if fn == "ssa:wrapnilchk" { // TODO(xsw): check nil ptr
|
if fn == "ssa:wrapnilchk" { // TODO(xsw): check nil ptr
|
||||||
arg := call.Args[0]
|
arg := args[0]
|
||||||
ret = p.compileValue(b, arg)
|
ret = p.compileValue(b, arg)
|
||||||
// log.Println("wrapnilchk:", ret.TypeOf())
|
// log.Println("wrapnilchk:", ret.TypeOf())
|
||||||
} else {
|
} else {
|
||||||
args := p.compileValues(b, call.Args, kind)
|
args := p.compileValues(b, args, kind)
|
||||||
ret = b.BuiltinCall(fn, args...)
|
ret = b.BuiltinCall(fn, args...)
|
||||||
}
|
}
|
||||||
case *ssa.Function:
|
case *ssa.Function:
|
||||||
fn, ftype := p.compileFunction(cv)
|
fn, ftype := p.compileFunction(cv)
|
||||||
switch ftype {
|
switch ftype {
|
||||||
case goFunc, cFunc:
|
case goFunc, cFunc:
|
||||||
args := p.compileValues(b, call.Args, kind)
|
args := p.compileValues(b, args, kind)
|
||||||
ret = b.Call(fn.Expr, args...)
|
ret = b.Call(fn.Expr, args...)
|
||||||
case llgoCstr:
|
case llgoCstr:
|
||||||
ret = cstr(b, call.Args)
|
ret = cstr(b, args)
|
||||||
case llgoAdvance:
|
case llgoAdvance:
|
||||||
ret = p.advance(b, call.Args)
|
ret = p.advance(b, args)
|
||||||
case llgoIndex:
|
case llgoIndex:
|
||||||
ret = p.index(b, call.Args)
|
ret = p.index(b, args)
|
||||||
case llgoAlloca:
|
case llgoAlloca:
|
||||||
ret = p.alloca(b, call.Args)
|
ret = p.alloca(b, args)
|
||||||
case llgoAllocaCStr:
|
case llgoAllocaCStr:
|
||||||
ret = p.allocaCStr(b, call.Args)
|
ret = p.allocaCStr(b, args)
|
||||||
case llgoUnreachable: // func unreachable()
|
case llgoUnreachable: // func unreachable()
|
||||||
b.Unreachable()
|
b.Unreachable()
|
||||||
default:
|
default:
|
||||||
@@ -511,7 +527,7 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
fn := p.compileValue(b, cv)
|
fn := p.compileValue(b, cv)
|
||||||
args := p.compileValues(b, call.Args, kind)
|
args := p.compileValues(b, args, kind)
|
||||||
ret = b.Call(fn, args...)
|
ret = b.Call(fn, args...)
|
||||||
}
|
}
|
||||||
case *ssa.BinOp:
|
case *ssa.BinOp:
|
||||||
@@ -534,7 +550,7 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
|
|||||||
ret = b.FieldAddr(x, v.Field)
|
ret = b.FieldAddr(x, v.Field)
|
||||||
case *ssa.Alloc:
|
case *ssa.Alloc:
|
||||||
t := v.Type().(*types.Pointer)
|
t := v.Type().(*types.Pointer)
|
||||||
if p.checkVArgs(v, t) { // varargs: this is a varargs allocation
|
if p.checkVArgs(v, t) { // varargs: this maybe a varargs allocation
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
elem := p.prog.Type(t.Elem(), llssa.InGo)
|
elem := p.prog.Type(t.Elem(), llssa.InGo)
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ func TestFromTestrt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFromTestdata(t *testing.T) {
|
func TestFromTestdata(t *testing.T) {
|
||||||
cltest.FromDir(t, "", "./_testdata", false)
|
cltest.FromDir(t, "vargs", "./_testdata", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSqlite(t *testing.T) {
|
func TestSqlite(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user