// Copyright 2017 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cc

import (
	"android/soong/android"
)

// LTO (link-time optimization) allows the compiler to optimize and generate
// code for the entire module at link time, rather than per-compilation
// unit. LTO is required for Clang CFI and other whole-program optimization
// techniques. LTO also allows cross-compilation unit optimizations that should
// result in faster and smaller code, at the expense of additional compilation
// time.
//
// To properly build a module with LTO, the module and all recursive static
// dependencies should be compiled with -flto which directs the compiler to emit
// bitcode rather than native object files. These bitcode files are then passed
// by the linker to the LLVM plugin for compilation at link time. Static
// dependencies not built as bitcode will still function correctly but cannot be
// optimized at link time and may not be compatible with features that require
// LTO, such as CFI.
//
// This file adds support to soong to automatically propogate LTO options to a
// new variant of all static dependencies for each module with LTO enabled.

type LTOProperties struct {
	// Lto must violate capitialization style for acronyms so that it can be
	// referred to in blueprint files as "lto"
	Lto struct {
		Never *bool `android:"arch_variant"`
		Full  *bool `android:"arch_variant"`
		Thin  *bool `android:"arch_variant"`
	} `android:"arch_variant"`

	// Dep properties indicate that this module needs to be built with LTO
	// since it is an object dependency of an LTO module.
	FullDep bool `blueprint:"mutated"`
	ThinDep bool `blueprint:"mutated"`

	// Use clang lld instead of gnu ld.
	Use_clang_lld *bool

	// Use -fwhole-program-vtables cflag.
	Whole_program_vtables *bool
}

type lto struct {
	Properties LTOProperties
}

func (lto *lto) props() []interface{} {
	return []interface{}{&lto.Properties}
}

func (lto *lto) begin(ctx BaseModuleContext) {
	if ctx.Config().IsEnvTrue("DISABLE_LTO") {
		lto.Properties.Lto.Never = boolPtr(true)
	} else if ctx.Config().IsEnvTrue("GLOBAL_THINLTO") {
		staticLib := ctx.static() && !ctx.staticBinary()
		hostBin := ctx.Host()
		vndk := ctx.isVndk() // b/169217596
		if !staticLib && !hostBin && !vndk {
			if !lto.Never() && !lto.FullLTO() {
				lto.Properties.Lto.Thin = boolPtr(true)
			}
		}
	}
}

func (lto *lto) deps(ctx BaseModuleContext, deps Deps) Deps {
	return deps
}

func (lto *lto) useClangLld(ctx BaseModuleContext) bool {
	if lto.Properties.Use_clang_lld != nil {
		return Bool(lto.Properties.Use_clang_lld)
	}
	return true
}

func (lto *lto) flags(ctx BaseModuleContext, flags Flags) Flags {
	// TODO(b/131771163): Disable LTO when using explicit fuzzing configurations.
	// LTO breaks fuzzer builds.
	if inList("-fsanitize=fuzzer-no-link", flags.Local.CFlags) {
		return flags
	}

	if lto.LTO() {
		var ltoFlag string
		if lto.ThinLTO() {
			ltoFlag = "-flto=thin -fsplit-lto-unit"
		} else {
			ltoFlag = "-flto"
		}

		flags.Local.CFlags = append(flags.Local.CFlags, ltoFlag)
		flags.Local.LdFlags = append(flags.Local.LdFlags, ltoFlag)

		if Bool(lto.Properties.Whole_program_vtables) {
			flags.Local.CFlags = append(flags.Local.CFlags, "-fwhole-program-vtables")
		}

		if lto.ThinLTO() && ctx.Config().IsEnvTrue("USE_THINLTO_CACHE") && lto.useClangLld(ctx) {
			// Set appropriate ThinLTO cache policy
			cacheDirFormat := "-Wl,--thinlto-cache-dir="
			cacheDir := android.PathForOutput(ctx, "thinlto-cache").String()
			flags.Local.LdFlags = append(flags.Local.LdFlags, cacheDirFormat+cacheDir)

			// Limit the size of the ThinLTO cache to the lesser of 10% of available
			// disk space and 10GB.
			cachePolicyFormat := "-Wl,--thinlto-cache-policy="
			policy := "cache_size=10%:cache_size_bytes=10g"
			flags.Local.LdFlags = append(flags.Local.LdFlags, cachePolicyFormat+policy)
		}

		// If the module does not have a profile, be conservative and limit cross TU inline
		// limit to 5 LLVM IR instructions, to balance binary size increase and performance.
		if !ctx.isPgoCompile() {
			flags.Local.LdFlags = append(flags.Local.LdFlags,
				"-Wl,-plugin-opt,-import-instr-limit=5")
		}
	}
	return flags
}

