Exemplo n.º 1
0
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
}
Exemplo n.º 2
0
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)
}
Exemplo n.º 3
0
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)
}
Exemplo n.º 4
0
// 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
}
Exemplo n.º 5
0
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
}
Exemplo n.º 6
0
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
}