|
2 | 2 | #include "emit.h"
|
3 | 3 |
|
4 | 4 | #include "../core/slang-writer.h"
|
| 5 | +#include "ir-dce.h" |
5 | 6 | #include "ir-insts.h"
|
6 | 7 | #include "ir-restructure.h"
|
7 | 8 | #include "ir-restructure-scoping.h"
|
| 9 | +#include "ir-specialize-resources.h" |
8 | 10 | #include "ir-ssa.h"
|
9 | 11 | #include "ir-validate.h"
|
10 | 12 | #include "legalize-types.h"
|
@@ -5603,21 +5605,56 @@ struct EmitVisitor
|
5603 | 5605 | emit("}\n");
|
5604 | 5606 | }
|
5605 | 5607 |
|
| 5608 | + /// Emit the array brackets that go on the end of a declaration of the given type. |
5606 | 5609 | void emitArrayBrackets(
|
5607 | 5610 | EmitContext* ctx,
|
5608 |
| - IRType* type) |
| 5611 | + IRType* inType) |
5609 | 5612 | {
|
5610 | 5613 | SLANG_UNUSED(ctx);
|
5611 | 5614 |
|
5612 |
| - if(auto arrayType = as<IRArrayType>(type)) |
5613 |
| - { |
5614 |
| - emit("["); |
5615 |
| - EmitVal(arrayType->getElementCount(), kEOp_General); |
5616 |
| - emit("]"); |
5617 |
| - } |
5618 |
| - else if(auto unsizedArrayType = as<IRUnsizedArrayType>(type)) |
| 5615 | + // A declaration may require zero, one, or |
| 5616 | + // more array brackets. When writing out array |
| 5617 | + // brackets from left to right, they represent |
| 5618 | + // the structure of the type from the "outside" |
| 5619 | + // in (that is, if we have a 5-element array of |
| 5620 | + // 3-element arrays we should output `[5][3]`), |
| 5621 | + // because of C-style declarator rules. |
| 5622 | + // |
| 5623 | + // This conveniently means that we can print |
| 5624 | + // out all the array brackets with a looping |
| 5625 | + // rather than a recursive structure. |
| 5626 | + // |
| 5627 | + // We will peel the input type like an onion, |
| 5628 | + // looking at one layer at a time until we |
| 5629 | + // reach a non-array type in the middle. |
| 5630 | + // |
| 5631 | + IRType* type = inType; |
| 5632 | + for(;;) |
5619 | 5633 | {
|
5620 |
| - emit("[]"); |
| 5634 | + if(auto arrayType = as<IRArrayType>(type)) |
| 5635 | + { |
| 5636 | + emit("["); |
| 5637 | + EmitVal(arrayType->getElementCount(), kEOp_General); |
| 5638 | + emit("]"); |
| 5639 | + |
| 5640 | + // Continue looping on the next layer in. |
| 5641 | + // |
| 5642 | + type = arrayType->getElementType(); |
| 5643 | + } |
| 5644 | + else if(auto unsizedArrayType = as<IRUnsizedArrayType>(type)) |
| 5645 | + { |
| 5646 | + emit("[]"); |
| 5647 | + |
| 5648 | + // Continue looping on the next layer in. |
| 5649 | + // |
| 5650 | + type = unsizedArrayType->getElementType(); |
| 5651 | + } |
| 5652 | + else |
| 5653 | + { |
| 5654 | + // This layer wasn't an array, so we are done. |
| 5655 | + // |
| 5656 | + return; |
| 5657 | + } |
5621 | 5658 | }
|
5622 | 5659 | }
|
5623 | 5660 |
|
@@ -5752,16 +5789,6 @@ struct EmitVisitor
|
5752 | 5789 | emit(";\n");
|
5753 | 5790 | }
|
5754 | 5791 |
|
5755 |
| - IRType* unwrapArray(IRType* type) |
5756 |
| - { |
5757 |
| - IRType* t = type; |
5758 |
| - while( auto arrayType = as<IRArrayTypeBase>(t) ) |
5759 |
| - { |
5760 |
| - t = arrayType->getElementType(); |
5761 |
| - } |
5762 |
| - return t; |
5763 |
| - } |
5764 |
| - |
5765 | 5792 | void emitIRStructuredBuffer_GLSL(
|
5766 | 5793 | EmitContext* ctx,
|
5767 | 5794 | IRGlobalParam* varDecl,
|
@@ -6546,6 +6573,46 @@ String emitEntryPoint(
|
6546 | 6573 | #endif
|
6547 | 6574 | validateIRModuleIfEnabled(compileRequest, irModule);
|
6548 | 6575 |
|
| 6576 | + // After type legalization and subsequent SSA cleanup we expect |
| 6577 | + // that any resource types passed to functions are exposed |
| 6578 | + // as their own top-level parameters (which might have |
| 6579 | + // resource or array-of-...-resource types). |
| 6580 | + // |
| 6581 | + // Many of our targets place restrictions on how certain |
| 6582 | + // resource types can be used, so that having them as |
| 6583 | + // function parameters is invalid. To clean this up, |
| 6584 | + // we will try to specialize called functions based |
| 6585 | + // on the actual resources that are being passed to them |
| 6586 | + // at specific call sites. |
| 6587 | + // |
| 6588 | + // Because the legalization may depend on what target |
| 6589 | + // we are compiling for (certain things might be okay |
| 6590 | + // for D3D targets that are not okay for Vulkan), we |
| 6591 | + // pass down the target request along with the IR. |
| 6592 | + // |
| 6593 | + specializeResourceParameters(compileRequest, targetRequest, irModule); |
| 6594 | + |
| 6595 | +#if 0 |
| 6596 | + dumpIRIfEnabled(compileRequest, irModule, "AFTER RESOURCE SPECIALIZATION"); |
| 6597 | +#endif |
| 6598 | + validateIRModuleIfEnabled(compileRequest, irModule); |
| 6599 | + |
| 6600 | + // The resource-based specialization pass above |
| 6601 | + // may create specialized versions of functions, but |
| 6602 | + // it does not try to completely eliminate the original |
| 6603 | + // functions, so there might still be invalid code in |
| 6604 | + // our IR module. |
| 6605 | + // |
| 6606 | + // To clean up the code, we will apply a fairly general |
| 6607 | + // dead-code-elimination (DCE) pass that only retains |
| 6608 | + // whatever code is "live." |
| 6609 | + // |
| 6610 | + eliminateDeadCode(compileRequest, irModule); |
| 6611 | +#if 0 |
| 6612 | + dumpIRIfEnabled(compileRequest, irModule, "AFTER DCE"); |
| 6613 | +#endif |
| 6614 | + validateIRModuleIfEnabled(compileRequest, irModule); |
| 6615 | + |
6549 | 6616 | // After all of the required optimization and legalization
|
6550 | 6617 | // passes have been performed, we can emit target code from
|
6551 | 6618 | // the IR module.
|
|
0 commit comments