1 module d.semantic.mangler;
2 
3 import d.semantic.semantic;
4 
5 import d.ir.symbol;
6 import d.ir.type;
7 
8 // Conflict with Interface in object.di
9 alias Interface = d.ir.symbol.Interface;
10 
11 struct TypeMangler {
12 	private SemanticPass pass;
13 	alias pass this;
14 	
15 	this(SemanticPass pass) {
16 		this.pass = pass;
17 	}
18 	
19 	string visit(Type t) {
20 		auto s = t.accept(this);
21 		final switch(t.qualifier) with(TypeQualifier) {
22 			case Mutable :
23 				return s;
24 			
25 			case Inout :
26 				return "Ng" ~ s;
27 			
28 			case Const :
29 				return "x" ~ s;
30 			
31 			case Shared :
32 				return "O" ~ s;
33 			
34 			case ConstShared :
35 				return "xO" ~ s;
36 			
37 			case Immutable :
38 				return "y" ~ s;
39 		}
40 	}
41 	
42 	string visit(BuiltinType t) {
43 		final switch(t) with(BuiltinType) {
44 			case None :
45 				assert(0, "none should never be mangled");
46 			
47 			case Void :
48 				return "v";
49 			
50 			case Bool :
51 				return "b";
52 			
53 			case Char :
54 				return "a";
55 			
56 			case Wchar :
57 				return "u";
58 			
59 			case Dchar :
60 				return "w";
61 			
62 			case Byte :
63 				return "g";
64 			
65 			case Ubyte :
66 				return "h";
67 			
68 			case Short :
69 				return "s";
70 			
71 			case Ushort :
72 				return "t";
73 			
74 			case Int :
75 				return "i";
76 			
77 			case Uint :
78 				return "k";
79 			
80 			case Long :
81 				return "l";
82 			
83 			case Ulong :
84 				return "m";
85 			
86 			case Cent :
87 				// Used for ifloat, that won't be implemented.
88 				return "o";
89 			
90 			case Ucent :
91 				// Used for idouble, that won't be implemented.
92 				return "p";
93 			
94 			case Float :
95 				return "f";
96 			
97 			case Double :
98 				return "d";
99 			
100 			case Real :
101 				return "e";
102 			
103 			case Null :
104 				assert(0, "Mangling for typeof(null) is not Implemented");
105 		}
106 	}
107 	
108 	string visitPointerOf(Type t) {
109 		return "P" ~ visit(t);
110 	}
111 	
112 	string visitSliceOf(Type t) {
113 		return "A" ~ visit(t);
114 	}
115 	
116 	string visitArrayOf(uint size, Type t) {
117 		import std.conv;
118 		return "G" ~ size.to!string() ~ visit(t);
119 	}
120 	
121 	string visit(Struct s) {
122 		scheduler.require(s, Step.Populated);
123 		return s.mangle.toString(context);
124 	}
125 	
126 	string visit(Class c) {
127 		scheduler.require(c, Step.Populated);
128 		return c.mangle.toString(context);
129 	}
130 	
131 	string visit(Enum e) {
132 		scheduler.require(e);
133 		return e.mangle.toString(context);
134 	}
135 	
136 	string visit(TypeAlias a) {
137 		scheduler.require(a);
138 		return a.mangle.toString(context);
139 	}
140 	
141 	string visit(Interface i) {
142 		scheduler.require(i, Step.Populated);
143 		return i.mangle.toString(context);
144 	}
145 	
146 	string visit(Union u) {
147 		scheduler.require(u, Step.Populated);
148 		return u.mangle.toString(context);
149 	}
150 	
151 	string visit(Function f) {
152 		return "M";
153 	}
154 	
155 	string visit(Type[] seq) {
156 		assert(0, "Not implemented.");
157 	}
158 	
159 	private auto mangleParam(ParamType t) {
160 		return (t.isRef ? "K" : "") ~ visit(t.getType());
161 	}
162 	
163 	private auto mangleLinkage(Linkage linkage) {
164 		switch(linkage) with(Linkage) {
165 			case D :
166 				return "F";
167 			
168 			case C :
169 				return "U";
170 			/+
171 			case Windows :
172 				return "W";
173 			
174 			case Pascal :
175 				return "V";
176 			
177 			case CXX :
178 				return "R";
179 			+/
180 			default:
181 				import std.conv;
182 				assert(0, "Linkage " ~ to!string(linkage) ~ " is not supported.");
183 		}
184 	}
185 	
186 	string visit(FunctionType f) {
187 		auto base = f.contexts.length ? "D" : "";
188 		auto linkage = mangleLinkage(f.linkage);
189 
190 		import std.algorithm, std.range;
191 		auto args = f.parameters.map!(p => mangleParam(p)).join();
192 		auto ret = mangleParam(f.returnType);
193 		return base ~ linkage ~ args ~ "Z" ~ ret;
194 	}
195 	
196 	string visit(Pattern p) {
197 		assert(0, "Can't mangle pattern.");
198 	}
199 	
200 	import d.ir.error;
201 	string visit(CompileError e) {
202 		assert(0, "Can't mangle error type.");
203 	}
204 }
205 
206 struct ValueMangler {
207 	private SemanticPass pass;
208 	alias pass this;
209 	
210 	this(SemanticPass pass) {
211 		this.pass = pass;
212 	}
213 	
214 	import d.ir.expression, std.conv;
215 	string visit(CompileTimeExpression e) {
216 		return this.dispatch(e);
217 	}
218 	
219 	string visit(StringLiteral s) {
220 		auto ret = "a";
221 		auto str = s.value;
222 		auto len = str.length;
223 		
224 		ret.reserve(len * 2 + 8);
225 		ret ~= to!string(len);
226 		ret ~= '_';
227 		foreach(ubyte c; str) {
228 			ret ~= byte2hex(c);
229 		}
230 		
231 		return ret;
232 	}
233 	
234 	string visit(BooleanLiteral e) {
235 		return to!string(cast(ubyte) e.value);
236 	}
237 	
238 	string visit(IntegerLiteral e) {
239 		if (!isSigned(e.type.builtin)) {
240 			return e.value.to!string();
241 		}
242 		
243 		long v = e.value;
244 		
245 		return v >= 0
246 			? v.to!string()
247 			: "N" ~ to!string(-v);
248 	}
249 }
250 
251 private:
252 
253 char[2] byte2hex(const ubyte b) pure {
254 	static immutable char[16] hexDigits = "0123456789abcdef";
255 	ubyte hi = (b >> 4);
256 	ubyte lo = (b & 0x0F);
257 	return [hexDigits[hi], hexDigits[lo]];
258 }
259 
260 unittest {
261 	assert(byte2hex(0) == "00");
262 	assert(byte2hex(42) == "2a");
263 	assert(byte2hex(255) == "ff");
264 }
265 
266 unittest {
267 	void check(string s, string m) {
268 		import source.location, d.ir.expression;
269 		auto sl = new StringLiteral(Location.init, s);
270 		
271 		assert(ValueMangler().visit(sl) == m);
272 	}
273 	
274 	check("Hello World", "a11_48656c6c6f20576f726c64");
275 	check("©", "a2_c2a9");
276 }
277