diff --git a/ssa/datastruct.go b/ssa/datastruct.go index 75e904c6..06f26b3a 100644 --- a/ssa/datastruct.go +++ b/ssa/datastruct.go @@ -148,12 +148,14 @@ func (b Builder) IndexAddr(x, idx Expr) Expr { // check index >= 0 and size to uint func (b Builder) checkIndex(idx Expr) Expr { + prog := b.Prog if needsNegativeCheck(idx) { - check := Expr{b.impl.CreateICmp(llvm.IntSLT, idx.impl, llvm.ConstInt(idx.ll, 0, false), ""), b.Prog.Bool()} - b.InlineCall(b.Func.Pkg.rtFunc("AssertIndexRange"), check) + zero := llvm.ConstInt(idx.ll, 0, false) + check := Expr{b.impl.CreateICmp(llvm.IntSLT, idx.impl, zero, ""), prog.Bool()} + b.InlineCall(b.Pkg.rtFunc("AssertIndexRange"), check) } - typ := b.Prog.Uint() - if b.Prog.SizeOf(idx.Type) < b.Prog.SizeOf(typ) { + typ := prog.Uint() + if prog.SizeOf(idx.Type) < prog.SizeOf(typ) { idx.Type = typ idx.impl = castUintptr(b, idx.impl, typ) } @@ -235,7 +237,6 @@ func (b Builder) Slice(x, low, high, max Expr) (ret Expr) { log.Printf("Slice %v, %v, %v\n", x.impl, low.impl, high.impl) } prog := b.Prog - pkg := b.Func.Pkg var nCap Expr var nEltSize Expr var base Expr @@ -251,7 +252,7 @@ func (b Builder) Slice(x, low, high, max Expr) (ret Expr) { high = b.StringLen(x) } ret.Type = x.Type - ret.impl = b.InlineCall(pkg.rtFunc("NewStringSlice"), x, low, high).impl + ret.impl = b.InlineCall(b.Pkg.rtFunc("NewStringSlice"), x, low, high).impl return case *types.Slice: nEltSize = b.SizeOf(prog.Index(x.Type)) @@ -278,7 +279,7 @@ func (b Builder) Slice(x, low, high, max Expr) (ret Expr) { if max.IsNil() { max = nCap } - ret.impl = b.InlineCall(pkg.rtFunc("NewSlice3"), base, nEltSize, nCap, low, high, max).impl + ret.impl = b.InlineCall(b.Pkg.rtFunc("NewSlice3"), base, nEltSize, nCap, low, high, max).impl return } @@ -297,9 +298,8 @@ func (b Builder) MakeMap(t Type, nReserve Expr) (ret Expr) { if debugInstr { log.Printf("MakeMap %v, %v\n", t.RawType(), nReserve.impl) } - pkg := b.Func.Pkg ret.Type = t - ret.impl = b.InlineCall(pkg.rtFunc("MakeSmallMap")).impl + ret.impl = b.InlineCall(b.Pkg.rtFunc("MakeSmallMap")).impl // TODO(xsw): nReserve return } @@ -322,7 +322,7 @@ func (b Builder) MakeSlice(t Type, len, cap Expr) (ret Expr) { if debugInstr { log.Printf("MakeSlice %v, %v, %v\n", t.RawType(), len.impl, cap.impl) } - pkg := b.Func.Pkg + pkg := b.Pkg if cap.IsNil() { cap = len } diff --git a/ssa/decl.go b/ssa/decl.go index ee8b3d12..97856aa3 100644 --- a/ssa/decl.go +++ b/ssa/decl.go @@ -248,7 +248,7 @@ func (p Function) NewBuilder() Builder { b := prog.ctx.NewBuilder() // TODO(xsw): Finalize may cause panic, so comment it. // b.Finalize() - return &aBuilder{b, p, prog} + return &aBuilder{b, p, p.Pkg, prog} } // HasBody reports whether the function has a body. @@ -305,16 +305,14 @@ type PyGlobal = *aPyGlobal // PyNewVar creates a Python variable. func (b Builder) PyNewVar(modName, name string) PyGlobal { - pkg := b.Func.Pkg - modPtr := pkg.PyNewModVar(modName, false).Expr + modPtr := b.Pkg.PyNewModVar(modName, false).Expr mod := b.Load(modPtr) return &aPyGlobal{pyVarExpr(mod, name)} } func (b Builder) pyLoad(ptr Expr) Expr { - pkg := b.Func.Pkg t := ptr.raw.Type.(*pyVarTy) - fn := pkg.pyFunc("PyObject_GetAttrString", b.Prog.tyGetAttrString()) + fn := b.Pkg.pyFunc("PyObject_GetAttrString", b.Prog.tyGetAttrString()) return b.Call(fn, t.mod, b.CStr(t.name)) } diff --git a/ssa/expr.go b/ssa/expr.go index 8106abf3..740bce6b 100644 --- a/ssa/expr.go +++ b/ssa/expr.go @@ -190,7 +190,7 @@ func (b Builder) CStr(v string) Expr { func (b Builder) Str(v string) (ret Expr) { prog := b.Prog cstr := b.CStr(v) - ret = b.InlineCall(b.Func.Pkg.rtFunc("NewString"), cstr, prog.Val(len(v))) + ret = b.InlineCall(b.Pkg.rtFunc("NewString"), cstr, prog.Val(len(v))) ret.Type = prog.String() return } @@ -308,8 +308,7 @@ func (b Builder) BinOp(op token.Token, x, y Expr) Expr { switch kind { case vkString: if op == token.ADD { - pkg := b.Func.Pkg - return Expr{b.InlineCall(pkg.rtFunc("StringCat"), x, y).impl, x.Type} + return Expr{b.InlineCall(b.Pkg.rtFunc("StringCat"), x, y).impl, x.Type} } case vkComplex: default: @@ -324,8 +323,9 @@ func (b Builder) BinOp(op token.Token, x, y Expr) Expr { return Expr{b.impl.CreateAnd(x.impl, b.impl.CreateNot(y.impl, ""), ""), x.Type} case token.SHL, token.SHR: if needsNegativeCheck(y) { - check := Expr{b.impl.CreateICmp(llvm.IntSLT, y.impl, llvm.ConstInt(y.ll, 0, false), ""), b.Prog.Bool()} - b.InlineCall(b.Func.Pkg.rtFunc("AssertNegativeShift"), check) + zero := llvm.ConstInt(y.ll, 0, false) + check := Expr{b.impl.CreateICmp(llvm.IntSLT, y.impl, zero, ""), b.Prog.Bool()} + b.InlineCall(b.Pkg.rtFunc("AssertNegativeShift"), check) } xsize, ysize := b.Prog.SizeOf(x.Type), b.Prog.SizeOf(y.Type) if xsize != ysize { @@ -416,7 +416,7 @@ func (b Builder) UnOp(op token.Token, x Expr) (ret Expr) { func checkExpr(v Expr, t types.Type, b Builder) Expr { if t, ok := t.(*types.Struct); ok && isClosure(t) { if v.kind != vkClosure { - return b.Func.Pkg.closureStub(b, t, v) + return b.Pkg.closureStub(b, t, v) } } return v @@ -584,9 +584,8 @@ func (b Builder) Store(ptr, val Expr) Builder { func (b Builder) aggregateAlloc(t Type, flds ...llvm.Value) llvm.Value { prog := b.Prog - pkg := b.Func.Pkg size := prog.SizeOf(t) - ptr := b.InlineCall(pkg.rtFunc("AllocU"), prog.IntVal(size, prog.Uintptr())).impl + ptr := b.InlineCall(b.Pkg.rtFunc("AllocU"), prog.IntVal(size, prog.Uintptr())).impl tll := t.ll impl := b.impl for i, fld := range flds { @@ -654,7 +653,7 @@ func (b Builder) Alloc(elem Type, heap bool) (ret Expr) { log.Printf("Alloc %v, %v\n", elem.RawType(), heap) } prog := b.Prog - pkg := b.Func.Pkg + pkg := b.Pkg size := b.SizeOf(elem) if heap { ret = b.InlineCall(pkg.rtFunc("AllocZ"), size) @@ -695,11 +694,10 @@ func (b Builder) AllocaCStr(gostr Expr) (ret Expr) { if debugInstr { log.Printf("AllocaCStr %v\n", gostr.impl) } - pkg := b.Func.Pkg n := b.StringLen(gostr) n1 := b.BinOp(token.ADD, n, b.Prog.Val(1)) cstr := b.Alloca(n1) - return b.InlineCall(pkg.rtFunc("CStrCopy"), cstr, gostr) + return b.InlineCall(b.Pkg.rtFunc("CStrCopy"), cstr, gostr) } // ----------------------------------------------------------------------------- @@ -968,13 +966,13 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) { case vkSlice: etSize := b.Prog.SizeOf(b.Prog.Elem(elem.Type)) ret.Type = src.Type - ret.impl = b.InlineCall(b.Func.Pkg.rtFunc("SliceAppend"), + ret.impl = b.InlineCall(b.Pkg.rtFunc("SliceAppend"), src, b.SliceData(elem), b.SliceLen(elem), b.Prog.Val(int(etSize))).impl return case vkString: etSize := b.Prog.SizeOf(b.Prog.Byte()) ret.Type = src.Type - ret.impl = b.InlineCall(b.Func.Pkg.rtFunc("SliceAppend"), + ret.impl = b.InlineCall(b.Pkg.rtFunc("SliceAppend"), src, b.StringData(elem), b.StringLen(elem), b.Prog.Val(int(etSize))).impl return } @@ -985,7 +983,7 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) { ret.Type = b.Prog.Void() for i, arg := range args { if ln && i > 0 { - b.InlineCall(b.Func.Pkg.rtFunc("PrintString"), b.Str(" ")) + b.InlineCall(b.Pkg.rtFunc("PrintString"), b.Str(" ")) } var fn string var typ Type @@ -1018,10 +1016,10 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) { if typ != nil && typ != arg.Type { arg = b.Convert(typ, arg) } - b.InlineCall(b.Func.Pkg.rtFunc(fn), arg) + b.InlineCall(b.Pkg.rtFunc(fn), arg) } if ln { - b.InlineCall(b.Func.Pkg.rtFunc("PrintString"), b.Str("\n")) + b.InlineCall(b.Pkg.rtFunc("PrintString"), b.Str("\n")) } return } diff --git a/ssa/interface.go b/ssa/interface.go index ca8a80a5..1bbfc8e9 100644 --- a/ssa/interface.go +++ b/ssa/interface.go @@ -27,6 +27,13 @@ import ( // ----------------------------------------------------------------------------- +// AbiBasic returns the abi type of the specified basic kind. +func (b Builder) AbiBasic(kind types.BasicKind) Expr { + return b.InlineCall(b.Pkg.rtFunc("Basic"), b.Prog.Val(int(kind))) +} + +// ----------------------------------------------------------------------------- + // MakeInterface constructs an instance of an interface type from a // value of a concrete type. // @@ -47,24 +54,24 @@ func (b Builder) MakeInterface(tinter Type, x Expr) (ret Expr) { log.Printf("MakeInterface %v, %v\n", raw, x.impl) } prog := b.Prog - pkg := b.Func.Pkg + pkg := b.Pkg switch tx := x.raw.Type.Underlying().(type) { case *types.Basic: kind := tx.Kind() switch { case kind >= types.Bool && kind <= types.Uintptr: - t := b.InlineCall(pkg.rtFunc("Basic"), prog.Val(int(kind))) + t := b.AbiBasic(kind) tptr := prog.Uintptr() vptr := Expr{llvm.CreateIntCast(b.impl, x.impl, tptr.ll), tptr} return Expr{b.InlineCall(pkg.rtFunc("MakeAnyInt"), t, vptr).impl, tinter} case kind == types.Float32: - t := b.InlineCall(pkg.rtFunc("Basic"), prog.Val(int(kind))) + t := b.AbiBasic(kind) tptr := prog.Uintptr() i32 := b.impl.CreateBitCast(x.impl, prog.tyInt32(), "") vptr := Expr{llvm.CreateIntCast(b.impl, i32, tptr.ll), tptr} return Expr{b.InlineCall(pkg.rtFunc("MakeAnyInt"), t, vptr).impl, tinter} case kind == types.Float64: - t := b.InlineCall(pkg.rtFunc("Basic"), prog.Val(int(kind))) + t := b.AbiBasic(kind) tptr := prog.Uintptr() vptr := Expr{b.impl.CreateBitCast(x.impl, tptr.ll, ""), tptr} return Expr{b.InlineCall(pkg.rtFunc("MakeAnyInt"), t, vptr).impl, tinter} @@ -122,7 +129,7 @@ func (b Builder) TypeAssert(x Expr, assertedTyp Type, commaOk bool) (ret Expr) { } switch assertedTyp.kind { case vkSigned, vkUnsigned, vkFloat, vkBool: - pkg := b.Func.Pkg + pkg := b.Pkg fnName := "I2Int" if commaOk { fnName = "CheckI2Int" @@ -167,7 +174,7 @@ func (b Builder) TypeAssert(x Expr, assertedTyp Type, commaOk bool) (ret Expr) { } return case vkString: - pkg := b.Func.Pkg + pkg := b.Pkg fnName := "I2String" if commaOk { fnName = "CheckI2String" diff --git a/ssa/package.go b/ssa/package.go index 57caaef9..bc9cb7cc 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -694,14 +694,13 @@ func (p Package) PyNewModVar(name string, doInit bool) Global { // PyImportMod imports a Python module. func (b Builder) PyImportMod(path string) Expr { - pkg := b.Func.Pkg - fnImp := pkg.pyFunc("PyImport_ImportModule", b.Prog.tyImportPyModule()) + fnImp := b.Pkg.pyFunc("PyImport_ImportModule", b.Prog.tyImportPyModule()) return b.Call(fnImp, b.CStr(path)) } // PyLoadModSyms loads python objects from specified module. func (b Builder) PyLoadModSyms(modName string, objs ...PyObjRef) Expr { - pkg := b.Func.Pkg + pkg := b.Pkg fnLoad := pkg.pyFunc("llgoLoadPyModSyms", b.Prog.tyLoadPyModSyms()) modPtr := pkg.PyNewModVar(modName, false).Expr mod := b.Load(modPtr) @@ -721,7 +720,7 @@ func (b Builder) PyLoadModSyms(modName string, objs ...PyObjRef) Expr { func (b Builder) pyCall(fn Expr, args []Expr) (ret Expr) { prog := b.Prog - pkg := b.Func.Pkg + pkg := b.Pkg fn = b.Load(fn) sig := fn.raw.Type.(*types.Signature) params := sig.Params() @@ -751,16 +750,14 @@ func (b Builder) pyCall(fn Expr, args []Expr) (ret Expr) { // PyNewList(n uintptr) *Object func (b Builder) PyNewList(n Expr) (ret Expr) { prog := b.Prog - pkg := b.Func.Pkg - fn := pkg.pyFunc("PyList_New", prog.tyNewList()) + fn := b.Pkg.pyFunc("PyList_New", prog.tyNewList()) return b.Call(fn, n) } // PyListSetItem(list *Object, index uintptr, item *Object) c.Int func (b Builder) PyListSetItem(list, index, item Expr) (ret Expr) { prog := b.Prog - pkg := b.Func.Pkg - fn := pkg.pyFunc("PyList_SetItem", prog.tyListSetItem()) + fn := b.Pkg.pyFunc("PyList_SetItem", prog.tyListSetItem()) return b.Call(fn, list, index, item) } @@ -793,15 +790,13 @@ func (b Builder) PyVal(v Expr) (ret Expr) { // PyFloat(fltVal float64) *Object func (b Builder) PyFloat(fltVal Expr) (ret Expr) { - prog := b.Prog - pkg := b.Func.Pkg - fn := pkg.pyFunc("PyFloat_FromDouble", prog.tyFloatFromDouble()) + fn := b.Pkg.pyFunc("PyFloat_FromDouble", b.Prog.tyFloatFromDouble()) return b.Call(fn, fltVal) } // callPyInit calls Py_Initialize. func (b Builder) callPyInit() (ret Expr) { - fn := b.Func.Pkg.pyFunc("Py_Initialize", NoArgsNoRet) + fn := b.Pkg.pyFunc("Py_Initialize", NoArgsNoRet) return b.Call(fn) } diff --git a/ssa/stmt_builder.go b/ssa/stmt_builder.go index ae91fee6..2bbaf771 100644 --- a/ssa/stmt_builder.go +++ b/ssa/stmt_builder.go @@ -52,6 +52,7 @@ func (p BasicBlock) Index() int { type aBuilder struct { impl llvm.Builder Func Function + Pkg Package Prog Program } @@ -124,8 +125,7 @@ func (b Builder) Panic(v Expr) { if debugInstr { log.Printf("Panic %v\n", v.impl) } - pkg := b.Func.Pkg - b.Call(pkg.rtFunc("TracePanic"), v) + b.Call(b.Pkg.rtFunc("TracePanic"), v) b.impl.CreateUnreachable() }