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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
// 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 replaceGetStringHash(IRModule* module, SharedIRBuilder& sharedBuilder, StringSlicePool& ioPool)
{
IRBuilder builder;
builder.sharedBuilder = &sharedBuilder;
builder.setInsertInto(module->getModuleInst());
List<IRGetStringHash*> insts;
_findGetStringHashRec(module->getModuleInst(), insts);
// Then we want to add the GlobalHashedString instruction in the root
for (auto inst : insts)
{
IRStringLit* stringLit = inst->getStringLit();
ioPool.add(stringLit->getStringSlice());
// Okay work out what the hash is
const int hash = GetHashCode(stringLit->getStringSlice());
IRInst* intLit = builder.getIntValue(builder.getIntType(), int32_t(hash));
// Okay we want to replace all uses with the literal
inst->replaceUsesWith(intLit);
inst->removeAndDeallocate();
}
}
void replaceGetStringHashWithGlobal(IRModule* module, SharedIRBuilder& sharedBuilder)
{
StringSlicePool pool(StringSlicePool::Style::Empty);
replaceGetStringHash(module, sharedBuilder, pool);
addGlobalHashedStringLiterals(pool, sharedBuilder);
}
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;
builder.sharedBuilder = &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();
IRInst* globalHashedInst = createEmptyInst(module, 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);
}
}
|