github.com/goplus/llgo@v0.8.3/ssa/decl.go (about) 1 /* 2 * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package ssa 18 19 import ( 20 "go/types" 21 "log" 22 "strconv" 23 24 "github.com/goplus/llvm" 25 ) 26 27 // ----------------------------------------------------------------------------- 28 29 const ( 30 ClosureCtx = "__llgo_ctx" 31 ClosureStub = "__llgo_stub." 32 ) 33 34 // ----------------------------------------------------------------------------- 35 36 const ( 37 NameValist = "__llgo_va_list" 38 ) 39 40 func VArg() *types.Var { 41 return types.NewParam(0, nil, NameValist, types.NewSlice(tyAny)) 42 } 43 44 // ----------------------------------------------------------------------------- 45 46 type aNamedConst struct { 47 } 48 49 // A NamedConst is a Member of a Package representing a package-level 50 // named constant. 51 // 52 // Pos() returns the position of the declaring ast.ValueSpec.Names[*] 53 // identifier. 54 // 55 // NB: a NamedConst is not a Value; it contains a constant Value, which 56 // it augments with the name and position of its 'const' declaration. 57 type NamedConst = *aNamedConst 58 59 // ----------------------------------------------------------------------------- 60 61 type aGlobal struct { 62 Expr 63 array bool 64 } 65 66 // A Global is a named Value holding the address of a package-level 67 // variable. 68 type Global = *aGlobal 69 70 // NewVar creates a new global variable. 71 func (p Package) NewVar(name string, typ types.Type, bg Background) Global { 72 if v, ok := p.vars[name]; ok { 73 return v 74 } 75 t := p.Prog.Type(typ, bg) 76 var gbl llvm.Value 77 var array bool 78 if t.kind == vkPtr && p.Prog.Elem(t).kind == vkArray { 79 typ := p.Prog.Elem(t).ll 80 gbl = llvm.AddGlobal(p.mod, typ, name) 81 gbl.SetInitializer(llvm.Undef(typ)) 82 array = true 83 } else { 84 gbl = llvm.AddGlobal(p.mod, t.ll, name) 85 } 86 ret := &aGlobal{Expr{gbl, t}, array} 87 p.vars[name] = ret 88 return ret 89 } 90 91 // VarOf returns a global variable by name. 92 func (p Package) VarOf(name string) Global { 93 return p.vars[name] 94 } 95 96 // Init initializes the global variable with the given value. 97 func (g Global) Init(v Expr) { 98 if g.array && v.kind == vkPtr { 99 return 100 } 101 g.impl.SetInitializer(v.impl) 102 } 103 104 // ----------------------------------------------------------------------------- 105 106 // Function represents the parameters, results, and code of a function 107 // or method. 108 // 109 // If Blocks is nil, this indicates an external function for which no 110 // Go source code is available. In this case, FreeVars, Locals, and 111 // Params are nil too. Clients performing whole-program analysis must 112 // handle external functions specially. 113 // 114 // Blocks contains the function's control-flow graph (CFG). 115 // Blocks[0] is the function entry point; block order is not otherwise 116 // semantically significant, though it may affect the readability of 117 // the disassembly. 118 // To iterate over the blocks in dominance order, use DomPreorder(). 119 // 120 // Recover is an optional second entry point to which control resumes 121 // after a recovered panic. The Recover block may contain only a return 122 // statement, preceded by a load of the function's named return 123 // parameters, if any. 124 // 125 // A nested function (Parent()!=nil) that refers to one or more 126 // lexically enclosing local variables ("free variables") has FreeVars. 127 // Such functions cannot be called directly but require a 128 // value created by MakeClosure which, via its Bindings, supplies 129 // values for these parameters. 130 // 131 // If the function is a method (Signature.Recv() != nil) then the first 132 // element of Params is the receiver parameter. 133 // 134 // A Go package may declare many functions called "init". 135 // For each one, Object().Name() returns "init" but Name() returns 136 // "init#1", etc, in declaration order. 137 // 138 // Pos() returns the declaring ast.FuncLit.Type.Func or the position 139 // of the ast.FuncDecl.Name, if the function was explicit in the 140 // source. Synthetic wrappers, for which Synthetic != "", may share 141 // the same position as the function they wrap. 142 // Syntax.Pos() always returns the position of the declaring "func" token. 143 // 144 // Type() returns the function's Signature. 145 // 146 // A generic function is a function or method that has uninstantiated type 147 // parameters (TypeParams() != nil). Consider a hypothetical generic 148 // method, (*Map[K,V]).Get. It may be instantiated with all ground 149 // (non-parameterized) types as (*Map[string,int]).Get or with 150 // parameterized types as (*Map[string,U]).Get, where U is a type parameter. 151 // In both instantiations, Origin() refers to the instantiated generic 152 // method, (*Map[K,V]).Get, TypeParams() refers to the parameters [K,V] of 153 // the generic method. TypeArgs() refers to [string,U] or [string,int], 154 // respectively, and is nil in the generic method. 155 type aFunction struct { 156 Expr 157 Pkg Package 158 Prog Program 159 160 blks []BasicBlock 161 162 params []Type 163 freeVars Expr 164 base int // base = 1 if hasFreeVars; base = 0 otherwise 165 hasVArg bool 166 } 167 168 // Function represents a function or method. 169 type Function = *aFunction 170 171 // NewFunc creates a new function. 172 func (p Package) NewFunc(name string, sig *types.Signature, bg Background) Function { 173 return p.NewFuncEx(name, sig, bg, false) 174 } 175 176 // NewFuncEx creates a new function. 177 func (p Package) NewFuncEx(name string, sig *types.Signature, bg Background, hasFreeVars bool) Function { 178 if v, ok := p.fns[name]; ok { 179 return v 180 } 181 t := p.Prog.FuncDecl(sig, bg) 182 if debugInstr { 183 log.Println("NewFunc", name, t.raw.Type, "hasFreeVars:", hasFreeVars) 184 } 185 fn := llvm.AddFunction(p.mod, name, t.ll) 186 ret := newFunction(fn, t, p, p.Prog, hasFreeVars) 187 p.fns[name] = ret 188 return ret 189 } 190 191 // FuncOf returns a function by name. 192 func (p Package) FuncOf(name string) Function { 193 return p.fns[name] 194 } 195 196 func newFunction(fn llvm.Value, t Type, pkg Package, prog Program, hasFreeVars bool) Function { 197 params, hasVArg := newParams(t, prog) 198 base := 0 199 if hasFreeVars { 200 base = 1 201 } 202 return &aFunction{Expr{fn, t}, pkg, prog, nil, params, Expr{}, base, hasVArg} 203 } 204 205 func newParams(fn Type, prog Program) (params []Type, hasVArg bool) { 206 sig := fn.raw.Type.(*types.Signature) 207 in := sig.Params() 208 if n := in.Len(); n > 0 { 209 if hasVArg = sig.Variadic(); hasVArg { 210 n-- 211 } 212 params = make([]Type, n) 213 for i := 0; i < n; i++ { 214 params[i] = prog.rawType(in.At(i).Type()) 215 } 216 } 217 return 218 } 219 220 // Params returns the function's ith parameter. 221 func (p Function) Param(i int) Expr { 222 i += p.base // skip if hasFreeVars 223 return Expr{p.impl.Param(i), p.params[i]} 224 } 225 226 func (p Function) closureCtx(b Builder) Expr { 227 if p.freeVars.IsNil() { 228 if p.base == 0 { 229 panic("ssa: function has no free variables") 230 } 231 ptr := Expr{p.impl.Param(0), p.params[0]} 232 p.freeVars = b.Load(ptr) 233 } 234 return p.freeVars 235 } 236 237 // FreeVar returns the function's ith free variable. 238 func (p Function) FreeVar(b Builder, i int) Expr { 239 ctx := p.closureCtx(b) 240 return b.getField(ctx, i) 241 } 242 243 // NewBuilder creates a new Builder for the function. 244 func (p Function) NewBuilder() Builder { 245 prog := p.Prog 246 b := prog.ctx.NewBuilder() 247 // TODO(xsw): Finalize may cause panic, so comment it. 248 // b.Finalize() 249 return &aBuilder{b, p, prog} 250 } 251 252 // HasBody reports whether the function has a body. 253 func (p Function) HasBody() bool { 254 return len(p.blks) > 0 255 } 256 257 // MakeBody creates nblk basic blocks for the function, and creates 258 // a new Builder associated to #0 block. 259 func (p Function) MakeBody(nblk int) Builder { 260 p.MakeBlocks(nblk) 261 b := p.NewBuilder() 262 b.impl.SetInsertPointAtEnd(p.blks[0].impl) 263 return b 264 } 265 266 // MakeBlocks creates nblk basic blocks for the function. 267 func (p Function) MakeBlocks(nblk int) []BasicBlock { 268 n := len(p.blks) 269 if n == 0 { 270 p.blks = make([]BasicBlock, 0, nblk) 271 } 272 for i := 0; i < nblk; i++ { 273 p.addBlock(n + i) 274 } 275 return p.blks[n:] 276 } 277 278 func (p Function) addBlock(idx int) BasicBlock { 279 label := "_llgo_" + strconv.Itoa(idx) 280 blk := llvm.AddBasicBlock(p.impl, label) 281 ret := &aBasicBlock{blk, p, idx} 282 p.blks = append(p.blks, ret) 283 return ret 284 } 285 286 // MakeBlock creates a new basic block for the function. 287 func (p Function) MakeBlock() BasicBlock { 288 return p.addBlock(len(p.blks)) 289 } 290 291 // Block returns the ith basic block of the function. 292 func (p Function) Block(idx int) BasicBlock { 293 return p.blks[idx] 294 } 295 296 // ----------------------------------------------------------------------------- 297 298 type aPyGlobal struct { 299 Expr 300 } 301 302 type PyGlobal = *aPyGlobal 303 304 // PyNewVar creates a Python variable. 305 func (b Builder) PyNewVar(modName, name string) PyGlobal { 306 pkg := b.Func.Pkg 307 modPtr := pkg.PyNewModVar(modName, false).Expr 308 mod := b.Load(modPtr) 309 return &aPyGlobal{pyVarExpr(mod, name)} 310 } 311 312 func (b Builder) pyLoad(ptr Expr) Expr { 313 pkg := b.Func.Pkg 314 t := ptr.raw.Type.(*pyVarTy) 315 fn := pkg.pyFunc("PyObject_GetAttrString", b.Prog.tyGetAttrString()) 316 return b.Call(fn, t.mod, b.CStr(t.name)) 317 } 318 319 // ----------------------------------------------------------------------------- 320 321 type aPyObjRef struct { 322 Expr 323 Obj Global 324 } 325 326 // PyObjRef represents a python object reference. 327 type PyObjRef = *aPyObjRef 328 329 // PyNewFunc creates a new python function. 330 func (p Package) PyNewFunc(name string, sig *types.Signature, doInit bool) PyObjRef { 331 if v, ok := p.pyobjs[name]; ok { 332 return v 333 } 334 prog := p.Prog 335 obj := p.NewVar(name, prog.PyObjectPtrPtr().RawType(), InC) 336 if doInit { 337 prog.NeedPyInit = true 338 obj.Init(prog.Null(obj.Type)) 339 obj.impl.SetLinkage(llvm.LinkOnceAnyLinkage) 340 } 341 ty := &aType{obj.ll, rawType{types.NewPointer(sig)}, vkPyFuncRef} 342 expr := Expr{obj.impl, ty} 343 ret := &aPyObjRef{expr, obj} 344 p.pyobjs[name] = ret 345 return ret 346 } 347 348 // PyObjOf returns a python object by name. 349 func (p Package) PyObjOf(name string) PyObjRef { 350 return p.pyobjs[name] 351 } 352 353 // PyObjs returns all used python objects in this project. 354 func (p Package) PyObjs() map[string]PyObjRef { 355 return p.pyobjs 356 } 357 358 // -----------------------------------------------------------------------------