blob: bc7cd52124b702b1c0c9308d901eb31038b6d706 [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
Vinh Tran056effb2023-06-27 14:03:25 +000037// This flag needs to be in both CFlags and LdFlags to ensure correct symbol ordering
38const afdoFlagsFormat = "-fprofile-sample-use=%s"
Yi Kongeb8efc92021-12-09 18:06:29 +080039
Yi Kong46c6e592022-01-20 22:55:00 +080040func recordMissingAfdoProfileFile(ctx android.BaseModuleContext, missing string) {
Yi Kongeb8efc92021-12-09 18:06:29 +080041 getNamedMapForConfig(ctx.Config(), modulesMissingProfileFileKey).Store(missing, true)
42}
43
Vinh Tran44cb78c2023-03-09 22:07:19 -050044type afdoRdep struct {
45 VariationName *string
46 ProfilePath *string
47}
48
Yi Kongeb8efc92021-12-09 18:06:29 +080049type AfdoProperties struct {
Alix40216ae2022-04-07 20:47:01 +000050 // Afdo allows developers self-service enroll for
51 // automatic feedback-directed optimization using profile data.
Yi Kongeb8efc92021-12-09 18:06:29 +080052 Afdo bool
53
Vinh Tran44cb78c2023-03-09 22:07:19 -050054 FdoProfilePath *string `blueprint:"mutated"`
55
56 AfdoRDeps []afdoRdep `blueprint:"mutated"`
Yi Kongeb8efc92021-12-09 18:06:29 +080057}
58
59type afdo struct {
60 Properties AfdoProperties
61}
62
63func (afdo *afdo) props() []interface{} {
64 return []interface{}{&afdo.Properties}
65}
66
Vinh Tran44cb78c2023-03-09 22:07:19 -050067// afdoEnabled returns true for binaries and shared libraries
68// that set afdo prop to True and there is a profile available
69func (afdo *afdo) afdoEnabled() bool {
Yabin Cui01c44562023-04-20 14:07:29 -070070 return afdo != nil && afdo.Properties.Afdo
Yi Kongeb8efc92021-12-09 18:06:29 +080071}
72
Yi Kongeb8efc92021-12-09 18:06:29 +080073func (afdo *afdo) flags(ctx ModuleContext, flags Flags) Flags {
Yabin Cui01c44562023-04-20 14:07:29 -070074 if afdo.Properties.Afdo {
75 // We use `-funique-internal-linkage-names` to associate profiles to the right internal
76 // functions. This option should be used before generating a profile. Because a profile
77 // generated for a binary without unique names doesn't work well building a binary with
78 // unique names (they have different internal function names).
79 // To avoid a chicken-and-egg problem, we enable `-funique-internal-linkage-names` when
80 // `afdo=true`, whether a profile exists or not.
81 // The profile can take effect in three steps:
82 // 1. Add `afdo: true` in Android.bp, and build the binary.
83 // 2. Collect an AutoFDO profile for the binary.
84 // 3. Make the profile searchable by the build system. So it's used the next time the binary
85 // is built.
86 flags.Local.CFlags = append([]string{"-funique-internal-linkage-names"}, flags.Local.CFlags...)
87 }
Vinh Tran44cb78c2023-03-09 22:07:19 -050088 if path := afdo.Properties.FdoProfilePath; path != nil {
Yi Konga1961e72023-04-05 11:33:11 +090089 // The flags are prepended to allow overriding.
Vinh Tran056effb2023-06-27 14:03:25 +000090 profileUseFlag := fmt.Sprintf(afdoFlagsFormat, *path)
Yi Konga1961e72023-04-05 11:33:11 +090091 flags.Local.CFlags = append([]string{profileUseFlag}, flags.Local.CFlags...)
92 flags.Local.LdFlags = append([]string{profileUseFlag, "-Wl,-mllvm,-no-warn-sample-unused=true"}, flags.Local.LdFlags...)
Yi Kongeb8efc92021-12-09 18:06:29 +080093
Vinh Tran44cb78c2023-03-09 22:07:19 -050094 // Update CFlagsDeps and LdFlagsDeps so the module is rebuilt
95 // if profileFile gets updated
96 pathForSrc := android.PathForSource(ctx, *path)
97 flags.CFlagsDeps = append(flags.CFlagsDeps, pathForSrc)
98 flags.LdFlagsDeps = append(flags.LdFlagsDeps, pathForSrc)
Yi Kongeb8efc92021-12-09 18:06:29 +080099 }
100
101 return flags
102}
103
Vinh Tran44cb78c2023-03-09 22:07:19 -0500104func (afdo *afdo) addDep(ctx BaseModuleContext, actx android.BottomUpMutatorContext) {
105 if ctx.Host() {
106 return
107 }
108
109 if ctx.static() && !ctx.staticBinary() {
110 return
111 }
112
113 if c, ok := ctx.Module().(*Module); ok && c.Enabled() {
114 if fdoProfileName, err := actx.DeviceConfig().AfdoProfile(actx.ModuleName()); fdoProfileName != nil && err == nil {
115 actx.AddFarVariationDependencies(
116 []blueprint.Variation{
117 {Mutator: "arch", Variation: actx.Target().ArchVariation()},
118 {Mutator: "os", Variation: "android"},
119 },
120 FdoProfileTag,
121 []string{*fdoProfileName}...,
122 )
123 }
124 }
125}
126
127// FdoProfileMutator reads the FdoProfileProvider from a direct dep with FdoProfileTag
128// assigns FdoProfileInfo.Path to the FdoProfilePath mutated property
Vinh Trancde10162023-03-09 22:07:19 -0500129func (c *Module) fdoProfileMutator(ctx android.BottomUpMutatorContext) {
Vinh Tran44cb78c2023-03-09 22:07:19 -0500130 if !c.Enabled() {
131 return
132 }
133
134 ctx.VisitDirectDepsWithTag(FdoProfileTag, func(m android.Module) {
135 if ctx.OtherModuleHasProvider(m, FdoProfileProvider) {
136 info := ctx.OtherModuleProvider(m, FdoProfileProvider).(FdoProfileInfo)
137 c.afdo.Properties.FdoProfilePath = proptools.StringPtr(info.Path.String())
138 }
139 })
140}
141
142var _ FdoProfileMutatorInterface = (*Module)(nil)
143
144// Propagate afdo requirements down from binaries and shared libraries
Yi Kongeb8efc92021-12-09 18:06:29 +0800145func afdoDepsMutator(mctx android.TopDownMutatorContext) {
Vinh Tran44cb78c2023-03-09 22:07:19 -0500146 if m, ok := mctx.Module().(*Module); ok && m.afdo.afdoEnabled() {
Yabin Cui01c44562023-04-20 14:07:29 -0700147 path := m.afdo.Properties.FdoProfilePath
148 mctx.WalkDeps(func(dep android.Module, parent android.Module) bool {
149 tag := mctx.OtherModuleDependencyTag(dep)
150 libTag, isLibTag := tag.(libraryDependencyTag)
Yi Kongeb8efc92021-12-09 18:06:29 +0800151
Yabin Cui01c44562023-04-20 14:07:29 -0700152 // Do not recurse down non-static dependencies
153 if isLibTag {
154 if !libTag.static() {
155 return false
Yi Kongeb8efc92021-12-09 18:06:29 +0800156 }
Yabin Cui01c44562023-04-20 14:07:29 -0700157 } else {
158 if tag != objDepTag && tag != reuseObjTag {
159 return false
Yi Kongeb8efc92021-12-09 18:06:29 +0800160 }
Yabin Cui01c44562023-04-20 14:07:29 -0700161 }
Yi Kongeb8efc92021-12-09 18:06:29 +0800162
Yabin Cui01c44562023-04-20 14:07:29 -0700163 if dep, ok := dep.(*Module); ok {
164 dep.afdo.Properties.AfdoRDeps = append(
165 dep.afdo.Properties.AfdoRDeps,
166 afdoRdep{
167 VariationName: proptools.StringPtr(encodeTarget(m.Name())),
168 ProfilePath: path,
169 },
170 )
171 }
172
173 return true
174 })
Yi Kongeb8efc92021-12-09 18:06:29 +0800175 }
176}
177
178// Create afdo variants for modules that need them
179func afdoMutator(mctx android.BottomUpMutatorContext) {
180 if m, ok := mctx.Module().(*Module); ok && m.afdo != nil {
Yabin Cui01c44562023-04-20 14:07:29 -0700181 if !m.static() && m.afdo.Properties.Afdo {
Vinh Tran44cb78c2023-03-09 22:07:19 -0500182 mctx.SetDependencyVariation(encodeTarget(m.Name()))
183 return
Yi Kongeb8efc92021-12-09 18:06:29 +0800184 }
185
186 variationNames := []string{""}
Vinh Tran44cb78c2023-03-09 22:07:19 -0500187
188 variantNameToProfilePath := make(map[string]*string)
189
190 for _, afdoRDep := range m.afdo.Properties.AfdoRDeps {
191 variantName := *afdoRDep.VariationName
192 // An rdep can be set twice in AfdoRDeps because there can be
193 // more than one path from an afdo-enabled module to
194 // a static dep such as
195 // afdo_enabled_foo -> static_bar ----> static_baz
196 // \ ^
197 // ----------------------|
198 // We only need to create one variant per unique rdep
Yabin Cui01c44562023-04-20 14:07:29 -0700199 if _, exists := variantNameToProfilePath[variantName]; !exists {
Vinh Tran44cb78c2023-03-09 22:07:19 -0500200 variationNames = append(variationNames, variantName)
201 variantNameToProfilePath[variantName] = afdoRDep.ProfilePath
202 }
Yi Kongeb8efc92021-12-09 18:06:29 +0800203 }
Vinh Tran44cb78c2023-03-09 22:07:19 -0500204
Yi Kongeb8efc92021-12-09 18:06:29 +0800205 if len(variationNames) > 1 {
206 modules := mctx.CreateVariations(variationNames...)
207 for i, name := range variationNames {
208 if name == "" {
209 continue
210 }
211 variation := modules[i].(*Module)
212 variation.Properties.PreventInstall = true
213 variation.Properties.HideFromMake = true
Yabin Cui01c44562023-04-20 14:07:29 -0700214 variation.afdo.Properties.Afdo = true
Vinh Tran44cb78c2023-03-09 22:07:19 -0500215 variation.afdo.Properties.FdoProfilePath = variantNameToProfilePath[name]
Yi Kongeb8efc92021-12-09 18:06:29 +0800216 }
217 }
218 }
219}
220
221// Encode target name to variation name.
222func encodeTarget(target string) string {
223 if target == "" {
224 return ""
225 }
226 return "afdo-" + target
227}
228
229// Decode target name from variation name.
230func decodeTarget(variation string) string {
231 if variation == "" {
232 return ""
233 }
234 return strings.TrimPrefix(variation, "afdo-")
235}