|
|
@ -209,6 +209,95 @@ func (c *Compiler) Parse(mainPath string, buildTags []string) error { |
|
|
|
} |
|
|
|
|
|
|
|
for _, pkg := range packageList { |
|
|
|
c.parsePackage(program, pkg) |
|
|
|
} |
|
|
|
|
|
|
|
return nil |
|
|
|
} |
|
|
|
|
|
|
|
func (c *Compiler) getLLVMType(goType types.Type) (llvm.Type, error) { |
|
|
|
fmt.Println(" type:", goType) |
|
|
|
switch typ := goType.(type) { |
|
|
|
case *types.Array: |
|
|
|
elemType, err := c.getLLVMType(typ.Elem()) |
|
|
|
if err != nil { |
|
|
|
return llvm.Type{}, err |
|
|
|
} |
|
|
|
return llvm.ArrayType(elemType, int(typ.Len())), nil |
|
|
|
case *types.Basic: |
|
|
|
switch typ.Kind() { |
|
|
|
case types.Bool: |
|
|
|
return llvm.Int1Type(), nil |
|
|
|
case types.Int8, types.Uint8: |
|
|
|
return llvm.Int8Type(), nil |
|
|
|
case types.Int16, types.Uint16: |
|
|
|
return llvm.Int16Type(), nil |
|
|
|
case types.Int32, types.Uint32: |
|
|
|
return llvm.Int32Type(), nil |
|
|
|
case types.Int, types.Uint: |
|
|
|
return c.intType, nil |
|
|
|
case types.Int64, types.Uint64: |
|
|
|
return llvm.Int64Type(), nil |
|
|
|
case types.String: |
|
|
|
return c.stringType, nil |
|
|
|
case types.Uintptr: |
|
|
|
return c.uintptrType, nil |
|
|
|
case types.UnsafePointer: |
|
|
|
return llvm.PointerType(llvm.Int8Type(), 0), nil |
|
|
|
default: |
|
|
|
return llvm.Type{}, errors.New("todo: unknown basic type: " + fmt.Sprintf("%#v", typ)) |
|
|
|
} |
|
|
|
case *types.Interface: |
|
|
|
return c.interfaceType, nil |
|
|
|
case *types.Named: |
|
|
|
return c.getLLVMType(typ.Underlying()) |
|
|
|
case *types.Pointer: |
|
|
|
ptrTo, err := c.getLLVMType(typ.Elem()) |
|
|
|
if err != nil { |
|
|
|
return llvm.Type{}, err |
|
|
|
} |
|
|
|
return llvm.PointerType(ptrTo, 0), nil |
|
|
|
case *types.Struct: |
|
|
|
members := make([]llvm.Type, typ.NumFields()) |
|
|
|
for i := 0; i < typ.NumFields(); i++ { |
|
|
|
member, err := c.getLLVMType(typ.Field(i).Type()) |
|
|
|
if err != nil { |
|
|
|
return llvm.Type{}, err |
|
|
|
} |
|
|
|
members[i] = member |
|
|
|
} |
|
|
|
return llvm.StructType(members, false), nil |
|
|
|
default: |
|
|
|
return llvm.Type{}, errors.New("todo: unknown type: " + fmt.Sprintf("%#v", goType)) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
func (c *Compiler) getInterfaceType(typ types.Type) llvm.Value { |
|
|
|
if _, ok := c.itfTypeNumbers[typ]; !ok { |
|
|
|
num := uint64(len(c.itfTypes)) |
|
|
|
c.itfTypes = append(c.itfTypes, typ) |
|
|
|
c.itfTypeNumbers[typ] = num |
|
|
|
} |
|
|
|
return llvm.ConstInt(llvm.Int32Type(), c.itfTypeNumbers[typ], false) |
|
|
|
} |
|
|
|
|
|
|
|
func (c *Compiler) getFunctionName(fn *ssa.Function) string { |
|
|
|
if fn.Signature.Recv() != nil { |
|
|
|
// Method on a defined type.
|
|
|
|
typeName := fn.Params[0].Type().(*types.Named).Obj().Name() |
|
|
|
return pkgPrefix(fn.Pkg) + "." + typeName + "." + fn.Name() |
|
|
|
} else { |
|
|
|
// Bare function.
|
|
|
|
if strings.HasPrefix(fn.Name(), "_Cfunc_") { |
|
|
|
// Name CGo functions directly.
|
|
|
|
return fn.Name()[len("_Cfunc_"):] |
|
|
|
} else { |
|
|
|
return pkgPrefix(fn.Pkg) + "." + fn.Name() |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
func (c *Compiler) parsePackage(program *ssa.Program, pkg *ssa.Package) error { |
|
|
|
fmt.Println("package:", pkg.Pkg.Path()) |
|
|
|
|
|
|
|
// Make sure we're walking through all members in a constant order every
|
|
|
@ -239,9 +328,12 @@ func (c *Compiler) Parse(mainPath string, buildTags []string) error { |
|
|
|
return err |
|
|
|
} |
|
|
|
frames[member] = frame |
|
|
|
if member.Synthetic == "package initializer" { |
|
|
|
c.initFuncs = append(c.initFuncs, frame.llvmFn) |
|
|
|
} |
|
|
|
case *ssa.NamedConst: |
|
|
|
// Ignore package-level untyped constants. The SSA form doesn't
|
|
|
|
// need them.
|
|
|
|
// Ignore package-level untyped constants. The SSA form doesn't need
|
|
|
|
// them.
|
|
|
|
case *ssa.Global: |
|
|
|
typ, err := c.getLLVMType(member.Type()) |
|
|
|
if err != nil { |
|
|
@ -295,93 +387,10 @@ func (c *Compiler) Parse(mainPath string, buildTags []string) error { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return nil |
|
|
|
} |
|
|
|
|
|
|
|
func (c *Compiler) getLLVMType(goType types.Type) (llvm.Type, error) { |
|
|
|
fmt.Println(" type:", goType) |
|
|
|
switch typ := goType.(type) { |
|
|
|
case *types.Array: |
|
|
|
elemType, err := c.getLLVMType(typ.Elem()) |
|
|
|
if err != nil { |
|
|
|
return llvm.Type{}, err |
|
|
|
} |
|
|
|
return llvm.ArrayType(elemType, int(typ.Len())), nil |
|
|
|
case *types.Basic: |
|
|
|
switch typ.Kind() { |
|
|
|
case types.Bool: |
|
|
|
return llvm.Int1Type(), nil |
|
|
|
case types.Int8, types.Uint8: |
|
|
|
return llvm.Int8Type(), nil |
|
|
|
case types.Int16, types.Uint16: |
|
|
|
return llvm.Int16Type(), nil |
|
|
|
case types.Int32, types.Uint32: |
|
|
|
return llvm.Int32Type(), nil |
|
|
|
case types.Int, types.Uint: |
|
|
|
return c.intType, nil |
|
|
|
case types.Int64, types.Uint64: |
|
|
|
return llvm.Int64Type(), nil |
|
|
|
case types.String: |
|
|
|
return c.stringType, nil |
|
|
|
case types.Uintptr: |
|
|
|
return c.uintptrType, nil |
|
|
|
case types.UnsafePointer: |
|
|
|
return llvm.PointerType(llvm.Int8Type(), 0), nil |
|
|
|
default: |
|
|
|
return llvm.Type{}, errors.New("todo: unknown basic type: " + fmt.Sprintf("%#v", typ)) |
|
|
|
} |
|
|
|
case *types.Interface: |
|
|
|
return c.interfaceType, nil |
|
|
|
case *types.Named: |
|
|
|
return c.getLLVMType(typ.Underlying()) |
|
|
|
case *types.Pointer: |
|
|
|
ptrTo, err := c.getLLVMType(typ.Elem()) |
|
|
|
if err != nil { |
|
|
|
return llvm.Type{}, err |
|
|
|
} |
|
|
|
return llvm.PointerType(ptrTo, 0), nil |
|
|
|
case *types.Struct: |
|
|
|
members := make([]llvm.Type, typ.NumFields()) |
|
|
|
for i := 0; i < typ.NumFields(); i++ { |
|
|
|
member, err := c.getLLVMType(typ.Field(i).Type()) |
|
|
|
if err != nil { |
|
|
|
return llvm.Type{}, err |
|
|
|
} |
|
|
|
members[i] = member |
|
|
|
} |
|
|
|
return llvm.StructType(members, false), nil |
|
|
|
default: |
|
|
|
return llvm.Type{}, errors.New("todo: unknown type: " + fmt.Sprintf("%#v", goType)) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
func (c *Compiler) getInterfaceType(typ types.Type) llvm.Value { |
|
|
|
if _, ok := c.itfTypeNumbers[typ]; !ok { |
|
|
|
num := uint64(len(c.itfTypes)) |
|
|
|
c.itfTypes = append(c.itfTypes, typ) |
|
|
|
c.itfTypeNumbers[typ] = num |
|
|
|
} |
|
|
|
return llvm.ConstInt(llvm.Int32Type(), c.itfTypeNumbers[typ], false) |
|
|
|
} |
|
|
|
|
|
|
|
func (c *Compiler) getFunctionName(fn *ssa.Function) string { |
|
|
|
if fn.Signature.Recv() != nil { |
|
|
|
// Method on a defined type.
|
|
|
|
typeName := fn.Params[0].Type().(*types.Named).Obj().Name() |
|
|
|
return pkgPrefix(fn.Pkg) + "." + typeName + "." + fn.Name() |
|
|
|
} else { |
|
|
|
// Bare function.
|
|
|
|
if strings.HasPrefix(fn.Name(), "_Cfunc_") { |
|
|
|
// Name CGo functions directly.
|
|
|
|
return fn.Name()[len("_Cfunc_"):] |
|
|
|
} else { |
|
|
|
return pkgPrefix(fn.Pkg) + "." + fn.Name() |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
func (c *Compiler) parseFuncDecl(f *ssa.Function) (*Frame, error) { |
|
|
|
f.WriteTo(os.Stdout) |
|
|
|
name := c.getFunctionName(f) |
|
|
|