func (in *interp) makeCompilerOptions() error { prefix, err := getInstPrefix() if err != nil { return err } importPaths := []string{filepath.Join(prefix, "lib", "go", "llgo-"+llvmVersion())} in.copts = irgen.CompilerOptions{ TargetTriple: llvm.DefaultTargetTriple(), ImportPaths: importPaths, GenerateDebug: true, Packages: in.pkgmap, } err = in.copts.MakeImporter() if err != nil { return err } origImporter := in.copts.Importer in.copts.Importer = func(pkgmap map[string]*types.Package, pkgpath string) (*types.Package, error) { if pkg, ok := pkgmap[pkgpath]; ok && pkg.Complete() { return pkg, nil } return origImporter(pkgmap, pkgpath) } return nil }
func (v *Codegen) Generate(input []*parser.Module) { v.builders = make(map[*parser.Function]llvm.Builder) v.inBlocks = make(map[*parser.Function][]*parser.Block) v.globalBuilder = llvm.NewBuilder() defer v.globalBuilder.Dispose() v.curLoopExits = make(map[*parser.Function][]llvm.BasicBlock) v.curLoopNexts = make(map[*parser.Function][]llvm.BasicBlock) v.input = make([]*WrappedModule, len(input)) for idx, mod := range input { v.input[idx] = &WrappedModule{Module: mod} } v.variableLookup = make(map[*parser.Variable]llvm.Value) v.namedTypeLookup = make(map[string]llvm.Type) // initialize llvm target llvm.InitializeNativeTarget() llvm.InitializeNativeAsmPrinter() // setup target stuff var err error v.target, err = llvm.GetTargetFromTriple(llvm.DefaultTargetTriple()) if err != nil { panic(err) } v.targetMachine = v.target.CreateTargetMachine(llvm.DefaultTargetTriple(), "", "", llvm.CodeGenLevelNone, llvm.RelocDefault, llvm.CodeModelDefault) v.targetData = v.targetMachine.TargetData() passManager := llvm.NewPassManager() passBuilder := llvm.NewPassManagerBuilder() if v.OptLevel > 0 { passBuilder.SetOptLevel(v.OptLevel) passBuilder.Populate(passManager) } v.blockDeferData = make(map[*parser.Block][]*deferData) for _, infile := range v.input { log.Timed("codegenning", infile.Name.String(), func() { infile.LlvmModule = llvm.NewModule(infile.Name.String()) v.curFile = infile for _, submod := range infile.Parts { v.declareDecls(submod.Nodes) for _, node := range submod.Nodes { v.genNode(node) } } if err := llvm.VerifyModule(infile.LlvmModule, llvm.ReturnStatusAction); err != nil { infile.LlvmModule.Dump() v.err("%s", err.Error()) } passManager.Run(infile.LlvmModule) if log.AtLevel(log.LevelDebug) { infile.LlvmModule.Dump() } }) } passManager.Dispose() log.Timed("creating binary", "", func() { v.createBinary() }) }
func (v *Codegen) Generate(input []*parser.Module, modules map[string]*parser.Module) { v.input = input v.builder = llvm.NewBuilder() v.variableLookup = make(map[*parser.Variable]llvm.Value) v.structLookup_UseHelperFunction = make(map[*parser.StructType]llvm.Type) v.enumLookup_UseHelperFunction = make(map[*parser.EnumType]llvm.Type) // initialize llvm target llvm.InitializeNativeTarget() // setup target stuff var err error v.target, err = llvm.GetTargetFromTriple(llvm.DefaultTargetTriple()) if err != nil { panic(err) } v.targetMachine = v.target.CreateTargetMachine(llvm.DefaultTargetTriple(), "", "", llvm.CodeGenLevelNone, llvm.RelocDefault, llvm.CodeModelDefault) v.targetData = v.targetMachine.TargetData() passManager := llvm.NewPassManager() passBuilder := llvm.NewPassManagerBuilder() if v.OptLevel > 0 { passBuilder.SetOptLevel(v.OptLevel) passBuilder.Populate(passManager) } v.modules = make(map[string]*parser.Module) v.blockDeferData = make(map[*parser.Block][]*deferData) for _, infile := range input { log.Verboseln("codegen", util.TEXT_BOLD+util.TEXT_GREEN+"Started codegenning "+util.TEXT_RESET+infile.Name) t := time.Now() infile.Module = llvm.NewModule(infile.Name) v.curFile = infile v.modules[v.curFile.Name] = v.curFile v.declareDecls(infile.Nodes) for _, node := range infile.Nodes { v.genNode(node) } if err := llvm.VerifyModule(infile.Module, llvm.ReturnStatusAction); err != nil { infile.Module.Dump() v.err("%s", err.Error()) } passManager.Run(infile.Module) if log.AtLevel(log.LevelVerbose) { infile.Module.Dump() } dur := time.Since(t) log.Verbose("codegen", util.TEXT_BOLD+util.TEXT_GREEN+"Finished codegenning "+util.TEXT_RESET+infile.Name+" (%.2fms)\n", float32(dur.Nanoseconds())/1000000) } passManager.Dispose() log.Timed("create binary", func() { v.createBinary() }) }
func parseArguments(args []string) (opts driverOptions, err error) { var goInputs, otherInputs []string hasOtherNonFlagInputs := false noPrefix := false actionKind := actionLink opts.triple = llvm.DefaultTargetTriple() for len(args) > 0 { consumedArgs := 1 switch { case !strings.HasPrefix(args[0], "-"): if strings.HasSuffix(args[0], ".go") { goInputs = append(goInputs, args[0]) } else { hasOtherNonFlagInputs = true otherInputs = append(otherInputs, args[0]) } case strings.HasPrefix(args[0], "-Wl,"), strings.HasPrefix(args[0], "-l"), strings.HasPrefix(args[0], "--sysroot="): // TODO(pcc): Handle these correctly. otherInputs = append(otherInputs, args[0]) case args[0] == "-B": if len(args) == 1 { return opts, errors.New("missing argument after '-B'") } opts.bprefix = args[1] consumedArgs = 2 case args[0] == "-D": if len(args) == 1 { return opts, errors.New("missing argument after '-D'") } otherInputs = append(otherInputs, args[0], args[1]) consumedArgs = 2 case strings.HasPrefix(args[0], "-D"): otherInputs = append(otherInputs, args[0]) case args[0] == "-I": if len(args) == 1 { return opts, errors.New("missing argument after '-I'") } opts.importPaths = append(opts.importPaths, args[1]) consumedArgs = 2 case strings.HasPrefix(args[0], "-I"): opts.importPaths = append(opts.importPaths, args[0][2:]) case args[0] == "-isystem": if len(args) == 1 { return opts, errors.New("missing argument after '-isystem'") } otherInputs = append(otherInputs, args[0], args[1]) consumedArgs = 2 case args[0] == "-L": if len(args) == 1 { return opts, errors.New("missing argument after '-L'") } opts.libPaths = append(opts.libPaths, args[1]) consumedArgs = 2 case strings.HasPrefix(args[0], "-L"): opts.libPaths = append(opts.libPaths, args[0][2:]) case args[0] == "-O0": opts.optLevel = 0 case args[0] == "-O1", args[0] == "-O": opts.optLevel = 1 case args[0] == "-O2": opts.optLevel = 2 case args[0] == "-Os": opts.optLevel = 2 opts.sizeLevel = 1 case args[0] == "-O3": opts.optLevel = 3 case args[0] == "-S": actionKind = actionAssemble case args[0] == "-c": actionKind = actionCompile case strings.HasPrefix(args[0], "-fcompilerrt-prefix="): opts.sanitizer.crtPrefix = args[0][20:] case strings.HasPrefix(args[0], "-fdebug-prefix-map="): split := strings.SplitN(args[0][19:], "=", 2) if len(split) < 2 { return opts, fmt.Errorf("argument '%s' must be of form '-fdebug-prefix-map=SOURCE=REPLACEMENT'", args[0]) } opts.debugPrefixMaps = append(opts.debugPrefixMaps, debug.PrefixMap{split[0], split[1]}) case args[0] == "-fdump-ssa": opts.dumpSSA = true case args[0] == "-fdump-trace": opts.dumpTrace = true case strings.HasPrefix(args[0], "-fgccgo-path="): opts.gccgoPath = args[0][13:] case strings.HasPrefix(args[0], "-fgo-pkgpath="): opts.pkgpath = args[0][13:] case strings.HasPrefix(args[0], "-fgo-relative-import-path="): // TODO(pcc): Handle this. case strings.HasPrefix(args[0], "-fstack-protector"): // TODO(axw) set ssp function attributes. This can be useful // even for Go, if it interfaces with code written in a non- // memory safe language (e.g. via cgo). case strings.HasPrefix(args[0], "-W"): // Go doesn't do warnings. Ignore. case args[0] == "-fload-plugin": if len(args) == 1 { return opts, errors.New("missing argument after '-fload-plugin'") } opts.plugins = append(opts.plugins, args[1]) consumedArgs = 2 case args[0] == "-fno-toplevel-reorder": // This is a GCC-specific code generation option. Ignore. case args[0] == "-emit-llvm": opts.emitIR = true case args[0] == "-flto": opts.lto = true case args[0] == "-fPIC": opts.pic = true case strings.HasPrefix(args[0], "-fsanitize-blacklist="): opts.sanitizer.blacklist = args[0][21:] // TODO(pcc): Enforce mutual exclusion between sanitizers. case args[0] == "-fsanitize=address": opts.sanitizer.address = true case args[0] == "-fsanitize=thread": opts.sanitizer.thread = true case args[0] == "-fsanitize=memory": opts.sanitizer.memory = true case args[0] == "-fsanitize=dataflow": opts.sanitizer.dataflow = true case args[0] == "-g": opts.generateDebug = true case args[0] == "-mllvm": if len(args) == 1 { return opts, errors.New("missing argument after '-mllvm'") } opts.llvmArgs = append(opts.llvmArgs, args[1]) consumedArgs = 2 case strings.HasPrefix(args[0], "-m"), args[0] == "-funsafe-math-optimizations", args[0] == "-ffp-contract=off": // TODO(pcc): Handle code generation options. case args[0] == "-no-prefix": noPrefix = true case args[0] == "-o": if len(args) == 1 { return opts, errors.New("missing argument after '-o'") } opts.output = args[1] consumedArgs = 2 case args[0] == "-pie": opts.pieLink = true case args[0] == "-dumpversion", args[0] == "-print-libgcc-file-name", args[0] == "-print-multi-os-directory", args[0] == "--version": actionKind = actionPrint opts.output = args[0] case args[0] == "-static": opts.staticLink = true case args[0] == "-static-libgcc": opts.staticLibgcc = true case args[0] == "-static-libgo": opts.staticLibgo = true default: return opts, fmt.Errorf("unrecognized command line option '%s'", args[0]) } args = args[consumedArgs:] } if actionKind != actionPrint && len(goInputs) == 0 && !hasOtherNonFlagInputs { return opts, errors.New("no input files") } if !noPrefix { opts.prefix, err = getInstPrefix() if err != nil { return opts, err } } if opts.sanitizer.crtPrefix == "" { opts.sanitizer.crtPrefix = opts.prefix } if opts.sanitizer.isPIEDefault() { // This should really only be turning on -fPIE, but this isn't // easy to do from Go, and -fPIC is a superset of it anyway. opts.pic = true opts.pieLink = true } switch actionKind { case actionLink: if len(goInputs) != 0 { opts.actions = []action{action{actionCompile, goInputs}} } opts.actions = append(opts.actions, action{actionLink, otherInputs}) case actionCompile, actionAssemble: if len(goInputs) != 0 { opts.actions = []action{action{actionKind, goInputs}} } case actionPrint: opts.actions = []action{action{actionKind, nil}} } if opts.output == "" && len(opts.actions) != 0 { switch actionKind { case actionCompile, actionAssemble: base := filepath.Base(goInputs[0]) base = base[0 : len(base)-3] if actionKind == actionCompile { opts.output = base + ".o" } else { opts.output = base + ".s" } case actionLink: opts.output = "a.out" } } return opts, nil }