@@ -105,6 +105,15 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
105105 defer os .RemoveAll (dir )
106106 }
107107
108+ // Look up the build cache directory, which is used to speed up incremental
109+ // builds.
110+ cacheDir := goenv .Get ("GOCACHE" )
111+ if cacheDir == "off" {
112+ // Use temporary build directory instead, effectively disabling the
113+ // build cache.
114+ cacheDir = dir
115+ }
116+
108117 // Check for a libc dependency.
109118 // As a side effect, this also creates the headers for the given libc, if
110119 // the libc needs them.
@@ -238,12 +247,6 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
238247
239248 // Determine the path of the bitcode file (which is a serialized version
240249 // of a LLVM module).
241- cacheDir := goenv .Get ("GOCACHE" )
242- if cacheDir == "off" {
243- // Use temporary build directory instead, effectively disabling the
244- // build cache.
245- cacheDir = dir
246- }
247250 bitcodePath := filepath .Join (cacheDir , "pkg-" + hex .EncodeToString (hash [:])+ ".bc" )
248251 packageBitcodePaths [pkg .ImportPath ] = bitcodePath
249252
@@ -416,7 +419,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
416419 // Load and link all the bitcode files. This does not yet optimize
417420 // anything, it only links the bitcode files together.
418421 ctx := llvm .NewContext ()
419- mod = ctx .NewModule ("" )
422+ mod = ctx .NewModule ("main " )
420423 for _ , pkg := range lprogram .Sorted () {
421424 pkgMod , err := ctx .ParseBitcodeFile (packageBitcodePaths [pkg .ImportPath ])
422425 if err != nil {
@@ -512,8 +515,14 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
512515 }
513516 return ioutil .WriteFile (outpath , llvmBuf .Bytes (), 0666 )
514517 case ".bc" :
515- data := llvm .WriteBitcodeToMemoryBuffer (mod ).Bytes ()
516- return ioutil .WriteFile (outpath , data , 0666 )
518+ var buf llvm.MemoryBuffer
519+ if config .UseThinLTO () {
520+ buf = llvm .WriteThinLTOBitcodeToMemoryBuffer (mod )
521+ } else {
522+ buf = llvm .WriteBitcodeToMemoryBuffer (mod )
523+ }
524+ defer buf .Dispose ()
525+ return ioutil .WriteFile (outpath , buf .Bytes (), 0666 )
517526 case ".ll" :
518527 data := []byte (mod .String ())
519528 return ioutil .WriteFile (outpath , data , 0666 )
@@ -533,10 +542,17 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
533542 dependencies : []* compileJob {programJob },
534543 result : objfile ,
535544 run : func (* compileJob ) error {
536- llvmBuf , err := machine .EmitToMemoryBuffer (mod , llvm .ObjectFile )
537- if err != nil {
538- return err
545+ var llvmBuf llvm.MemoryBuffer
546+ if config .UseThinLTO () {
547+ llvmBuf = llvm .WriteThinLTOBitcodeToMemoryBuffer (mod )
548+ } else {
549+ var err error
550+ llvmBuf , err = machine .EmitToMemoryBuffer (mod , llvm .ObjectFile )
551+ if err != nil {
552+ return err
553+ }
539554 }
555+ defer llvmBuf .Dispose ()
540556 return ioutil .WriteFile (objfile , llvmBuf .Bytes (), 0666 )
541557 },
542558 }
@@ -569,7 +585,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
569585 job := & compileJob {
570586 description : "compile extra file " + path ,
571587 run : func (job * compileJob ) error {
572- result , err := compileAndCacheCFile (abspath , dir , config .CFlags (), config .Options .PrintCommands )
588+ result , err := compileAndCacheCFile (abspath , dir , config .CFlags (), config .UseThinLTO (), config . Options .PrintCommands )
573589 job .result = result
574590 return err
575591 },
@@ -587,7 +603,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
587603 job := & compileJob {
588604 description : "compile CGo file " + abspath ,
589605 run : func (job * compileJob ) error {
590- result , err := compileAndCacheCFile (abspath , dir , pkg .CFlags , config .Options .PrintCommands )
606+ result , err := compileAndCacheCFile (abspath , dir , pkg .CFlags , config .UseThinLTO (), config . Options .PrintCommands )
591607 job .result = result
592608 return err
593609 },
@@ -656,6 +672,24 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
656672 if config .Options .PrintCommands != nil {
657673 config .Options .PrintCommands (config .Target .Linker , ldflags ... )
658674 }
675+ if config .UseThinLTO () {
676+ ldflags = append (ldflags ,
677+ "--thinlto-cache-dir=" + filepath .Join (cacheDir , "thinlto" ),
678+ "-plugin-opt=mcpu=" + config .CPU (),
679+ "-plugin-opt=O" + strconv .Itoa (optLevel ),
680+ "-plugin-opt=thinlto" )
681+ if config .CodeModel () != "default" {
682+ ldflags = append (ldflags ,
683+ "-mllvm" , "-code-model=" + config .CodeModel ())
684+ }
685+ if sizeLevel >= 2 {
686+ // Workaround with roughly the same effect as
687+ // https://reviews.llvm.org/D119342.
688+ // Can hopefully be removed in LLVM 15.
689+ ldflags = append (ldflags ,
690+ "-mllvm" , "--rotation-max-header-size=0" )
691+ }
692+ }
659693 err = link (config .Target .Linker , ldflags ... )
660694 if err != nil {
661695 return & commandError {"failed to link" , executable , err }
@@ -846,7 +880,7 @@ func optimizeProgram(mod llvm.Module, config *compileopts.Config) error {
846880 }
847881 }
848882
849- if config .GOOS () != "darwin" {
883+ if config .GOOS () != "darwin" && ! config . UseThinLTO () {
850884 transform .ApplyFunctionSections (mod ) // -ffunction-sections
851885 }
852886
0 commit comments