blob: 49f69873c4c6e1da8618b82fa2d09de88f167dd4 [file] [log] [blame]
Yi Kongeb8efc92021-12-09 18:06:29 +08001// Copyright 2021 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package cc
16
17import (
18 "fmt"
19 "strings"
20
Yi Kongeb8efc92021-12-09 18:06:29 +080021 "android/soong/android"
Vinh Tran44cb78c2023-03-09 22:07:19 -050022
23 "github.com/google/blueprint"
24 "github.com/google/blueprint/proptools"
Yi Kongeb8efc92021-12-09 18:06:29 +080025)
26
Vinh Trancde10162023-03-09 22:07:19 -050027// TODO(b/267229066): Remove globalAfdoProfileProjects after implementing bp2build converter for fdo_profile
Yi Kongeb8efc92021-12-09 18:06:29 +080028var (
29 globalAfdoProfileProjects = []string{
30 "vendor/google_data/pgo_profile/sampling/",
31 "toolchain/pgo-profiles/sampling/",
32 }
33)
34
35var afdoProfileProjectsConfigKey = android.NewOnceKey("AfdoProfileProjects")
36
Yabin Cui01c44562023-04-20 14:07:29 -070037const afdoCFlagsFormat = "-fprofile-sample-accurate -fprofile-sample-use=%s"
Yi Kongeb8efc92021-12-09 18:06:29 +080038
Yi Kong46c6e592022-01-20 22:55:00 +080039func recordMissingAfdoProfileFile(ctx android.BaseModuleContext, missing string) {
Yi Kongeb8efc92021-12-09 18:06:29 +080040 getNamedMapForConfig(ctx.Config(), modulesMissingProfileFileKey).Store(missing, true)
41}
42
Vinh Tran44cb78c2023-03-09 22:07:19 -050043type afdoRdep struct {
44 VariationName *string
45 ProfilePath *string
46}
47
Yi Kongeb8efc92021-12-09 18:06:29 +080048type AfdoProperties struct {
Alix40216ae2022-04-07 20:47:01 +000049 // Afdo allows developers self-service enroll for
50 // automatic feedback-directed optimization using profile data.
Yi Kongeb8efc92021-12-09 18:06:29 +080051 Afdo bool
52
Vinh Tran44cb78c2023-03-09 22:07:19 -050053 FdoProfilePath *string `blueprint:"mutated"`
54
55 AfdoRDeps []afdoRdep `blueprint:"mutated"`
Yi Kongeb8efc92021-12-09 18:06:29 +080056}
57
58type afdo struct {
59 Properties AfdoProperties
60}
61
62func (afdo *afdo) props() []interface{} {
63 return []interface{}{&afdo.Properties}
64}
65
Vinh Tran44cb78c2023-03-09 22:07:19 -050066// afdoEnabled returns true for binaries and shared libraries
67// that set afdo prop to True and there is a profile available
68func (afdo *afdo) afdoEnabled() bool {
Yabin Cui01c44562023-04-20 14:07:29 -070069 return afdo != nil && afdo.Properties.Afdo
Yi Kongeb8efc92021-12-09 18:06:29 +080070}
71
Yi Kongeb8efc92021-12-09 18:06:29 +080072func (afdo *afdo) flags(ctx ModuleContext, flags Flags) Flags {
Yabin Cui01c44562023-04-20 14:07:29 -070073 if afdo.Properties.Afdo {
74 // We use `-funique-internal-linkage-names` to associate profiles to the right internal
75 // functions. This option should be used before generating a profile. Because a profile
76 // generated for a binary without unique names doesn't work well building a binary with
77 // unique names (they have different internal function names).
78 // To avoid a chicken-and-egg problem, we enable `-funique-internal-linkage-names` when
79 // `afdo=true`, whether a profile exists or not.
80 // The profile can take effect in three steps:
81 // 1. Add `afdo: true` in Android.bp, and build the binary.
82 // 2. Collect an AutoFDO profile for the binary.
83 // 3. Make the profile searchable by the build system. So it's used the next time the binary
84 // is built.
85 flags.Local.CFlags = append([]string{"-funique-internal-linkage-names"}, flags.Local.CFlags...)
86 }
Vinh Tran44cb78c2023-03-09 22:07:19 -050087 if path := afdo.Properties.FdoProfilePath; path != nil {
Yi Konga1961e72023-04-05 11:33:11 +090088 // The flags are prepended to allow overriding.
Vinh Tran44cb78c2023-03-09 22:07:19 -050089 profileUseFlag := fmt.Sprintf(afdoCFlagsFormat, *path)
Yi Konga1961e72023-04-05 11:33:11 +090090 flags.Local.CFlags = append([]string{profileUseFlag}, flags.Local.CFlags...)
91 flags.Local.LdFlags = append([]string{profileUseFlag, "-Wl,-mllvm,-no-warn-sample-unused=true"}, flags.Local.LdFlags...)
Yi Kongeb8efc92021-12-09 18:06:29 +080092
Vinh Tran44cb78c2023-03-09 22:07:19 -050093 // Update CFlagsDeps and LdFlagsDeps so the module is rebuilt
94 // if profileFile gets updated
95 pathForSrc := android.PathForSource(ctx, *path)
96 flags.CFlagsDeps = append(flags.CFlagsDeps, pathForSrc)
97 flags.LdFlagsDeps = append(flags.LdFlagsDeps, pathForSrc)
Yi Kongeb8efc92021-12-09 18:06:29 +080098 }
99
100 return flags
101}
102
Vinh Tran44cb78c2023-03-09 22:07:19 -0500103func (afdo *afdo) addDep(ctx BaseModuleContext, actx android.BottomUpMutatorContext) {
104 if ctx.Host() {
105 return
106 }
107
108 if ctx.static() && !ctx.staticBinary() {
109 return
110 }
111
112 if c, ok := ctx.Module().(*Module); ok && c.Enabled() {
113 if fdoProfileName, err := actx.DeviceConfig().AfdoProfile(actx.ModuleName()); fdoProfileName != nil && err == nil {
114 actx.AddFarVariationDependencies(
115 []blueprint.Variation{
116 {Mutator: "arch", Variation: actx.Target().ArchVariation()},
117 {Mutator: "os", Variation: "android"},
118 },
119 FdoProfileTag,
120 []string{*fdoProfileName}...,
121 )
122 }
123 }
124}
125
126// FdoProfileMutator reads the FdoProfileProvider from a direct dep with FdoProfileTag
127// assigns FdoProfileInfo.Path to the FdoProfilePath mutated property
Vinh Trancde10162023-03-09 22:07:19 -0500128func (c *Module) fdoProfileMutator(ctx android.BottomUpMutatorContext) {
Vinh Tran44cb78c2023-03-09 22:07:19 -0500129 if !c.Enabled() {
130 return
131 }
132
133 ctx.VisitDirectDepsWithTag(FdoProfileTag, func(m android.Module) {
134 if ctx.OtherModuleHasProvider(m, FdoProfileProvider) {
135 info := ctx.OtherModuleProvider(m, FdoProfileProvider).(FdoProfileInfo)
136 c.afdo.Properties.FdoProfilePath = proptools.StringPtr(info.Path.String())
137 }
138 })
139}
140
141var _ FdoProfileMutatorInterface = (*Module)(nil)
142
143// Propagate afdo requirements down from binaries and shared libraries
Yi Kongeb8efc92021-12-09 18:06:29 +0800144func afdoDepsMutator(mctx android.TopDownMutatorContext) {
Vinh Tran44cb78c2023-03-09 22:07:19 -0500145 if m, ok := mctx.Module().(*Module); ok && m.afdo.afdoEnabled() {
Yabin Cui01c44562023-04-20 14:07:29 -0700146 path := m.afdo.Properties.FdoProfilePath
147 mctx.WalkDeps(func(dep android.Module, parent android.Module) bool {
148 tag := mctx.OtherModuleDependencyTag(dep)
149 libTag, isLibTag := tag.(libraryDependencyTag)
Yi Kongeb8efc92021-12-09 18:06:29 +0800150
Yabin Cui01c44562023-04-20 14:07:29 -0700151 // Do not recurse down non-static dependencies
152 if isLibTag {
153 if !libTag.static() {
154 return false
Yi Kongeb8efc92021-12-09 18:06:29 +0800155 }
Yabin Cui01c44562023-04-20 14:07:29 -0700156 } else {
157 if tag != objDepTag && tag != reuseObjTag {
158 return false
Yi Kongeb8efc92021-12-09 18:06:29 +0800159 }
Yabin Cui01c44562023-04-20 14:07:29 -0700160 }
Yi Kongeb8efc92021-12-09 18:06:29 +0800161
Yabin Cui01c44562023-04-20 14:07:29 -0700162 if dep, ok := dep.(*Module); ok {
163 dep.afdo.Properties.AfdoRDeps = append(
164 dep.afdo.Properties.AfdoRDeps,
165 afdoRdep{
166 VariationName: proptools.StringPtr(encodeTarget(m.Name())),
167 ProfilePath: path,
168 },
169 )
170 }
171
172 return true
173 })
Yi Kongeb8efc92021-12-09 18:06:29 +0800174 }
175}
176
177// Create afdo variants for modules that need them
178func afdoMutator(mctx android.BottomUpMutatorContext) {
179 if m, ok := mctx.Module().(*Module); ok && m.afdo != nil {
Yabin Cui01c44562023-04-20 14:07:29 -0700180 if !m.static() && m.afdo.Properties.Afdo {
Vinh Tran44cb78c2023-03-09 22:07:19 -0500181 mctx.SetDependencyVariation(encodeTarget(m.Name()))
182 return
Yi Kongeb8efc92021-12-09 18:06:29 +0800183 }
184
185 variationNames := []string{""}
Vinh Tran44cb78c2023-03-09 22:07:19 -0500186
187 variantNameToProfilePath := make(map[string]*string)
188
189 for _, afdoRDep := range m.afdo.Properties.AfdoRDeps {
190 variantName := *afdoRDep.VariationName
191 // An rdep can be set twice in AfdoRDeps because there can be
192 // more than one path from an afdo-enabled module to
193 // a static dep such as
194 // afdo_enabled_foo -> static_bar ----> static_baz
195 // \ ^
196 // ----------------------|
197 // We only need to create one variant per unique rdep
Yabin Cui01c44562023-04-20 14:07:29 -0700198 if _, exists := variantNameToProfilePath[variantName]; !exists {
Vinh Tran44cb78c2023-03-09 22:07:19 -0500199 variationNames = append(variationNames, variantName)
200 variantNameToProfilePath[variantName] = afdoRDep.ProfilePath
201 }
Yi Kongeb8efc92021-12-09 18:06:29 +0800202 }
Vinh Tran44cb78c2023-03-09 22:07:19 -0500203
Yi Kongeb8efc92021-12-09 18:06:29 +0800204 if len(variationNames) > 1 {
205 modules := mctx.CreateVariations(variationNames...)
206 for i, name := range variationNames {
207 if name == "" {
208 continue
209 }
210 variation := modules[i].(*Module)
211 variation.Properties.PreventInstall = true
212 variation.Properties.HideFromMake = true
Yabin Cui01c44562023-04-20 14:07:29 -0700213 variation.afdo.Properties.Afdo = true
Vinh Tran44cb78c2023-03-09 22:07:19 -0500214 variation.afdo.Properties.FdoProfilePath = variantNameToProfilePath[name]
Yi Kongeb8efc92021-12-09 18:06:29 +0800215 }
216 }
217 }
218}
219
220// Encode target name to variation name.
221func encodeTarget(target string) string {
222 if target == "" {
223 return ""
224 }
225 return "afdo-" + target
226}
227
228// Decode target name from variation name.
229func decodeTarget(variation string) string {
230 if variation == "" {
231 return ""
232 }
233 return strings.TrimPrefix(variation, "afdo-")
234}