Exemple #1
0
func NewCompiler(opts CompilerOptions) (Compiler, error) {
	compiler := &compiler{CompilerOptions: opts}
	if strings.ToLower(compiler.TargetTriple) == "pnacl" {
		compiler.TargetTriple = PNaClTriple
		compiler.pnacl = true
	}

	// Triples are several fields separated by '-' characters.
	// The first field is the architecture. The architecture's
	// canonical form may include a '-' character, which would
	// have been translated to '_' for inclusion in a triple.
	triple := compiler.TargetTriple
	arch := triple[:strings.IndexRune(triple, '-')]
	arch = parseArch(arch)
	var machine llvm.TargetMachine
	for target := llvm.FirstTarget(); target.C != nil; target = target.NextTarget() {
		if arch == target.Name() {
			machine = target.CreateTargetMachine(triple, "", "",
				llvm.CodeGenLevelDefault,
				llvm.RelocDefault,
				llvm.CodeModelDefault)
			compiler.machine = machine
			break
		}
	}

	if machine.C == nil {
		return nil, fmt.Errorf("Invalid target triple: %s", triple)
	}
	compiler.target = machine.TargetData()
	return compiler, nil
}
Exemple #2
0
func (compiler *compiler) Compile(fset *token.FileSet,
	pkg *ast.Package,
	exprTypes map[ast.Expr]types.Type) (m *Module, err error) {
	// FIXME create a compilation state, rather than storing in 'compiler'.
	compiler.fileset = fset
	compiler.pkg = pkg
	compiler.initfuncs = make([]Value, 0)

	// Create a Builder, for building LLVM instructions.
	compiler.builder = llvm.GlobalContext().NewBuilder()
	defer compiler.builder.Dispose()

	// Create a TargetMachine from the OS & Arch.
	triple := fmt.Sprintf("%s-unknown-%s",
		getTripleArchName(compiler.targetArch),
		compiler.targetOs)
	var machine llvm.TargetMachine
	for target := llvm.FirstTarget(); target.C != nil && machine.C == nil; target = target.NextTarget() {
		if target.Name() == compiler.targetArch {
			machine = target.CreateTargetMachine(triple, "", "",
				llvm.CodeGenLevelDefault,
				llvm.RelocDefault,
				llvm.CodeModelDefault)
			defer machine.Dispose()
		}
	}

	if machine.C == nil {
		err = fmt.Errorf("Invalid target triple: %s", triple)
		return
	}

	// Create a Module, which contains the LLVM bitcode. Dispose it on panic,
	// otherwise we'll set a finalizer at the end. The caller may invoke
	// Dispose manually, which will render the finalizer a no-op.
	modulename := pkg.Name
	compiler.target = machine.TargetData()
	compiler.module = &Module{llvm.NewModule(modulename), modulename, false}
	compiler.module.SetTarget(triple)
	compiler.module.SetDataLayout(compiler.target.String())
	defer func() {
		if e := recover(); e != nil {
			compiler.module.Dispose()
			panic(e)
			//err = e.(error)
		}
	}()
	compiler.types = NewTypeMap(compiler.module.Module, compiler.target, exprTypes)

	// Create a mapping from objects back to packages, so we can create the
	// appropriate symbol names.
	compiler.pkgmap = createPackageMap(pkg)

	// Compile each file in the package.
	for _, file := range pkg.Files {
		file.Scope.Outer = pkg.Scope
		compiler.filescope = file.Scope
		compiler.scope = file.Scope
		compiler.fixConstDecls(file)
		for _, decl := range file.Decls {
			compiler.VisitDecl(decl)
		}
	}

	// Define intrinsics for use by the runtime: malloc, free, memcpy, etc.
	compiler.defineRuntimeIntrinsics()

	// Create global constructors.
	//
	// XXX When imports are handled, we'll need to defer creating
	//     llvm.global_ctors until we create an executable. This is
	//     due to (a) imports having to be initialised before the
	//     importer, and (b) LLVM having no specified order of
	//     initialisation for ctors with the same priority.
	if len(compiler.initfuncs) > 0 {
		elttypes := []llvm.Type{
			llvm.Int32Type(),
			llvm.PointerType(
				llvm.FunctionType(llvm.VoidType(), nil, false), 0)}
		ctortype := llvm.StructType(elttypes, false)
		ctors := make([]llvm.Value, len(compiler.initfuncs))
		for i, fn := range compiler.initfuncs {
			struct_values := []llvm.Value{
				llvm.ConstInt(llvm.Int32Type(), 1, false),
				fn.LLVMValue()}
			ctors[i] = llvm.ConstStruct(struct_values, false)
		}

		global_ctors_init := llvm.ConstArray(ctortype, ctors)
		global_ctors_var := llvm.AddGlobal(
			compiler.module.Module, global_ctors_init.Type(),
			"llvm.global_ctors")
		global_ctors_var.SetInitializer(global_ctors_init)
		global_ctors_var.SetLinkage(llvm.AppendingLinkage)
	}

	// Create debug metadata.
	compiler.createMetadata()

	return compiler.module, nil
}
Exemple #3
0
func (compiler *compiler) Compile(fset *token.FileSet,
	pkg *ast.Package, importpath string,
	exprTypes map[ast.Expr]types.Type) (m *Module, err error) {
	// FIXME create a compilation state, rather than storing in 'compiler'.
	compiler.fileset = fset
	compiler.pkg = pkg
	compiler.importpath = importpath
	compiler.initfuncs = nil
	compiler.varinitfuncs = nil

	// Create a Builder, for building LLVM instructions.
	compiler.builder = llvm.GlobalContext().NewBuilder()
	defer compiler.builder.Dispose()

	// Create a TargetMachine from the OS & Arch.
	triple := compiler.GetTargetTriple()
	var machine llvm.TargetMachine
	for target := llvm.FirstTarget(); target.C != nil && machine.C == nil; target = target.NextTarget() {
		if target.Name() == compiler.targetArch {
			machine = target.CreateTargetMachine(triple, "", "",
				llvm.CodeGenLevelDefault,
				llvm.RelocDefault,
				llvm.CodeModelDefault)
			defer machine.Dispose()
		}
	}

	if machine.C == nil {
		err = fmt.Errorf("Invalid target triple: %s", triple)
		return
	}

	// Create a Module, which contains the LLVM bitcode. Dispose it on panic,
	// otherwise we'll set a finalizer at the end. The caller may invoke
	// Dispose manually, which will render the finalizer a no-op.
	modulename := pkg.Name
	compiler.target = machine.TargetData()
	compiler.module = &Module{llvm.NewModule(modulename), modulename, false}
	compiler.module.SetTarget(triple)
	compiler.module.SetDataLayout(compiler.target.String())
	defer func() {
		if e := recover(); e != nil {
			compiler.module.Dispose()
			panic(e)
			//err = e.(error)
		}
	}()

	// Create a mapping from objects back to packages, so we can create the
	// appropriate symbol names.
	compiler.pkgmap = createPackageMap(pkg, importpath)

	// Create a struct responsible for mapping static types to LLVM types,
	// and to runtime/dynamic type values.
	var resolver Resolver = compiler
	llvmtypemap := NewLLVMTypeMap(compiler.module.Module, compiler.target)
	compiler.FunctionCache = NewFunctionCache(compiler)
	compiler.types = NewTypeMap(llvmtypemap, importpath, exprTypes, compiler.FunctionCache, compiler.pkgmap, resolver)

	// Compile each file in the package.
	for _, file := range pkg.Files {
		file.Scope.Outer = pkg.Scope
		compiler.filescope = file.Scope
		compiler.scope = file.Scope
		compiler.fixConstDecls(file)
		for _, decl := range file.Decls {
			compiler.VisitDecl(decl)
		}
	}

	// Define intrinsics for use by the runtime: malloc, free, memcpy, etc.
	// These could be defined in LLVM IR, and may be moved there later.
	if pkg.Name == "runtime" {
		compiler.defineRuntimeIntrinsics()
	}

	// Export runtime type information.
	if pkg.Name == "runtime" {
		compiler.exportBuiltinRuntimeTypes()
	}

	// Create global constructors.
	//
	// XXX When imports are handled, we'll need to defer creating
	//     llvm.global_ctors until we create an executable. This is
	//     due to (a) imports having to be initialised before the
	//     importer, and (b) LLVM having no specified order of
	//     initialisation for ctors with the same priority.
	var initfuncs [][]Value
	if compiler.varinitfuncs != nil {
		initfuncs = append(initfuncs, compiler.varinitfuncs)
	}
	if compiler.initfuncs != nil {
		initfuncs = append(initfuncs, compiler.initfuncs)
	}
	if initfuncs != nil {
		elttypes := []llvm.Type{llvm.Int32Type(), llvm.PointerType(llvm.FunctionType(llvm.VoidType(), nil, false), 0)}
		ctortype := llvm.StructType(elttypes, false)
		var ctors []llvm.Value
		var priority uint64
		for _, initfuncs := range initfuncs {
			for _, fn := range initfuncs {
				priorityval := llvm.ConstInt(llvm.Int32Type(), uint64(priority), false)
				struct_values := []llvm.Value{priorityval, fn.LLVMValue()}
				ctors = append(ctors, llvm.ConstStruct(struct_values, false))
				priority++
			}
		}
		global_ctors_init := llvm.ConstArray(ctortype, ctors)
		global_ctors_var := llvm.AddGlobal(compiler.module.Module, global_ctors_init.Type(), "llvm.global_ctors")
		global_ctors_var.SetInitializer(global_ctors_init)
		global_ctors_var.SetLinkage(llvm.AppendingLinkage)
	}

	// Create debug metadata.
	//compiler.createMetadata()

	return compiler.module, nil
}