func doParseReflect() { buildpkg, err := build.Import("reflect", "", 0) if err != nil { parseReflectResult, parseReflectError = nil, err return } filenames := make([]string, len(buildpkg.GoFiles)) for i, f := range buildpkg.GoFiles { filenames[i] = path.Join(buildpkg.Dir, f) } fset := token.NewFileSet() files, err := parseFiles(fset, filenames) if err != nil { parseReflectResult, parseReflectError = nil, err return } pkg, err := ast.NewPackage(fset, files, types.GcImport, types.Universe) if err != nil { parseReflectResult, parseReflectError = nil, err return } _, err = types.Check(fset, pkg) if err != nil { parseReflectResult, parseReflectError = nil, err return } parseReflectResult, parseReflectError = pkg, nil return }
func compilePackage(fset *token.FileSet, files map[string]*ast.File) (*llgo.Module, error) { // make a package (resolve all identifiers) pkg, err := ast.NewPackage(fset, files, types.GcImport, types.Universe) if err != nil { report(err) return nil, err } exprTypes, err := types.Check(fset, pkg) if err != nil { report(err) return nil, err } if *dumpast { ast.Fprint(os.Stderr, fset, pkg, nil) os.Exit(0) } compiler := llgo.NewCompiler() compiler.SetTraceEnabled(*trace) compiler.SetTargetArch(*arch) compiler.SetTargetOs(*os_) return compiler.Compile(fset, pkg, exprTypes) }
func compilePackage(compiler llgo.Compiler, fset *token.FileSet, files map[string]*ast.File, importpath string) (*llgo.Module, error) { // make a package (resolve all identifiers) pkg, err := ast.NewPackage(fset, files, types.GcImport, types.Universe) if err != nil { report(err) return nil, err } // an empty importpath means the same as the package name if importpath == "" { importpath = pkg.Name } exprTypes, err := types.Check(importpath, compiler, fset, pkg) if err != nil { report(err) return nil, err } if *dumpast { ast.Fprint(os.Stderr, fset, pkg, nil) os.Exit(0) } return compiler.Compile(fset, pkg, importpath, exprTypes) }
// parseReflect parses the reflect package and type-checks its AST. // This is used to generate runtime type structures. func (c *compiler) parseReflect() (*ast.Package, error) { buildpkg, err := build.Import("reflect", "", 0) if err != nil { return nil, err } filenames := make([]string, len(buildpkg.GoFiles)) for i, f := range buildpkg.GoFiles { filenames[i] = path.Join(buildpkg.Dir, f) } fset := token.NewFileSet() files, err := parseFiles(fset, filenames) if err != nil { return nil, err } pkg, err := ast.NewPackage(fset, files, types.GcImport, types.Universe) if err != nil { return nil, err } _, err = types.Check(buildpkg.Name, c, fset, pkg) if err != nil { return nil, err } return pkg, nil }
func (c *FunctionCache) NamedFunction(name string, signature string) llvm.Value { f, _ := c.functions[name+":"+signature] if !f.IsNil() { return f } if strings.HasPrefix(name, c.module.Name+".") { obj := c.pkg.Scope.Lookup(name[len(c.module.Name)+1:]) value := c.Resolve(obj) f = value.LLVMValue() } else { fset := token.NewFileSet() code := `package runtime;import("unsafe");` + signature + `{panic()}` file, err := parser.ParseFile(fset, "", code, 0) if err != nil { panic(err) } // Parse the runtime package, since we may need to refer to // its types. TODO cache the package. buildpkg, err := build.Import("github.com/axw/llgo/pkg/runtime", "", 0) if err != nil { panic(err) } runtimefiles := make([]string, len(buildpkg.GoFiles)) for i, f := range buildpkg.GoFiles { runtimefiles[i] = path.Join(buildpkg.Dir, f) } files, err := parseFiles(fset, runtimefiles) if err != nil { panic(err) } files["<src>"] = file pkg, err := ast.NewPackage(fset, files, types.GcImport, types.Universe) if err != nil { panic(err) } _, err = types.Check(fset, pkg) if err != nil { panic(err) } fdecl := file.Decls[len(file.Decls)-1].(*ast.FuncDecl) ftype := fdecl.Name.Obj.Type.(*types.Func) llvmfptrtype := c.types.ToLLVM(ftype) f = llvm.AddFunction(c.module.Module, name, llvmfptrtype.ElementType()) if !strings.HasPrefix(name, "llvm.") { f.SetLinkage(llvm.AvailableExternallyLinkage) } } c.functions[name+":"+signature] = f return f }
func (c *FunctionCache) NamedFunction(name string, signature string) llvm.Value { f, _ := c.functions[name+":"+signature] if !f.IsNil() { return f } if strings.HasPrefix(name, c.module.Name+".") { obj := c.pkg.Scope.Lookup(name[len(c.module.Name)+1:]) value := c.Resolve(obj) f = value.LLVMValue() } else { fset := token.NewFileSet() code := `package runtime;import("unsafe");` + signature + `{panic()}` file, err := parser.ParseFile(fset, "", code, 0) if err != nil { panic(err) } // Parse the runtime package, since we may need to refer to // its types. Can't be cached, because type-checking can't // be done twice on the AST. buildpkg, err := build.Import("github.com/axw/llgo/pkg/runtime", "", 0) if err != nil { panic(err) } // All types visible to the compiler are in "types.go". runtimefiles := []string{path.Join(buildpkg.Dir, "types.go")} files, err := parseFiles(fset, runtimefiles) if err != nil { panic(err) } files["<src>"] = file pkg, err := ast.NewPackage(fset, files, types.GcImport, types.Universe) if err != nil { panic(err) } _, err = types.Check("", c.compiler, fset, pkg) if err != nil { panic(err) } fdecl := file.Decls[len(file.Decls)-1].(*ast.FuncDecl) ftype := fdecl.Name.Obj.Type.(*types.Func) llvmfptrtype := c.types.ToLLVM(ftype) f = llvm.AddFunction(c.module.Module, name, llvmfptrtype.ElementType()) } c.functions[name+":"+signature] = f return f }