// Can be called with a null receiver
func (lto *lto) LTO() bool {
	if lto == nil || lto.Never() {
		return false
	}

	return lto.FullLTO() || lto.ThinLTO()
}

func (lto *lto) FullLTO() bool {
	return Bool(lto.Properties.Lto.Full)
}

func (lto *lto) ThinLTO() bool {
	return Bool(lto.Properties.Lto.Thin)
}

// Is lto.never explicitly set to true?
func (lto *lto) Never() bool {
	return Bool(lto.Properties.Lto.Never)
}

// Propagate lto requirements down from binaries
func ltoDepsMutator(mctx android.TopDownMutatorContext) {
	if m, ok := mctx.Module().(*Module); ok && m.lto.LTO() {
		full := m.lto.FullLTO()
		thin := m.lto.ThinLTO()
		if full && thin {
			mctx.PropertyErrorf("LTO", "FullLTO and ThinLTO are mutually exclusive")
		}

		mctx.WalkDeps(func(dep android.Module, parent android.Module) bool {
			tag := mctx.OtherModuleDependencyTag(dep)
			libTag, isLibTag := tag.(libraryDependencyTag)

			// Do not recurse down non-static dependencies
			if isLibTag {
				if !libTag.static() {
					return false
				}
			} else {
				if tag != objDepTag && tag != reuseObjTag {
					return false
				}
			}

			if dep, ok := dep.(*Module); ok && dep.lto != nil &&
				!dep.lto.Never() {
				if full && !dep.lto.FullLTO() {
					dep.lto.Properties.FullDep = true
				}
				if thin && !dep.lto.ThinLTO() {
					dep.lto.Properties.ThinDep = true
				}
			}

			// Recursively walk static dependencies
			return true
		})
	}
}

// Create lto variants for modules that need them
func ltoMutator(mctx android.BottomUpMutatorContext) {
	if m, ok := mctx.Module().(*Module); ok && m.lto != nil {
		// Create variations for LTO types required as static
		// dependencies
		variationNames := []string{""}
		if m.lto.Properties.FullDep && !m.lto.FullLTO() {
			variationNames = append(variationNames, "lto-full")
		}
		if m.lto.Properties.ThinDep && !m.lto.ThinLTO() {
			variationNames = append(variationNames, "lto-thin")
		}

		// Use correct dependencies if LTO property is explicitly set
		// (mutually exclusive)
		if m.lto.FullLTO() {
			mctx.SetDependencyVariation("lto-full")
		}
		if m.lto.ThinLTO() {
			mctx.SetDependencyVariation("lto-thin")
		}

		if len(variationNames) > 1 {
			modules := mctx.CreateVariations(variationNames...)
			for i, name := range variationNames {
				variation := modules[i].(*Module)
				// Default module which will be
				// installed. Variation set above according to
				// explicit LTO properties
				if name == "" {
					continue
				}

				// LTO properties for dependencies
				if name == "lto-full" {
					variation.lto.Properties.Lto.Full = boolPtr(true)
					variation.lto.Properties.Lto.Thin = boolPtr(false)
				}
				if name == "lto-thin" {
					variation.lto.Properties.Lto.Full = boolPtr(false)
					variation.lto.Properties.Lto.Thin = boolPtr(true)
				}
				variation.Properties.PreventInstall = true
				variation.Properties.HideFromMake = true
				variation.lto.Properties.FullDep = false
				variation.lto.Properties.ThinDep = false
			}
		}
	}
}
