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