1 module llvm.config;
2 
3 import std.conv : to;
4 import std.array : array, replace, join;
5 import std.algorithm.iteration : filter, map, joiner;
6 import std.algorithm.searching : canFind;
7 
8 /// LLVM Versions that llvm-d supports
9 immutable LLVM_Versions = [
10 	[10,0,0],
11 	[9,0,1],
12 	[9,0,0],
13 	[8,0,1],
14 	[8,0,0],
15 	[7,1,0],
16 	[7,0,1],
17 	[7,0,0],
18 	[6,0,1],
19 	[6,0,0],
20 	[5,0,2],
21 	[5,0,1],
22 	[5,0,0],
23 	[4,0,1],
24 	[4,0,0],
25 	[3,9,1],
26 	[3,9,0],
27 	[3,8,1],
28 	[3,8,0],
29 	[3,7,1],
30 	[3,7,0],
31 	[3,6,2],
32 	[3,6,1],
33 	[3,6,0],
34 	[3,5,2],
35 	[3,5,1],
36 	[3,5,0],
37 	[3,4,2],
38 	[3,4,1],
39 	[3,4,0],
40 	[3,3,0],
41 	[3,2,0],
42 	[3,1,0],
43 ];
44 
45 mixin(LLVM_Versions.map!(ver =>
46 	q{version(LLVM_%MAJOR_%MINOR_%PATCH) {
47 			immutable LLVM_VERSION_MAJOR = %MAJOR;
48 			immutable LLVM_VERSION_MINOR = %MINOR;
49 			immutable LLVM_VERSION_PATCH = %PATCH;
50 		}}.replace("%MAJOR", ver[0].to!string).replace("%MINOR", ver[1].to!string).replace("%PATCH", ver[2].to!string)
51 	).join("else\n") ~
52 	q{else {
53 		immutable LLVM_VERSION_MAJOR = LLVM_Versions[0][0];
54 		immutable LLVM_VERSION_MINOR = LLVM_Versions[0][1];
55 		immutable LLVM_VERSION_PATCH = LLVM_Versions[0][2];
56 	}}
57 );
58 
59 /// Makes an ordered identifier from a major, minor, and patch number
60 pure nothrow @nogc
61 ulong asVersion(ushort major, ushort minor, ushort patch)
62 {
63 	return cast(ulong)(major) << (ushort.sizeof*2*8) | cast(ulong)(minor) << (ushort.sizeof*8) | cast(ulong)(patch);
64 }
65 
66 /// LLVM Version that llvm-d was compiled against
67 immutable LLVM_Version = asVersion(LLVM_VERSION_MAJOR, LLVM_VERSION_MINOR, LLVM_VERSION_PATCH);
68 
69 /// LLVM Version that llvm-d was compiled against as a string
70 immutable LLVM_VersionString = LLVM_VERSION_MAJOR.to!string ~ "." ~ LLVM_VERSION_MINOR.to!string ~ "." ~ LLVM_VERSION_PATCH.to!string;
71 
72 /// LLVM Targets that can be used (enable target Name via version LLVM_Target_Name)
73 immutable LLVM_Targets = {
74 	string[] targets;
75 	mixin({
76 			static if (LLVM_Version >= asVersion(10, 0, 0)) {
77 				return ["AArch64","AMDGPU","ARC","ARM","AVR","BPF","Hexagon","Lanai","MSP430","Mips","NVPTX","PowerPC","RISCV","Sparc","SystemZ","VE","WebAssembly","X86","XCore"];
78 			} else static if (LLVM_Version >= asVersion(9, 0, 1)) {
79 				return ["AArch64","AMDGPU","ARC","ARM","AVR","BPF","Hexagon","Lanai","MSP430","Mips","NVPTX","PowerPC","RISCV","Sparc","SystemZ","WebAssembly","X86","XCore"];
80 			} else static if (LLVM_Version >= asVersion(9, 0, 0)) {
81 				return ["AArch64","AMDGPU","ARC","ARM","AVR","BPF","Hexagon","Lanai","MSP430","Mips","NVPTX","Nios2","PowerPC","RISCV","Sparc","SystemZ","WebAssembly","X86","XCore"];
82 			} else static if (LLVM_Version >= asVersion(8, 0, 0)) {
83 				return ["AArch64","AMDGPU","ARC","ARM","AVR","BPF","Hexagon","Lanai","MSP430","Mips","NVPTX","Nios2","PowerPC","RISCV","Sparc","SystemZ","WebAssembly","X86","XCore"];
84 			} else static if (LLVM_Version >= asVersion(7, 0, 0)) {
85 				return ["AArch64","AMDGPU","ARC","ARM","AVR","BPF","Hexagon","Lanai","Mips","MSP430","Nios2","NVPTX","PowerPC","RISCV","Sparc","SystemZ","WebAssembly","X86","XCore"];
86 			} else static if (LLVM_Version >= asVersion(6, 0, 0)) {
87 				return ["AArch64","AMDGPU","ARC","ARM","AVR","BPF","Hexagon","Lanai","Mips","MSP430","Nios2","NVPTX","PowerPC","RISCV","Sparc","SystemZ","WebAssembly","X86","XCore"];
88 			} else static if (LLVM_Version >= asVersion(5, 0, 0)) {
89 				return ["AArch64","AMDGPU","ARM","AVR","BPF","Hexagon","Lanai","Mips","MSP430","Nios2","NVPTX","PowerPC","RISCV","Sparc","SystemZ","WebAssembly","X86","XCore"];
90 			} else static if (LLVM_Version >= asVersion(4, 0, 0)) {
91 				return ["AArch64","AMDGPU","ARM","AVR","BPF","Hexagon","Lanai","MSP430","Mips","NVPTX","PowerPC","RISCV","Sparc","SystemZ","WebAssembly","X86","XCore"];
92 			} else static if (LLVM_Version >= asVersion(3, 9, 0)) {
93 				return ["AArch64","AMDGPU","ARM","AVR","BPF","Hexagon","Lanai","MSP430","Mips","NVPTX","PowerPC","Sparc","SystemZ","WebAssembly","X86","XCore"];
94 			} else static if (LLVM_Version >= asVersion(3, 8, 0)) {
95 				return ["AArch64","AMDGPU","ARM","AVR","BPF","CppBackend","Hexagon","MSP430","Mips","NVPTX","PowerPC","Sparc","SystemZ","WebAssembly","X86","XCore"];
96 			} else static if (LLVM_Version >= asVersion(3, 7, 0)) {
97 				return ["AArch64","AMDGPU","ARM","BPF","CppBackend","Hexagon","MSP430","Mips","NVPTX","PowerPC","Sparc","SystemZ","WebAssembly","X86","XCore"];
98 			} else static if (LLVM_Version >= asVersion(3, 6, 0)) {
99 				return ["AArch64","ARM","CppBackend","Hexagon","MSP430","Mips","NVPTX","PowerPC","R600","Sparc","SystemZ","X86","XCore"];
100 			} else static if (LLVM_Version >= asVersion(3, 5, 0)) {
101 				return ["AArch64","ARM","CppBackend","Hexagon","MSP430","Mips","NVPTX","PowerPC","R600","Sparc","SystemZ","X86","XCore"];
102 			} else static if (LLVM_Version >= asVersion(3, 4, 0)) {
103 				return ["AArch64","ARM","CppBackend","Hexagon","MSP430","Mips","NVPTX","PowerPC","R600","Sparc","SystemZ","X86","XCore"];
104 			} else static if (LLVM_Version >= asVersion(3, 3, 0)) {
105 				return ["AArch64","ARM","CppBackend","Hexagon","MBlaze","MSP430","Mips","NVPTX","PowerPC","R600","Sparc","SystemZ","X86","XCore"];
106 			} else static if (LLVM_Version >= asVersion(3, 2, 0)) {
107 				return ["ARM","CellSPU","CppBackend","Hexagon","MBlaze","MSP430","Mips","NVPTX","PTX","PowerPC","Sparc","X86","XCore"];
108 			} else {
109 				return ["ARM","CellSPU","CppBackend","Hexagon","MBlaze","MSP430","Mips","PTX","PowerPC","Sparc","X86","XCore"];
110 			}
111 		}().map!(t => "version (LLVM_Target_" ~ t ~ ") targets ~= \"" ~ t ~ "\";").joiner.array);
112 	return targets;
113 }();
114 
115 /// LLVM Targets with AsmPrinter capability (if enabled)
116 immutable LLVM_AsmPrinters = {
117 
118 	static if (LLVM_Version >= asVersion(10, 0, 0)) {
119 		return ["AArch64","AMDGPU","AMDGPU","ARC","ARM","AVR","BPF","Hexagon","Lanai","MSP430","Mips","NVPTX","PowerPC","RISCV","Sparc","SystemZ","VE","WebAssembly","X86","XCore"];
120 	} else static if (LLVM_Version >= asVersion(9, 0, 1)) {
121 		return ["AArch64","AMDGPU","AMDGPU","ARC","ARM","AVR","BPF","Hexagon","Lanai","MSP430","Mips","NVPTX","PowerPC","RISCV","Sparc","SystemZ","WebAssembly","X86","XCore"];
122 	} else static if (LLVM_Version >= asVersion(9, 0, 0)) {
123 		return ["AArch64","AMDGPU","AMDGPU","ARC","ARM","AVR","BPF","Hexagon","Lanai","MSP430","Mips","NVPTX","PowerPC","RISCV","Sparc","SystemZ","WebAssembly","X86","XCore"];
124 	} else static if (LLVM_Version >= asVersion(8, 0, 0)) {
125 		return ["AArch64","AMDGPU","AMDGPU","ARC","ARM","AVR","BPF","Hexagon","Lanai","MSP430","Mips","NVPTX","PowerPC","RISCV","Sparc","SystemZ","WebAssembly","X86","XCore"];
126 	} else static if (LLVM_Version >= asVersion(7, 0, 0)) {
127 		return ["AArch64","AMDGPU","AMDGPU","ARC","ARM","AVR","BPF","Hexagon","Lanai","Mips","MSP430","Nios2","NVPTX","PowerPC","RISCV","Sparc","SystemZ","WebAssembly","X86","XCore"];
128 	} else static if (LLVM_Version >= asVersion(6, 0, 0)) {
129 		return ["AArch64","AMDGPU","ARC","ARM","AVR","BPF","Hexagon","Lanai","Mips","MSP430","Nios2","NVPTX","PowerPC","RISCV","Sparc","SystemZ","WebAssembly","X86","XCore"];
130 	} else static if (LLVM_Version >= asVersion(5, 0, 0)) {
131 		return ["AArch64","AMDGPU","ARM","AVR","BPF","Hexagon","Lanai","Mips","MSP430","NVPTX","PowerPC","Sparc","SystemZ","WebAssembly","X86","XCore"];
132 	} else static if (LLVM_Version >= asVersion(4, 0, 0)) {
133 		return ["AArch64","AMDGPU","ARM","AVR","BPF","Hexagon","Lanai","MSP430","Mips","NVPTX","PowerPC","Sparc","SystemZ","WebAssembly","X86","XCore"];
134 	} else static if (LLVM_Version >= asVersion(3, 9, 0)) {
135 		return ["AArch64","AMDGPU","ARM","BPF","Hexagon","Lanai","MSP430","Mips","NVPTX","PowerPC","Sparc","SystemZ","WebAssembly","X86","XCore"];
136 	} else static if (LLVM_Version >= asVersion(3, 8, 0)) {
137 		return ["AArch64","AMDGPU","ARM","BPF","Hexagon","MSP430","Mips","NVPTX","PowerPC","Sparc","SystemZ","WebAssembly","X86","XCore"];
138 	} else static if (LLVM_Version >= asVersion(3, 7, 0)) {
139 		return ["AArch64","AMDGPU","ARM","BPF","Hexagon","MSP430","Mips","NVPTX","PowerPC","Sparc","SystemZ","X86","XCore"];
140 	} else static if (LLVM_Version >= asVersion(3, 6, 0)) {
141 		return ["AArch64","ARM","Hexagon","MSP430","Mips","NVPTX","PowerPC","R600","Sparc","SystemZ","X86","XCore"];
142 	} else static if (LLVM_Version >= asVersion(3, 5, 0)) {
143 		return ["AArch64","ARM","Hexagon","MSP430","Mips","NVPTX","PowerPC","R600","Sparc","SystemZ","X86","XCore"];
144 	} else static if (LLVM_Version >= asVersion(3, 4, 0)) {
145 		return ["AArch64","ARM","Hexagon","MSP430","Mips","NVPTX","PowerPC","R600","Sparc","SystemZ","X86","XCore"];
146 	} else static if (LLVM_Version >= asVersion(3, 3, 0)) {
147 		return ["AArch64","ARM","Hexagon","MBlaze","MSP430","Mips","NVPTX","PowerPC","R600","Sparc","SystemZ","X86","XCore"];
148 	} else static if (LLVM_Version >= asVersion(3, 2, 0)) {
149 		return ["ARM","CellSPU","Hexagon","MBlaze","MSP430","Mips","NVPTX","PowerPC","Sparc","X86","XCore"];
150 	} else {
151 		return ["ARM","CellSPU","Hexagon","MBlaze","MSP430","Mips","PTX","PowerPC","Sparc","X86","XCore"];
152 	}
153 }().filter!(t => LLVM_Targets.canFind(t)).array;
154 
155 /// LLVM Targets with AsmParser capability (if enabled)
156 immutable LLVM_AsmParsers = {
157 	static if (LLVM_Version >= asVersion(10, 0, 0)) {
158 		return ["AArch64","AMDGPU","ARM","AVR","BPF","Hexagon","Lanai","MSP430","Mips","PowerPC","RISCV","Sparc","SystemZ","WebAssembly","X86"];
159 	} else static if (LLVM_Version >= asVersion(9, 0, 1)) {
160 		return ["AArch64","AMDGPU","ARM","AVR","BPF","Hexagon","Lanai","MSP430","Mips","PowerPC","RISCV","Sparc","SystemZ","WebAssembly","X86"];
161 	} else static if (LLVM_Version >= asVersion(9, 0, 0)) {
162 		return ["AArch64","AMDGPU","ARM","AVR","BPF","Hexagon","Lanai","MSP430","Mips","PowerPC","RISCV","Sparc","SystemZ","WebAssembly","X86"];
163 	} else static if (LLVM_Version >= asVersion(8, 0, 0)) {
164 		return ["AArch64","AMDGPU","ARM","AVR","BPF","Hexagon","Lanai","MSP430","Mips","PowerPC","RISCV","Sparc","SystemZ","WebAssembly","X86"];
165 	} else static if (LLVM_Version >= asVersion(7, 0, 0)) {
166 		return ["AArch64","AMDGPU","ARM","AVR","BPF","Hexagon","Lanai","Mips","PowerPC","RISCV","Sparc","SystemZ","WebAssembly","X86"];
167 	} else static if (LLVM_Version >= asVersion(6, 0, 0)) {
168 		return ["AArch64","AMDGPU","ARM","AVR","BPF","Hexagon","Lanai","Mips","PowerPC","RISCV","Sparc","SystemZ","X86"];
169 	} else static if (LLVM_Version >= asVersion(5, 0, 0)) {
170 		return ["AArch64","AMDGPU","ARM","AVR","Hexagon","Lanai","Mips","PowerPC","Sparc","SystemZ","X86"];
171 	} else static if (LLVM_Version >= asVersion(4, 0, 0)) {
172 		return ["AArch64","AMDGPU","ARM","AVR","Hexagon","Lanai","Mips","PowerPC","Sparc","SystemZ","X86"];
173 	} else static if (LLVM_Version >= asVersion(3, 9, 0)) {
174 		return ["AArch64","AMDGPU","ARM","Hexagon","Lanai","Mips","PowerPC","Sparc","SystemZ","X86"];
175 	} else static if (LLVM_Version >= asVersion(3, 8, 0)) {
176 		return ["AArch64","AMDGPU","ARM","Hexagon","Mips","PowerPC","Sparc","SystemZ","X86"];
177 	} else static if (LLVM_Version >= asVersion(3, 7, 0)) {
178 		return ["AArch64","AMDGPU","ARM","Mips","PowerPC","Sparc","SystemZ","X86"];
179 	} else static if (LLVM_Version >= asVersion(3, 6, 0)) {
180 		return ["AArch64","ARM","Mips","PowerPC","R600","Sparc","SystemZ","X86"];
181 	} else static if (LLVM_Version >= asVersion(3, 5, 0)) {
182 		return ["AArch64","ARM","Mips","PowerPC","Sparc","SystemZ","X86"];
183 	} else static if (LLVM_Version >= asVersion(3, 4, 0)) {
184 		return ["AArch64","ARM","Mips","PowerPC","SystemZ","X86"];
185 	} else static if (LLVM_Version >= asVersion(3, 3, 0)) {
186 		return ["AArch64","ARM","MBlaze","Mips","PowerPC","SystemZ","X86"];
187 	} else static if (LLVM_Version >= asVersion(3, 2, 0)) {
188 		return ["ARM","MBlaze","Mips","X86"];
189 	} else {
190 		return ["ARM","MBlaze","Mips","X86"];
191 	}
192 }().filter!(t => LLVM_Targets.canFind(t)).array;
193 
194 /// LLVM Targets with Disassembler capability (if enabled)
195 immutable LLVM_Disassemblers = {
196 	static if (LLVM_Version >= asVersion(10, 0, 0)) {
197 		return ["AArch64","AMDGPU","ARC","ARM","AVR","BPF","Hexagon","Lanai","MSP430","Mips","PowerPC","RISCV","Sparc","SystemZ","WebAssembly","X86","XCore"];
198 	} else static if (LLVM_Version >= asVersion(9, 0, 1)) {
199 		return ["AArch64","AMDGPU","ARC","ARM","AVR","BPF","Hexagon","Lanai","MSP430","Mips","PowerPC","RISCV","Sparc","SystemZ","WebAssembly","X86","XCore"];
200 	} else static if (LLVM_Version >= asVersion(9, 0, 0)) {
201 		return ["AArch64","AMDGPU","ARC","ARM","AVR","BPF","Hexagon","Lanai","MSP430","Mips","PowerPC","RISCV","Sparc","SystemZ","WebAssembly","X86","XCore"];
202 	} else static if (LLVM_Version >= asVersion(8, 0, 0)) {
203 		return ["AArch64","AMDGPU","ARC","ARM","AVR","BPF","Hexagon","Lanai","MSP430","Mips","PowerPC","RISCV","Sparc","SystemZ","WebAssembly","X86","XCore"];
204 	} else static if (LLVM_Version >= asVersion(7, 0, 0)) {
205 		return ["AArch64","AMDGPU","ARC","ARM","AVR","BPF","Hexagon","Lanai","Mips","PowerPC","RISCV","Sparc","SystemZ","WebAssembly","X86","XCore"];
206 	} else static if (LLVM_Version >= asVersion(6, 0, 0)) {
207 		return ["AArch64","AMDGPU","ARC","ARM","AVR","BPF","Hexagon","Lanai","Mips","PowerPC","RISCV","Sparc","SystemZ","WebAssembly","X86","XCore"];
208 	} else static if (LLVM_Version >= asVersion(5, 0, 0)) {
209 		return ["AArch64","AMDGPU","ARM","AVR","BPF","Hexagon","Lanai","Mips","PowerPC","Sparc","SystemZ","WebAssembly","X86","XCore"];
210 	} else static if (LLVM_Version >= asVersion(4, 0, 0)) {
211 		return ["AArch64","AMDGPU","ARM","AVR","BPF","Hexagon","Lanai","Mips","PowerPC","Sparc","SystemZ","WebAssembly","X86","XCore"];
212 	} else  static if (LLVM_Version >= asVersion(3, 9, 0)) {
213 		return ["AArch64","AMDGPU","ARM","Hexagon","Lanai","Mips","PowerPC","Sparc","SystemZ","WebAssembly","X86","XCore"];
214 	} else static if (LLVM_Version >= asVersion(3, 8, 0)) {
215 		return ["AArch64","ARM","Hexagon","Mips","PowerPC","Sparc","SystemZ","WebAssembly","X86","XCore"];
216 	} else static if (LLVM_Version >= asVersion(3, 7, 0)) {
217 		return ["AArch64","ARM","Hexagon","Mips","PowerPC","Sparc","SystemZ","X86","XCore"];
218 	} else static if (LLVM_Version >= asVersion(3, 6, 0)) {
219 		return ["AArch64","ARM","Hexagon","Mips","PowerPC","Sparc","SystemZ","X86","XCore"];
220 	} else static if (LLVM_Version >= asVersion(3, 5, 0)) {
221 		return ["AArch64","ARM","Mips","PowerPC","Sparc","SystemZ","X86","XCore"];
222 	} else static if (LLVM_Version >= asVersion(3, 4, 0)) {
223 		return ["AArch64","ARM","Mips","SystemZ","X86","XCore"];
224 	} else static if (LLVM_Version >= asVersion(3, 3, 0)) {
225 		return ["AArch64","ARM","MBlaze","Mips","X86","XCore"];
226 	} else static if (LLVM_Version >= asVersion(3, 2, 0)) {
227 		return ["ARM","MBlaze","Mips","X86"];
228 	} else {
229 		return ["ARM","MBlaze","Mips","X86"];
230 	}
231 }().filter!(t => LLVM_Targets.canFind(t)).array;
232 
233 /// LLVM Target that corresponds to the native architecture (if enabled)
234 immutable LLVM_NativeTarget = {
235 	auto t = {
236 		     version(X86)     return "X86";
237 		else version(X86_64)  return "X86";
238 		else version(SPARC)   return "Sparc";
239 		else version(SPARC64) return "Sparc";
240 		else version(PPC)     return "PowerPC";
241 		else version(PPC64)   return "PowerPC";
242 		else version(AArch64) return "AArch64";
243 		else version(ARM)     return "ARM";
244 		else version(MIPS32)  return "Mips";
245 		else version(MIPS64)  return "Mips";
246 		else version(SystemZ) return "SystemZ";
247 		else                  return "";
248 	}();
249 	if (t != "" && LLVM_Targets.canFind(t)) return t;
250 	else return "";
251 }();