aboutsummaryrefslogtreecommitdiff
path: root/misc/featuregen/featuregen.py
blob: da4cc68f51fbe26a07c399c15cc6538272081c4a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import subprocess
import tempfile
import os
import sys

archs = [
	("amd64",     "linux_amd64", "x86_64-pc-linux-gnu", [], []),
	("i386",      "linux_i386",  "i386-pc-linux-gnu",   [], []),
	("arm32",     "linux_arm32", "arm-linux-gnu",       [], []),
	("arm64",     "linux_arm64", "aarch64-linux-elf",   [], []),
	("wasm32",    "js_wasm32",   "wasm32-js-js",        [], []),
	("wasm64p32", "js_wasm64p32","wasm32-js-js",        [], []),
];

SEEKING_CPUS     = 0
PARSING_CPUS     = 1
PARSING_FEATURES = 2

with tempfile.NamedTemporaryFile(suffix=".odin", delete=True) as temp_file:
	temp_file.write(b"package main\n")

	for arch, target, triple, cpus, features in archs:
		cmd = ["odin", "build", temp_file.name, "-file", "-build-mode:llvm", "-out:temp", "-target-features:\"help\"", f"-target:\"{target}\""]
		process = subprocess.Popen(cmd, stderr=subprocess.PIPE, text=True)

		state = SEEKING_CPUS
		for line in process.stderr:

			if state == SEEKING_CPUS:
				if line == "Available CPUs for this target:\n":
					state = PARSING_CPUS
			
			elif state == PARSING_CPUS:
				if line == "Available features for this target:\n":
					state = PARSING_FEATURES
					continue
			
				parts = line.split(" -", maxsplit=1)
				if len(parts) < 2:
					continue

				cpu = parts[0].strip()
				cpus.append(cpu)

			elif state == PARSING_FEATURES:
				if line == "\n" and len(features) > 0:
					break

				parts = line.split(" -", maxsplit=1)
				if len(parts) < 2:
					continue

				feature = parts[0].strip()
				features.append(feature)

		process.wait()
		if process.returncode != 0:
			print(f"odin build returned with non-zero exit code {process.returncode}")
			sys.exit(1)

		os.remove("temp.ll")

def print_default_features(triple, microarch):
	cmd = ["./featuregen", triple, microarch]
	process = subprocess.Popen(cmd, stdout=subprocess.PIPE, text=True)
	first = True
	for line in process.stdout:
		print("" if first else ",", line.strip(), sep="", end="")
		first = False
	process.wait()
	if process.returncode != 0:
		print(f"featuregen returned with non-zero exit code {process.returncode}")
		sys.exit(1)

print("// Generated with the featuregen script in `misc/featuregen`")
print("gb_global String target_microarch_list[TargetArch_COUNT] = {")
print("\t// TargetArch_Invalid:")
print('\tstr_lit(""),')
for arch, target, triple, cpus, features in archs:
	print(f"\t// TargetArch_{arch}:")
	print(f'\tstr_lit("{','.join(cpus)}"),')
print("};")

print("")

print("// Generated with the featuregen script in `misc/featuregen`")
print("gb_global String target_features_list[TargetArch_COUNT] = {")
print("\t// TargetArch_Invalid:")
print('\tstr_lit(""),')
for arch, target, triple, cpus, features in archs:
	print(f"\t// TargetArch_{arch}:")
	print(f'\tstr_lit("{','.join(features)}"),')
print("};")

print("")

print("// Generated with the featuregen script in `misc/featuregen`")
print("gb_global int target_microarch_counts[TargetArch_COUNT] = {")
print("\t// TargetArch_Invalid:")
print("\t0,")
for arch, target, triple, cpus, feature in archs:
	print(f"\t// TargetArch_{arch}:")
	print(f"\t{len(cpus)},")
print("};")

print("")

print("// Generated with the featuregen script in `misc/featuregen`")
print("gb_global MicroarchFeatureList microarch_features_list[] = {")
for arch, target, triple, cpus, features in archs:
	print(f"\t// TargetArch_{arch}:")
	for cpu in cpus:
		print(f'\t{{ str_lit("{cpu}"), str_lit("', end="")
		print_default_features(triple, cpu)
		print('") },')
print("};")