summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-ir-string-hash.cpp
blob: 8ff0ec7564c872257a517a0e70e153f6097c6f3f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// slang-ir-string-hash.cpp
#include "slang-ir-string-hash.h"

#include "slang-ir.h"
#include "slang-ir-insts.h"

namespace Slang {

static void _findGetStringHashRec(IRInst* inst, List<IRGetStringHash*>& outInsts)
{
    for (IRInst* child = inst->getFirstDecorationOrChild(); child; child = child->getNextInst())
    {
        if (IRGetStringHash* getInst = as<IRGetStringHash>(child))
        {
            outInsts.add(getInst);
        }
        _findGetStringHashRec(child, outInsts);
    }
}

void findGlobalHashedStringLiterals(IRModule* module, StringSlicePool& pool)
{
    IRModuleInst* moduleInst = module->getModuleInst();

    for(IRInst* child : moduleInst->getChildren())
    {
        if (IRGlobalHashedStringLiterals* hashedStringLits = as<IRGlobalHashedStringLiterals>(child))
        {
            const Index count = hashedStringLits->getOperandCount();
            for (Index i = 0; i < count; ++i)
            {
                IRStringLit* stringLit = as<IRStringLit>(hashedStringLits->getOperand(i));
                pool.add(stringLit->getStringSlice());
            }
        }
    }
}

void addGlobalHashedStringLiterals(const StringSlicePool& pool, SharedIRBuilder& sharedBuilder)
{
    auto slices = pool.getAdded();
    if (slices.getCount() == 0)
    {
        return;
    }

    IRBuilder builder(sharedBuilder);
    
    // 
    IRModule* module = builder.getModule();

    // We need to add a global instruction that references all of these string literals
    builder.setInsertInto(module->getModuleInst());

    const Index slicesCount = slices.getCount();

    // Note: This pass is using the extremely low-level `_allocateInst` operation on `IRModule`
    // as an optimization. By allocating the instruction here in an "empty" state and then filling
    // its operands in in place, we can avoid allocating space for a temporary `List<IRInst*>` to
    // hold the IR string values created in the loop below.
    //
    // TODO: We should probably either eliminate this micro-optimization and just use a `List<IRInst*>`
    // here, *or* we should devise a more first-class system for doing in-place instruction creation
    // like that that can be compatible with desirable features like automatic deduplication.
    //
    IRInst* globalHashedInst = module->_allocateInst(kIROp_GlobalHashedStringLiterals, int(slicesCount));
    builder.addInst(globalHashedInst);

    auto operands = globalHashedInst->getOperands();

    for (Index i = 0; i < slicesCount; ++i)
    {
        IRStringLit* stringLit = builder.getStringValue(slices[i]);
        operands[i].init(globalHashedInst, stringLit);
    }

    // Mark to keep alive
    builder.addKeepAliveDecoration(globalHashedInst);
}

}