Skip to content

Commit 917dd90

Browse files
Add cpu-target-features binary
This is a very small executable which is used to determine what CPU target features are enabled for a given compiler toolchain. These features are only provided through internal compiler defines, and thus we have to do a lot of macro shenaningans to get them to display correctly. Bug: 354747380 Test: Built for x86_64 cuttlefish, not tested installation Change-Id: Ic68cd365c41ddd278a856a21796e1645a82fd760
1 parent 7a6842d commit 917dd90

File tree

3 files changed

+162
-0
lines changed

3 files changed

+162
-0
lines changed

cpu_target_features/Android.bp

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package {
2+
default_applicable_licenses: ["Android-Apache-2.0"],
3+
}
4+
5+
cc_binary {
6+
name: "cpu-target-features",
7+
srcs: [
8+
"main.cpp",
9+
],
10+
generated_headers: ["print_target_features.inc"],
11+
}
12+
13+
genrule {
14+
name: "print_target_features.inc",
15+
out: ["print_target_features.inc"],
16+
tool_files: ["generate_printer.py"],
17+
cmd: "$(location generate_printer.py) $(out)",
18+
}
+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
#!/usr/bin/env python3
2+
3+
"""Generate the compilation target feature printing source code.
4+
5+
The source code for detecting target features is heavily redundant and
6+
copy-pasted, and is easier to maintain using a generative script.
7+
8+
This script creates the source and the include files in its current
9+
directory.
10+
"""
11+
12+
import argparse
13+
from pathlib import Path
14+
from typing import Dict, List, Iterable
15+
16+
_CPP_BOILERPLATE: str = """\
17+
#include <stdio.h>
18+
19+
#define TO_STRING_EXP(DEF) #DEF
20+
#define TO_STRING(DEF) TO_STRING_EXP(DEF)
21+
"""
22+
23+
_FEATURES = {
24+
"Aarch64": [
25+
"__ARM_FEATURE_AES",
26+
"__ARM_FEATURE_BTI",
27+
"__ARM_FEATURE_CRC32",
28+
"__ARM_FEATURE_CRYPTO",
29+
"__ARM_FEATURE_PAC_DEFAULT",
30+
"__ARM_FEATURE_SHA2",
31+
"__ARM_FEATURE_SHA3",
32+
"__ARM_FEATURE_SHA512",
33+
],
34+
"Arm32": [
35+
"__ARM_ARCH_ISA_THUMB",
36+
"__ARM_FEATURE_AES",
37+
"__ARM_FEATURE_BTI",
38+
"__ARM_FEATURE_CRC32",
39+
"__ARM_FEATURE_CRYPTO",
40+
"__ARM_FEATURE_PAC_DEFAULT",
41+
"__ARM_FEATURE_SHA2",
42+
],
43+
"X86": [
44+
"__AES__",
45+
"__AVX__",
46+
"__CRC32__",
47+
"__POPCNT__",
48+
"__SHA512__",
49+
"__SHA__",
50+
],
51+
"Riscv": [
52+
"__riscv_vector",
53+
],
54+
}
55+
56+
57+
def _make_function_sig(name: str) -> str:
58+
return f"void print{name}TargetFeatures()"
59+
60+
61+
def check_template(define: str) -> List[str]:
62+
return [
63+
f"#if defined({define})",
64+
f' printf("%s=%s\\n", TO_STRING_EXP({define}), TO_STRING({define}));',
65+
"#else",
66+
f' printf("%s not defined\\n", TO_STRING_EXP({define}));',
67+
"#endif",
68+
]
69+
70+
71+
def generate_cpp_file(define_mapping: Dict[str, List[str]]) -> List[str]:
72+
out: List[str] = _CPP_BOILERPLATE.split("\n")
73+
for target, defines in define_mapping.items():
74+
out.append("")
75+
out.extend(generate_print_function(target, defines))
76+
return out
77+
78+
79+
def generate_print_function(name: str, defines: List[str]) -> List[str]:
80+
"""Generate a print<DEFINE>TargetFeatures function."""
81+
function_body = [_make_function_sig(name) + " {"]
82+
for d in defines:
83+
function_body.extend(check_template(d))
84+
function_body.append("}")
85+
return function_body
86+
87+
88+
def parse_args() -> argparse.Namespace:
89+
parser = argparse.ArgumentParser(description=__doc__)
90+
parser.add_argument(
91+
"cpp_in",
92+
type=Path,
93+
help="Output path to generate the cpp file.",
94+
)
95+
return parser.parse_args()
96+
97+
98+
def main() -> None:
99+
args = parse_args()
100+
printer_cpp_filepath = args.cpp_in
101+
printer_cpp_filepath.write_text(
102+
"\n".join(generate_cpp_file(_FEATURES)), encoding="utf-8"
103+
)
104+
105+
106+
if __name__ == "__main__":
107+
main()

cpu_target_features/main.cpp

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright (C) 2024 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include <stdio.h>
18+
19+
#include "print_target_features.inc"
20+
21+
int main() {
22+
#if defined(__aarch64__)
23+
printAarch64TargetFeatures();
24+
return 0;
25+
#elif defined(__arm__)
26+
printArm32TargetFeatures();
27+
return 0;
28+
#elif defined(__x86_64__) || defined(__i386__)
29+
printX86TargetFeatures();
30+
return 0;
31+
#elif defined(__riscv)
32+
printRiscvTargetFeatures();
33+
return 0;
34+
#else
35+
#error Unsupported arch. This binary only supports aarch64, arm, x86, x86-64, and risc-v
36+
#endif
37+
}

0 commit comments

Comments
 (0)