1// Copyright 2015 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 config
16
17import (
18	"fmt"
19	"strings"
20
21	"android/soong/android"
22)
23
24var (
25	armToolchainCflags = []string{
26		"-mthumb-interwork",
27		"-msoft-float",
28	}
29
30	armCflags = []string{
31		"-fomit-frame-pointer",
32	}
33
34	armCppflags = []string{}
35
36	armLdflags = []string{
37		"-Wl,--hash-style=gnu",
38		"-Wl,-m,armelf",
39	}
40
41	armLldflags = ClangFilterUnknownLldflags(armLdflags)
42
43	armArmCflags = []string{
44		"-fstrict-aliasing",
45	}
46
47	armThumbCflags = []string{
48		"-mthumb",
49		"-Os",
50	}
51
52	armClangArchVariantCflags = map[string][]string{
53		"armv7-a": []string{
54			"-march=armv7-a",
55			"-mfloat-abi=softfp",
56			"-mfpu=vfpv3-d16",
57		},
58		"armv7-a-neon": []string{
59			"-march=armv7-a",
60			"-mfloat-abi=softfp",
61			"-mfpu=neon",
62		},
63		"armv8-a": []string{
64			"-march=armv8-a",
65			"-mfloat-abi=softfp",
66			"-mfpu=neon-fp-armv8",
67		},
68		"armv8-2a": []string{
69			"-march=armv8.2-a",
70			"-mfloat-abi=softfp",
71			"-mfpu=neon-fp-armv8",
72		},
73	}
74
75	armClangCpuVariantCflags = map[string][]string{
76		"cortex-a7": []string{
77			"-mcpu=cortex-a7",
78			"-mfpu=neon-vfpv4",
79			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
80			// don't advertise.
81			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
82			// better solution comes around. See Bug 27340895
83			"-D__ARM_FEATURE_LPAE=1",
84		},
85		"cortex-a8": []string{
86			"-mcpu=cortex-a8",
87		},
88		"cortex-a15": []string{
89			"-mcpu=cortex-a15",
90			"-mfpu=neon-vfpv4",
91			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
92			// don't advertise.
93			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
94			// better solution comes around. See Bug 27340895
95			"-D__ARM_FEATURE_LPAE=1",
96		},
97		"cortex-a53": []string{
98			"-mcpu=cortex-a53",
99			"-mfpu=neon-fp-armv8",
100			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
101			// don't advertise.
102			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
103			// better solution comes around. See Bug 27340895
104			"-D__ARM_FEATURE_LPAE=1",
105		},
106		"cortex-a55": []string{
107			"-mcpu=cortex-a55",
108			"-mfpu=neon-fp-armv8",
109			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
110			// don't advertise.
111			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
112			// better solution comes around. See Bug 27340895
113			"-D__ARM_FEATURE_LPAE=1",
114		},
115		"cortex-a75": []string{
116			"-mcpu=cortex-a55",
117			"-mfpu=neon-fp-armv8",
118			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
119			// don't advertise.
120			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
121			// better solution comes around. See Bug 27340895
122			"-D__ARM_FEATURE_LPAE=1",
123		},
124		"cortex-a76": []string{
125			"-mcpu=cortex-a55",
126			"-mfpu=neon-fp-armv8",
127			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
128			// don't advertise.
129			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
130			// better solution comes around. See Bug 27340895
131			"-D__ARM_FEATURE_LPAE=1",
132		},
133		"krait": []string{
134			"-mcpu=krait",
135			"-mfpu=neon-vfpv4",
136			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
137			// don't advertise.
138			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
139			// better solution comes around. See Bug 27340895
140			"-D__ARM_FEATURE_LPAE=1",
141		},
142		"kryo": []string{
143			// Use cortex-a53 because the GNU assembler doesn't recognize -mcpu=kryo
144			// even though clang does.
145			"-mcpu=cortex-a53",
146			"-mfpu=neon-fp-armv8",
147			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
148			// don't advertise.
149			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
150			// better solution comes around. See Bug 27340895
151			"-D__ARM_FEATURE_LPAE=1",
152		},
153		"kryo385": []string{
154			// Use cortex-a53 because kryo385 is not supported in GCC/clang.
155			"-mcpu=cortex-a53",
156			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
157			// don't advertise.
158			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
159			// better solution comes around. See Bug 27340895
160			"-D__ARM_FEATURE_LPAE=1",
161		},
162	}
163)
164
165const (
166	armGccVersion = "4.9"
167)
168
169func init() {
170	pctx.StaticVariable("armGccVersion", armGccVersion)
171
172	pctx.SourcePathVariable("ArmGccRoot",
173		"prebuilts/gcc/${HostPrebuiltTag}/arm/arm-linux-androideabi-${armGccVersion}")
174
175	pctx.StaticVariable("ArmLdflags", strings.Join(armLdflags, " "))
176	pctx.StaticVariable("ArmLldflags", strings.Join(armLldflags, " "))
177
178	// Clang cflags
179	pctx.StaticVariable("ArmToolchainClangCflags", strings.Join(ClangFilterUnknownCflags(armToolchainCflags), " "))
180	pctx.StaticVariable("ArmClangCflags", strings.Join(ClangFilterUnknownCflags(armCflags), " "))
181	pctx.StaticVariable("ArmClangLdflags", strings.Join(ClangFilterUnknownCflags(armLdflags), " "))
182	pctx.StaticVariable("ArmClangLldflags", strings.Join(ClangFilterUnknownCflags(armLldflags), " "))
183	pctx.StaticVariable("ArmClangCppflags", strings.Join(ClangFilterUnknownCflags(armCppflags), " "))
184
185	// Clang ARM vs. Thumb instruction set cflags
186	pctx.StaticVariable("ArmClangArmCflags", strings.Join(ClangFilterUnknownCflags(armArmCflags), " "))
187	pctx.StaticVariable("ArmClangThumbCflags", strings.Join(ClangFilterUnknownCflags(armThumbCflags), " "))
188
189	// Clang arch variant cflags
190	pctx.StaticVariable("ArmClangArmv7ACflags",
191		strings.Join(armClangArchVariantCflags["armv7-a"], " "))
192	pctx.StaticVariable("ArmClangArmv7ANeonCflags",
193		strings.Join(armClangArchVariantCflags["armv7-a-neon"], " "))
194	pctx.StaticVariable("ArmClangArmv8ACflags",
195		strings.Join(armClangArchVariantCflags["armv8-a"], " "))
196	pctx.StaticVariable("ArmClangArmv82ACflags",
197		strings.Join(armClangArchVariantCflags["armv8-2a"], " "))
198
199	// Clang cpu variant cflags
200	pctx.StaticVariable("ArmClangGenericCflags",
201		strings.Join(armClangCpuVariantCflags[""], " "))
202	pctx.StaticVariable("ArmClangCortexA7Cflags",
203		strings.Join(armClangCpuVariantCflags["cortex-a7"], " "))
204	pctx.StaticVariable("ArmClangCortexA8Cflags",
205		strings.Join(armClangCpuVariantCflags["cortex-a8"], " "))
206	pctx.StaticVariable("ArmClangCortexA15Cflags",
207		strings.Join(armClangCpuVariantCflags["cortex-a15"], " "))
208	pctx.StaticVariable("ArmClangCortexA53Cflags",
209		strings.Join(armClangCpuVariantCflags["cortex-a53"], " "))
210	pctx.StaticVariable("ArmClangCortexA55Cflags",
211		strings.Join(armClangCpuVariantCflags["cortex-a55"], " "))
212	pctx.StaticVariable("ArmClangKraitCflags",
213		strings.Join(armClangCpuVariantCflags["krait"], " "))
214	pctx.StaticVariable("ArmClangKryoCflags",
215		strings.Join(armClangCpuVariantCflags["kryo"], " "))
216}
217
218var (
219	armClangArchVariantCflagsVar = map[string]string{
220		"armv7-a":      "${config.ArmClangArmv7ACflags}",
221		"armv7-a-neon": "${config.ArmClangArmv7ANeonCflags}",
222		"armv8-a":      "${config.ArmClangArmv8ACflags}",
223		"armv8-2a":     "${config.ArmClangArmv82ACflags}",
224	}
225
226	armClangCpuVariantCflagsVar = map[string]string{
227		"":               "${config.ArmClangGenericCflags}",
228		"cortex-a7":      "${config.ArmClangCortexA7Cflags}",
229		"cortex-a8":      "${config.ArmClangCortexA8Cflags}",
230		"cortex-a15":     "${config.ArmClangCortexA15Cflags}",
231		"cortex-a53":     "${config.ArmClangCortexA53Cflags}",
232		"cortex-a53.a57": "${config.ArmClangCortexA53Cflags}",
233		"cortex-a55":     "${config.ArmClangCortexA55Cflags}",
234		"cortex-a72":     "${config.ArmClangCortexA53Cflags}",
235		"cortex-a73":     "${config.ArmClangCortexA53Cflags}",
236		"cortex-a75":     "${config.ArmClangCortexA55Cflags}",
237		"cortex-a76":     "${config.ArmClangCortexA55Cflags}",
238		"krait":          "${config.ArmClangKraitCflags}",
239		"kryo":           "${config.ArmClangKryoCflags}",
240		"kryo385":        "${config.ArmClangCortexA53Cflags}",
241		"exynos-m1":      "${config.ArmClangCortexA53Cflags}",
242		"exynos-m2":      "${config.ArmClangCortexA53Cflags}",
243	}
244)
245
246type toolchainArm struct {
247	toolchain32Bit
248	ldflags              string
249	lldflags             string
250	toolchainClangCflags string
251}
252
253func (t *toolchainArm) Name() string {
254	return "arm"
255}
256
257func (t *toolchainArm) GccRoot() string {
258	return "${config.ArmGccRoot}"
259}
260
261func (t *toolchainArm) GccTriple() string {
262	return "arm-linux-androideabi"
263}
264
265func (t *toolchainArm) GccVersion() string {
266	return armGccVersion
267}
268
269func (t *toolchainArm) IncludeFlags() string {
270	return ""
271}
272
273func (t *toolchainArm) ClangTriple() string {
274	// http://b/72619014 work around llvm LTO bug.
275	return "armv7a-linux-androideabi"
276}
277
278func (t *toolchainArm) ndkTriple() string {
279	// Use current NDK include path, while ClangTriple is changed.
280	return t.GccTriple()
281}
282
283func (t *toolchainArm) ToolchainClangCflags() string {
284	return t.toolchainClangCflags
285}
286
287func (t *toolchainArm) ClangCflags() string {
288	return "${config.ArmClangCflags}"
289}
290
291func (t *toolchainArm) ClangCppflags() string {
292	return "${config.ArmClangCppflags}"
293}
294
295func (t *toolchainArm) ClangLdflags() string {
296	return t.ldflags
297}
298
299func (t *toolchainArm) ClangLldflags() string {
300	return t.lldflags // TODO: handle V8 cases
301}
302
303func (t *toolchainArm) ClangInstructionSetFlags(isa string) (string, error) {
304	switch isa {
305	case "arm":
306		return "${config.ArmClangArmCflags}", nil
307	case "thumb", "":
308		return "${config.ArmClangThumbCflags}", nil
309	default:
310		return t.toolchainBase.ClangInstructionSetFlags(isa)
311	}
312}
313
314func (toolchainArm) LibclangRuntimeLibraryArch() string {
315	return "arm"
316}
317
318func armToolchainFactory(arch android.Arch) Toolchain {
319	var fixCortexA8 string
320	toolchainClangCflags := make([]string, 2, 3)
321
322	toolchainClangCflags[0] = "${config.ArmToolchainClangCflags}"
323	toolchainClangCflags[1] = armClangArchVariantCflagsVar[arch.ArchVariant]
324
325	toolchainClangCflags = append(toolchainClangCflags,
326		variantOrDefault(armClangCpuVariantCflagsVar, arch.CpuVariant))
327
328	switch arch.ArchVariant {
329	case "armv7-a-neon":
330		switch arch.CpuVariant {
331		case "cortex-a8", "":
332			// Generic ARM might be a Cortex A8 -- better safe than sorry
333			fixCortexA8 = "-Wl,--fix-cortex-a8"
334		default:
335			fixCortexA8 = "-Wl,--no-fix-cortex-a8"
336		}
337	case "armv7-a":
338		fixCortexA8 = "-Wl,--fix-cortex-a8"
339	case "armv8-a", "armv8-2a":
340		// Nothing extra for armv8-a/armv8-2a
341	default:
342		panic(fmt.Sprintf("Unknown ARM architecture version: %q", arch.ArchVariant))
343	}
344
345	return &toolchainArm{
346		ldflags: strings.Join([]string{
347			"${config.ArmLdflags}",
348			fixCortexA8,
349		}, " "),
350		lldflags:             "${config.ArmLldflags}",
351		toolchainClangCflags: strings.Join(toolchainClangCflags, " "),
352	}
353}
354
355func init() {
356	registerToolchainFactory(android.Android, android.Arm, armToolchainFactory)
357}
358