1 module d.ir.symbol; 2 3 import d.ir.dscope; 4 import d.ir.expression; 5 import d.ir.type; 6 7 import d.common.node; 8 9 import source.context; 10 import source.name; 11 12 public import d.common.qualifier; 13 14 enum Step { 15 Parsed, 16 Populated, 17 Signed, 18 Processed, 19 } 20 21 enum InTemplate { 22 No, 23 Yes, 24 } 25 26 class Symbol : Node { 27 Name name; 28 Name mangle; 29 30 import std.bitmanip; 31 mixin(bitfields!( 32 // sdfmt off 33 Step, "step", 2, 34 Linkage, "linkage", 3, 35 Visibility, "visibility", 3, 36 InTemplate, "inTemplate", 1, 37 bool, "hasThis", 1, 38 bool, "hasContext", 1, 39 bool, "isPoisoned", 1, 40 bool, "isAbstract", 1, 41 bool, "isProperty", 1, 42 uint, "__derived", 18, 43 // sdfmt on 44 )); 45 46 this(Location location, Name name) { 47 super(location); 48 49 this.name = name; 50 } 51 52 string toString(const Context c) const { 53 return name.toString(c); 54 } 55 56 protected: 57 @property 58 uint derived() const { 59 return __derived; 60 } 61 62 @property 63 uint derived(uint val) { 64 __derived = val; 65 return derived; 66 } 67 } 68 69 /** 70 * Symbol that introduce a scope. 71 * NB: Symbols that introduce non standard scope may not extend this. 72 */ 73 abstract class ScopeSymbol : Symbol, Scope { 74 mixin ScopeImpl; 75 76 this(Location location, Scope parentScope, Name name) { 77 super(location, name); 78 fillParentScope(parentScope); 79 } 80 } 81 82 /** 83 * Symbol that represent a value once resolved. 84 */ 85 abstract class ValueSymbol : Symbol { 86 this(Location location, Name name) { 87 super(location, name); 88 } 89 } 90 91 /** 92 * Package 93 */ 94 class Package : Symbol, Scope { 95 mixin ScopeImpl!(ScopeType.Module); 96 97 Package parent; 98 99 this(Location location, Name name, Package parent) { 100 super(location, name); 101 102 this.parent = parent; 103 } 104 } 105 106 /** 107 * Function 108 */ 109 class Function : ValueSymbol, Scope { 110 mixin ScopeImpl; 111 FunctionType type; 112 113 Variable[] params; 114 uint[Variable] closure; 115 116 import d.ir.instruction; 117 Body fbody; 118 119 this(Location location, Scope parentScope, FunctionType type, Name name, 120 Variable[] params) { 121 super(location, name); 122 fillParentScope(parentScope); 123 124 this.type = type; 125 this.params = params; 126 } 127 128 @property 129 Intrinsic intrinsicID() const { 130 if (hasThis) { 131 return Intrinsic.None; 132 } 133 134 return cast(Intrinsic) __derived; 135 } 136 137 @property 138 Intrinsic intrinsicID(Intrinsic id) in { 139 assert(!hasThis, "Method can't be intrinsic"); 140 assert(intrinsicID == Intrinsic.None, "This is already an intrinsic"); 141 } do { 142 __derived = id; 143 return intrinsicID; 144 } 145 146 void dump(const Context c) const { 147 import std.algorithm, std.range; 148 auto params = params.map!(p => p.name.toString(c)).join(", "); 149 150 auto retStr = 151 (step >= Step.Signed) ? type.returnType.toString(c) : "__untyped"; 152 153 import std.stdio; 154 write(retStr, ' ', name.toString(c), '(', params, ") {"); 155 fbody.dump(c); 156 writeln("}\n"); 157 } 158 } 159 160 /** 161 * Entry for template parameters 162 */ 163 class TemplateParameter : Symbol { 164 this(Location location, Name name, uint index) { 165 super(location, name); 166 167 this.derived = index; 168 } 169 170 final: 171 @property 172 uint index() const { 173 return derived; 174 } 175 } 176 177 /** 178 * Superclass for struct, class and interface. 179 */ 180 abstract class Aggregate : ScopeSymbol { 181 Name[] aliasThis; 182 Symbol[] members; 183 184 this(Location location, Scope parentScope, Name name, Symbol[] members) { 185 super(location, parentScope, name); 186 187 this.members = members; 188 } 189 } 190 191 final: 192 /** 193 * Module 194 */ 195 class Module : Package { 196 Symbol[] members; 197 Function[] tests; 198 199 this(Location location, Name name, Package parent) { 200 super(location, name, parent); 201 dmodule = this; 202 } 203 } 204 205 /** 206 * Placeholder in symbol tables for templates and functions. 207 */ 208 class OverloadSet : Symbol { 209 Symbol[] set; 210 211 this(Location location, Name name, Symbol[] set) { 212 super(location, name); 213 this.mangle = name; 214 this.set = set; 215 } 216 217 OverloadSet clone() { 218 auto os = new OverloadSet(location, name, set); 219 os.mangle = mangle; 220 return os; 221 } 222 223 @property 224 isResolved() const { 225 return !!__derived; 226 } 227 228 @property 229 isResolved(bool resolved) { 230 __derived = resolved; 231 return resolved; 232 } 233 } 234 235 /** 236 * Variable 237 */ 238 class Variable : ValueSymbol { 239 Expression value; 240 ParamType paramType; 241 242 this(Location location, ParamType paramType, Name name, 243 Expression value = null) { 244 super(location, name); 245 246 this.paramType = paramType; 247 this.value = value; 248 } 249 250 this(Location location, Type type, Name name, Expression value = null) { 251 super(location, name); 252 253 this.type = type; 254 this.value = value; 255 } 256 257 @property 258 inout(Type) type() inout { 259 return paramType.getType(); 260 } 261 262 @property 263 Type type(Type t) { 264 paramType = t.getParamType(ParamKind.Regular); 265 return t; 266 } 267 268 @property 269 bool isRef() const { 270 return paramType.isRef; 271 } 272 273 @property 274 bool isFinal() const { 275 return paramType.isFinal; 276 } 277 278 @property 279 storage() const { 280 return cast(Storage) (__derived & 0x03); 281 } 282 283 @property 284 storage(Storage storage) { 285 __derived = storage; 286 return storage; 287 } 288 289 override string toString(const Context c) const { 290 return type.toString(c) ~ " " ~ name.toString(c) ~ " = " 291 ~ value.toString(c) ~ ";"; 292 } 293 } 294 295 /** 296 * Field 297 * Simply a Variable with a field index. 298 */ 299 class Field : ValueSymbol { 300 CompileTimeExpression value; 301 Type type; 302 303 this(Location location, uint index, Type type, Name name, 304 CompileTimeExpression value = null) { 305 super(location, name); 306 307 this.value = value; 308 this.type = type; 309 this.derived = index; 310 311 // Always true for fields. 312 this.hasThis = true; 313 } 314 315 @property 316 index() const { 317 return derived; 318 } 319 } 320 321 /** 322 * Template 323 */ 324 class Template : ScopeSymbol { 325 TemplateInstance[string] instances; 326 Type[] ifti; 327 328 TemplateParameter[] parameters; 329 330 import d.ast.declaration : Declaration; 331 Declaration[] members; 332 333 this(Location location, Scope parentScope, Name name, 334 TemplateParameter[] parameters, Declaration[] members) { 335 super(location, parentScope, name); 336 337 this.parameters = parameters; 338 this.members = members; 339 } 340 341 @property 342 storage() const { 343 return cast(Storage) (__derived & 0x03); 344 } 345 346 @property 347 storage(Storage storage) { 348 __derived = storage; 349 return storage; 350 } 351 } 352 353 /** 354 * Template type parameter 355 */ 356 class TypeTemplateParameter : TemplateParameter { 357 Type specialization; 358 Type defaultValue; 359 360 this(Location location, Name name, uint index, Type specialization, 361 Type defaultValue) { 362 super(location, name, index); 363 364 this.specialization = specialization; 365 this.defaultValue = defaultValue; 366 } 367 368 override string toString(const Context c) const { 369 return name.toString(c) ~ " : " ~ specialization.toString(c) ~ " = " 370 ~ defaultValue.toString(c); 371 } 372 } 373 374 /** 375 * Template value parameter 376 */ 377 class ValueTemplateParameter : TemplateParameter { 378 Type type; 379 Expression defaultValue; 380 381 this(Location location, Name name, uint index, Type type, 382 Expression defaultValue) { 383 super(location, name, index); 384 385 this.type = type; 386 this.defaultValue = defaultValue; 387 } 388 } 389 390 /** 391 * Template alias parameter 392 */ 393 class AliasTemplateParameter : TemplateParameter { 394 this(Location location, Name name, uint index) { 395 super(location, name, index); 396 } 397 } 398 399 /** 400 * Template typed alias parameter 401 */ 402 class TypedAliasTemplateParameter : TemplateParameter { 403 Type type; 404 405 this(Location location, Name name, uint index, Type type) { 406 super(location, name, index); 407 408 this.type = type; 409 } 410 } 411 412 /** 413 * Template instance 414 */ 415 class TemplateInstance : Symbol, Scope { 416 mixin ScopeImpl!(ScopeType.WithParent, Template); 417 418 TemplateArgument[] args; 419 Symbol[] members; 420 421 this(Location location, Template tpl, TemplateArgument[] args) { 422 super(location, tpl.name); 423 fillParentScope(tpl); 424 425 this.args = args; 426 } 427 428 Template getTemplate() { 429 return getParentScope(); 430 } 431 432 @property 433 storage() const { 434 return cast(Storage) (__derived & 0x03); 435 } 436 437 @property 438 storage(Storage storage) { 439 __derived = storage; 440 return storage; 441 } 442 } 443 444 alias TemplateArgument = 445 Type.UnionType!(typeof(null), Symbol, CompileTimeExpression); 446 447 auto apply(alias undefinedHandler, alias handler)(TemplateArgument a) { 448 alias Tag = typeof(a.tag); 449 final switch (a.tag) with (Tag) { 450 case Undefined: 451 return undefinedHandler(); 452 453 case Symbol: 454 return handler(a.get!Symbol); 455 456 case CompileTimeExpression: 457 return handler(a.get!CompileTimeExpression); 458 459 case Type: 460 return handler(a.get!Type); 461 } 462 } 463 464 unittest { 465 TemplateArgument.init.apply!(() {}, (i) { 466 assert(0); 467 })(); 468 } 469 470 /** 471 * Alias of symbols 472 */ 473 class SymbolAlias : Symbol { 474 Symbol symbol; 475 476 this(Location location, Name name, Symbol symbol) { 477 super(location, name); 478 479 this.symbol = symbol; 480 } 481 482 /+ 483 invariant() { 484 if (step >= Step.Signed) { 485 assert(symbol && hasContext == symbol.hasContext); 486 } 487 } 488 +/ 489 } 490 491 /** 492 * Alias of types 493 */ 494 class TypeAlias : Symbol { 495 Type type; 496 497 this(Location location, Name name, Type type) { 498 super(location, name); 499 500 this.type = type; 501 } 502 } 503 504 /** 505 * Alias of values 506 */ 507 class ValueAlias : ValueSymbol { 508 CompileTimeExpression value; 509 510 this(Location location, Name name, CompileTimeExpression value) { 511 super(location, name); 512 513 this.value = value; 514 } 515 } 516 517 /** 518 * Struct 519 */ 520 class Struct : Aggregate { 521 this(Location location, Scope parentScope, Name name, Symbol[] members) { 522 super(location, parentScope, name, members); 523 } 524 525 // XXX: std.bitmanip should really offer the possibility to create bitfield 526 // out of unused bits of existing bitfields. 527 @property 528 bool hasIndirection() const in { 529 assert(step >= Step.Signed, 530 "Struct need to be signed to use hasIndirection"); 531 } do { 532 return !!(derived & 0x01); 533 } 534 535 @property 536 bool hasIndirection(bool hasIndirection) { 537 if (hasIndirection) { 538 derived = derived | 0x01; 539 } else { 540 derived = derived & ~0x01; 541 } 542 543 return hasIndirection; 544 } 545 546 @property 547 bool isPod() const in { 548 assert(step >= Step.Signed, "Struct need to be signed to use isPod"); 549 } do { 550 return !!(derived & 0x02); 551 } 552 553 @property 554 bool isPod(bool isPod) { 555 if (isPod) { 556 derived = derived | 0x02; 557 } else { 558 derived = derived & ~0x02; 559 } 560 561 return isPod; 562 } 563 564 @property 565 bool isSmall() const in { 566 assert(step >= Step.Signed, "Struct need to be signed to use isSmall"); 567 } do { 568 return !!(derived & 0x04); 569 } 570 571 @property 572 bool isSmall(bool isSmall) { 573 if (isSmall) { 574 derived = derived | 0x04; 575 } else { 576 derived = derived & ~0x04; 577 } 578 579 return isSmall; 580 } 581 } 582 583 /** 584 * Union 585 */ 586 class Union : Aggregate { 587 this(Location location, Scope parentScope, Name name, Symbol[] members) { 588 super(location, parentScope, name, members); 589 } 590 591 @property 592 hasIndirection() const in { 593 assert(step >= Step.Signed, 594 "Union need to be signed to use hasIndirection"); 595 } do { 596 return !!derived; 597 } 598 599 @property 600 hasIndirection(bool hasIndirection) { 601 derived = hasIndirection; 602 return hasIndirection; 603 } 604 } 605 606 /** 607 * Class 608 */ 609 class Class : Aggregate { 610 Class base; 611 Interface[] interfaces; 612 613 this(Location location, Scope parentScope, Name name, Symbol[] members) { 614 super(location, parentScope, name, members); 615 616 this.name = name; 617 } 618 } 619 620 /** 621 * Interface 622 */ 623 class Interface : Aggregate { 624 Interface[] bases; 625 626 this(Location location, Scope parentScope, Name name, Interface[] bases, 627 Symbol[] members) { 628 super(location, parentScope, name, members); 629 this.bases = bases; 630 } 631 } 632 633 /** 634 * Enum 635 */ 636 class Enum : ScopeSymbol { 637 Type type; 638 Variable[] entries; 639 640 this(Location location, Scope parentScope, Name name, Type type, 641 Variable[] entries) { 642 super(location, parentScope, name); 643 644 this.type = type; 645 this.entries = entries; 646 } 647 } 648 649 /** 650 * Virtual method 651 * Simply a function declaration with its index in the vtable. 652 */ 653 class Method : Function { 654 uint index; 655 656 this(Location location, Scope parentScope, uint index, FunctionType type, 657 Name name, Variable[] params) { 658 super(location, parentScope, type, name, params); 659 660 this.index = index; 661 } 662 }