// 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
}

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)
	}
}

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 {
	if lto.LTO() {
		var ltoFlag string
		if Bool(lto.Properties.Lto.Thin) {
			ltoFlag = "-flto=thin -fsplit-lto-unit"
		} else {
			ltoFlag = "-flto"
		}

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

		if ctx.Config().IsEnvTrue("USE_THINLTO_CACHE") && Bool(lto.Properties.Lto.Thin) && lto.useClangLld(ctx) {
			// Set appropriate ThinLTO cache policy
			cacheDirFormat := "-Wl,--thinlto-cache-dir="
			cacheDir := android.PathForOutput(ctx, "thinlto-cache").String()
			flags.LdFlags = append(flags.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.LdFlags = append(flags.LdFlags, cachePolicyFormat+policy)
		}

		// If the module does not have a profile, be conservative and do not inline
		// or unroll loops during LTO, in order to prevent significant size bloat.
		if !ctx.isPgoCompile() {
			flags.LdFlags = append(flags.LdFlags, "-Wl,-plugin-opt,-inline-threshold=0")
			flags.LdFlags = append(flags.LdFlags, "-Wl,-plugin-opt,-unroll-threshold=0")
		}
	}
	return flags
}

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

	full := Bool(lto.Properties.Lto.Full)
	thin := Bool(lto.Properties.Lto.Thin)
	return full || thin
}

// Is lto.never explicitly set to true?
func (lto *lto) Disabled() bool {
	return lto.Properties.Lto.Never != nil && *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 := Bool(m.lto.Properties.Lto.Full)
		thin := Bool(m.lto.Properties.Lto.Thin)
		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)
			switch tag {
			case staticDepTag, staticExportDepTag, lateStaticDepTag, wholeStaticDepTag, objDepTag, reuseObjTag:
				if dep, ok := dep.(*Module); ok && dep.lto != nil &&
					!dep.lto.Disabled() {
					if full && !Bool(dep.lto.Properties.Lto.Full) {
						dep.lto.Properties.FullDep = true
					}
					if thin && !Bool(dep.lto.Properties.Lto.Thin) {
						dep.lto.Properties.ThinDep = true
					}
				}

				// Recursively walk static dependencies
				return true
			}

			// Do not recurse down non-static dependencies
			return false
		})
	}
}

// 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 && !Bool(m.lto.Properties.Lto.Full) {
			variationNames = append(variationNames, "lto-full")
		}
		if m.lto.Properties.ThinDep && !Bool(m.lto.Properties.Lto.Thin) {
			variationNames = append(variationNames, "lto-thin")
		}

		// Use correct dependencies if LTO property is explicitly set
		// (mutually exclusive)
		if Bool(m.lto.Properties.Lto.Full) {
			mctx.SetDependencyVariation("lto-full")
		}
		if Bool(m.lto.Properties.Lto.Thin) {
			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
			}
		}
	}
}
