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