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