diff options
| author | Tim Foley <tfoleyNV@users.noreply.github.com> | 2018-12-13 12:13:58 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-12-13 12:13:58 -0800 |
| commit | 822ed708364b257b7d2f61ecb8a51a4c96f7edaa (patch) | |
| tree | 4ba9e463875dbad0009ffbba0be1336df3030271 /tests/ir | |
| parent | 76280cfc114e489f4b596dc2b0e2a560b7f13a55 (diff) | |
Move mangled name out of IRGlobalValue (#752)
* Move mangled name out of IRGlobalValue
Previously the `IRGlobalValue` type was used as a root for all IR instructions that can have "linkage," in the sense that a definition in one module can satisfy a use in another module.
The mangled symbol name was stored in state directly on each `IRGlobalValue`, which created some complications, and also forced IR instructions that wanted to support linkage to wedge into the hierarchy at that specific point.
This change moves the mangled name out into a decoration: either an `IRImportDecoration` or an `IRExportDecoration`, both of which inherit from `IRLinkageDecoration` which exposes the mangled name.
This change has a few benefits:
* We can now have any kind of instruction be exported/imported, without having to inherit from `IRGlobalValue`. This could potentially let `IRStructType` and `IRWitnessTable` be simplified to just have operand lists instead of dummy chldren as they do today.
* We can now easily have "global values" like functions that explicitly *don't* get linkage, instead of using a null or empty mangled name as a marker.
* We can use the exact opcode on a linkage decoration to distinguish imports from exports, which could be used to more accurately resolve symbols during the linking step.
Other than adding the decorations and making sure that AST->IR lowering adds them, the main changes here are around any code that used `IRGlobalValue`. Variables and parameters of type `IRGlobalValue*` were changed to `IRInst*` easily, so the main challenge was around code that *casts* to `IRGlobalValue*.
In cases where a cast to `IRGlobalValue` also performed a test for the mangled name being non-null/non-empty, we simply switched the code to check for the presence of an `IRLinkageDecoration`, since that is the new way of indicating a value with linakge.
Most of the serious complications arose in `ir.cpp` around the "linking"/target-specialization and generic specialization steps.
The "linking" logic was checking for `IRGlobalValue` to opt into some more complicated cloning logic, and just checking for a linkage decoration here wasn't sufficient since the front-end *does* produce global values without linkage in some cases (e.g., for a function-`static` variable we produce a global variable without linkage). This logic was updated to just check for the cases that used to amount to `IRGlobalValue`s directly by opcode. It might be simpler in the short term to have kept `IRGlobalValue` around to make the existing casts Just Work, but I'm confident that this logic could actually be rewritten for much greater clarity and simplicity and that is the better way forward.
The generic specialization logic was using some really messy code to generate a new mangled name to represent the specialized symbol, and then searching for an existing match for that name.
The original idea there was that an IR module could include "pre-specialized" versions of certain generics to speed up back-end compilation by eliminating the need to specialize in some cases, but this feature has never been implemented so the overhead here is just a waste.
Instead, I moved generic specialization to use a simpler dictionary to map the operands to a `specialize` instruction over to the resulting specialized value.
This allows for some simplifications in the name mangling logic, because it no longer needs to figure out how to produce mangled names from IR instructions representing types/values.
As part of this change I also overhauled the IR emit logic to produce cleaner output by default, borrowing some of the ideas from the logic in `emit.cpp`. IR values are now automatically given names based on their "name hint" decoration, if any, to make the code easier to follow, and I also made it so that types and literals get collapsed into their use sites in a new "simplified" IR dump mode (which is currently the default, with no way to opt into the other mode without tweaking the code). The resulting IR dumps are much nicer to look at, but as a result the one test that involves IR dumping (`ir/string-literal`) doesn't really test what it used to.
One weird issue that came up during testing is that the `transitive-interface` test had previously been producing output that made no sense (that is, the expected output file wasn't really sensible), and somehow these changes were altering its behavior. Changing the test to use `int` values instead of `float` was enough to make the output be what I'd expect, and hand inspection of generating DXBC has me convinced we were compiling the `float` case correctly too. There appears to be some issue around tests with floating-point outputs that we should investigate.
* fixup: C++ declaration order
Diffstat (limited to 'tests/ir')
| -rw-r--r-- | tests/ir/string-literal.slang.expected | 25 |
1 files changed, 6 insertions, 19 deletions
diff --git a/tests/ir/string-literal.slang.expected b/tests/ir/string-literal.slang.expected index 4503cb74a..7bc66d682 100644 --- a/tests/ir/string-literal.slang.expected +++ b/tests/ir/string-literal.slang.expected @@ -1,27 +1,14 @@ result code = 0 standard error = { -let %1 : _ = String() -let %2 : %1 = string_constant("main") -let %3 : _ = Void() -let %4 : _ = UInt() -let %5 : _ = Func(%3, %4) -let %6 : _ = BasicBlock() -let %7 : _ = Ptr(%3) -let %8 : %7 = ptr_constant() -let %9 : %1 = string_constant("tid") -Ptr(%4) -let %10 : %1 = string_constant("Hello \t\n\0x083 World") -let %11 : %7 = ptr_constant() -[highLevelDecl(%11)] +[export("_S04mainp1puV")] [nameHint("main")] -func @_S04mainp1puV : %5 +func %main : Func(Void, UInt) { -block %12( - param %13 : %4): - return_void() +block %1( + [nameHint("tid")] + param %tid : UInt): + return_void } - - } standard output = { } |
