func (m *TypeMap) descriptorInterface(t *types.Interface, name string) TypeDebugDescriptor { ifaceStruct := types.NewStruct([]*types.Var{ types.NewVar(0, nil, "type", types.NewPointer(types.Typ[types.Uint8])), types.NewVar(0, nil, "data", types.NewPointer(types.Typ[types.Uint8])), }, nil) return m.typeDebugDescriptor(ifaceStruct, name) }
// tupleType returns a struct type with anonymous // fields with the specified types. func tupleType(fieldTypes ...types.Type) types.Type { vars := make([]*types.Var, len(fieldTypes)) for i, t := range fieldTypes { vars[i] = types.NewParam(0, nil, fmt.Sprintf("f%d", i), t) } return types.NewStruct(vars, nil) }
func (m *TypeMap) descriptorSlice(t *types.Slice, name string) TypeDebugDescriptor { sliceStruct := types.NewStruct([]*types.Var{ types.NewVar(0, nil, "ptr", types.NewPointer(t.Elem())), types.NewVar(0, nil, "len", types.Typ[types.Int]), types.NewVar(0, nil, "cap", types.Typ[types.Int]), }, nil) return m.typeDebugDescriptor(sliceStruct, name) }
// StructType = "struct" "{" { Field } "}" . func (p *parser) parseStructType(pkg *types.Package) types.Type { p.expectKeyword("struct") var fields []*types.Var var tags []string p.expect('{') for p.tok != '}' && p.tok != scanner.EOF { field, tag := p.parseField(pkg) p.expect(';') fields = append(fields, field) tags = append(tags, tag) } p.expect('}') return types.NewStruct(fields, tags) }
func (m *TypeMap) descriptorBasic(t *types.Basic, name string) TypeDebugDescriptor { switch t.Kind() { case types.String: return m.descriptorStruct(types.NewStruct([]*types.Var{ types.NewVar(0, nil, "ptr", types.NewPointer(types.Typ[types.Uint8])), types.NewVar(0, nil, "len", types.Typ[types.Int]), }, nil), name) case types.UnsafePointer: return &BasicTypeDescriptor{ TypeDescriptorCommon: TypeDescriptorCommon{ Name: name, Size: uint64(m.Sizes.Sizeof(t) * 8), Alignment: uint64(m.Sizes.Alignof(t) * 8), }, TypeEncoding: DW_ATE_unsigned, } default: bt := &BasicTypeDescriptor{ TypeDescriptorCommon: TypeDescriptorCommon{ Name: t.String(), Size: uint64(m.Sizes.Sizeof(t) * 8), Alignment: uint64(m.Sizes.Alignof(t) * 8), }, } switch bi := t.Info(); { case bi&types.IsBoolean != 0: bt.TypeEncoding = DW_ATE_boolean case bi&types.IsUnsigned != 0: bt.TypeEncoding = DW_ATE_unsigned case bi&types.IsInteger != 0: bt.TypeEncoding = DW_ATE_signed case bi&types.IsFloat != 0: bt.TypeEncoding = DW_ATE_float case bi&types.IsComplex != 0: bt.TypeEncoding = DW_ATE_imaginary_float case bi&types.IsUnsigned != 0: bt.TypeEncoding = DW_ATE_unsigned default: panic(fmt.Sprintf("unhandled: %#v", t)) } return bt } }
// StructType = "struct" "{" [ FieldList ] "}" . // FieldList = Field { ";" Field } . // func (p *parser) parseStructType() types.Type { var fields []*types.Var var tags []string p.expectKeyword("struct") p.expect('{') for i := 0; p.tok != '}' && p.tok != scanner.EOF; i++ { if i > 0 { p.expect(';') } fld, tag := p.parseField() if tag != "" && tags == nil { tags = make([]string, i) } if tags != nil { tags = append(tags, tag) } fields = append(fields, fld) } p.expect('}') return types.NewStruct(fields, tags) }
func (cdd *CDD) tupleName(tup *types.Tuple) (tupName string, fields []*types.Var, acds []*CDD) { n := tup.Len() for i := 0; i < n; i++ { if i != 0 { tupName += "$$" } name, dim, a := cdd.TypeStr(tup.At(i).Type()) tupName += dimFuncPtr(name, dim) acds = append(acds, a...) } tupName = strings.Map(symToDol, tupName) fields = make([]*types.Var, n) for i := 0; i < n; i++ { v := tup.At(i) fields[i] = types.NewField( v.Pos(), v.Pkg(), "_"+strconv.Itoa(i), v.Type(), false, ) } if _, ok := cdd.gtc.tupNames[tupName]; ok { return } cdd.gtc.tupNames[tupName] = struct{}{} s := types.NewStruct(fields, nil) o := types.NewTypeName(tup.At(0).Pos(), cdd.gtc.pkg, tupName, s) acd := cdd.gtc.newCDD(o, TypeDecl, 0) acd.structDecl(new(bytes.Buffer), tupName, s) cdd.DeclUses[o] = true acds = append(acds, acd) return }
func (p *importer) typ() types.Type { // if the type was seen before, i is its index (>= 0) i := p.int() if i >= 0 { return p.typList[i] } // otherwise, i is the type tag (< 0) switch i { case arrayTag: t := new(types.Array) p.record(t) n := p.int64() *t = *types.NewArray(p.typ(), n) return t case sliceTag: t := new(types.Slice) p.record(t) *t = *types.NewSlice(p.typ()) return t case structTag: t := new(types.Struct) p.record(t) n := p.int() fields := make([]*types.Var, n) tags := make([]string, n) for i := range fields { fields[i] = p.field() tags[i] = p.string() } *t = *types.NewStruct(fields, tags) return t case pointerTag: t := new(types.Pointer) p.record(t) *t = *types.NewPointer(p.typ()) return t case signatureTag: t := new(types.Signature) p.record(t) *t = *p.signature() return t case interfaceTag: t := new(types.Interface) p.record(t) // read embedded interfaces embeddeds := make([]*types.Named, p.int()) for i := range embeddeds { embeddeds[i] = p.typ().(*types.Named) } // read methods methods := make([]*types.Func, p.int()) for i := range methods { pkg, name := p.qualifiedName() methods[i] = types.NewFunc(token.NoPos, pkg, name, p.typ().(*types.Signature)) } *t = *types.NewInterface(methods, embeddeds) return t case mapTag: t := new(types.Map) p.record(t) *t = *types.NewMap(p.typ(), p.typ()) return t case chanTag: t := new(types.Chan) p.record(t) *t = *types.NewChan(types.ChanDir(p.int()), p.typ()) return t case namedTag: // read type object name := p.string() pkg := p.pkg() scope := pkg.Scope() obj := scope.Lookup(name) // if the object doesn't exist yet, create and insert it if obj == nil { obj = types.NewTypeName(token.NoPos, pkg, name, nil) scope.Insert(obj) } // associate new named type with obj if it doesn't exist yet t0 := types.NewNamed(obj.(*types.TypeName), nil, nil) // but record the existing type, if any t := obj.Type().(*types.Named) p.record(t) // read underlying type t0.SetUnderlying(p.typ()) // read associated methods for i, n := 0, p.int(); i < n; i++ { t0.AddMethod(types.NewFunc(token.NoPos, pkg, p.string(), p.typ().(*types.Signature))) } return t default: panic(fmt.Sprintf("unexpected type tag %d", i)) } }
func (c *compiler) VisitFuncLit(lit *ast.FuncLit) Value { ftyp := c.types.expr[lit].Type.(*types.Signature) // Walk the function literal, promoting stack vars not defined // in the function literal, and storing the ident's for non-const // values not declared in the function literal. // // (First, set a dummy "stack" value for the params and results.) var dummyfunc LLVMValue dummyfunc.stack = &dummyfunc paramVars := ftyp.Params() resultVars := ftyp.Results() c.functions.push(&function{ LLVMValue: &dummyfunc, results: resultVars, }) v := &identVisitor{compiler: c} ast.Walk(v, lit.Body) c.functions.pop() // Create closure by adding a context parameter to the function, // and bind it with the values of the stack vars found in the // step above. origfnpairtyp := c.types.ToLLVM(ftyp) fnpairtyp := origfnpairtyp fntyp := origfnpairtyp.StructElementTypes()[0].ElementType() if v.captures != nil { // Add the additional context param. ctxfields := make([]*types.Field, len(v.captures)) for i, capturevar := range v.captures { ctxfields[i] = &types.Field{ Type: types.NewPointer(capturevar.Type()), } } ctxtyp := types.NewPointer(types.NewStruct(ctxfields, nil)) llvmctxtyp := c.types.ToLLVM(ctxtyp) rettyp := fntyp.ReturnType() paramtyps := append([]llvm.Type{llvmctxtyp}, fntyp.ParamTypes()...) vararg := fntyp.IsFunctionVarArg() fntyp = llvm.FunctionType(rettyp, paramtyps, vararg) opaqueptrtyp := origfnpairtyp.StructElementTypes()[1] elttyps := []llvm.Type{llvm.PointerType(fntyp, 0), opaqueptrtyp} fnpairtyp = llvm.StructType(elttyps, false) } fnptr := llvm.AddFunction(c.module.Module, "", fntyp) fnvalue := llvm.ConstNull(fnpairtyp) fnvalue = llvm.ConstInsertValue(fnvalue, fnptr, []uint32{0}) currBlock := c.builder.GetInsertBlock() f := c.NewValue(fnvalue, ftyp) captureVars := types.NewTuple(v.captures...) c.buildFunction(f, captureVars, paramVars, resultVars, lit.Body, ftyp.IsVariadic()) // Closure? Bind values to a context block. if v.captures != nil { // Store the free variables in the heap allocated block. block := c.createTypeMalloc(fntyp.ParamTypes()[0].ElementType()) for i, contextvar := range v.captures { value := c.objectdata[contextvar].Value blockPtr := c.builder.CreateStructGEP(block, i, "") c.builder.CreateStore(value.pointer.LLVMValue(), blockPtr) } // Cast the function pointer type back to the original // type, without the context parameter. fnptr = llvm.ConstBitCast(fnptr, origfnpairtyp.StructElementTypes()[0]) fnvalue = llvm.Undef(origfnpairtyp) fnvalue = llvm.ConstInsertValue(fnvalue, fnptr, []uint32{0}) // Set the context value. i8ptr := llvm.PointerType(llvm.Int8Type(), 0) block = c.builder.CreateBitCast(block, i8ptr, "") fnvalue = c.builder.CreateInsertValue(fnvalue, block, 1, "") f.value = fnvalue } else { c.builder.SetInsertPointAtEnd(currBlock) } return f }