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