Coverage Report

Created: 2026-05-30 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/glslang/glslang/MachineIndependent/SymbolTable.cpp
Line
Count
Source
1
//
2
// Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
3
// Copyright (C) 2012-2013 LunarG, Inc.
4
// Copyright (C) 2017 ARM Limited.
5
// Copyright (C) 2015-2018 Google, Inc.
6
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
7
//
8
// All rights reserved.
9
//
10
// Redistribution and use in source and binary forms, with or without
11
// modification, are permitted provided that the following conditions
12
// are met:
13
//
14
//    Redistributions of source code must retain the above copyright
15
//    notice, this list of conditions and the following disclaimer.
16
//
17
//    Redistributions in binary form must reproduce the above
18
//    copyright notice, this list of conditions and the following
19
//    disclaimer in the documentation and/or other materials provided
20
//    with the distribution.
21
//
22
//    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
23
//    contributors may be used to endorse or promote products derived
24
//    from this software without specific prior written permission.
25
//
26
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
29
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
30
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
32
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
34
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
36
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37
// POSSIBILITY OF SUCH DAMAGE.
38
//
39
40
//
41
// Symbol table for parsing.  Most functionality and main ideas
42
// are documented in the header file.
43
//
44
45
#include "SymbolTable.h"
46
47
namespace glslang {
48
49
//
50
// TType helper function needs a place to live.
51
//
52
53
//
54
// Recursively generate mangled names.
55
//
56
void TType::buildMangledName(TString& mangledName) const
57
2.00M
{
58
2.00M
    if (isTensorARM())
59
1.64k
        mangledName += 'T';
60
2.00M
    else if (isMatrix())
61
417k
        mangledName += 'm';
62
1.58M
    else if (isVector())
63
677k
        mangledName += 'v';
64
65
2.00M
    if (isCoopVecNV())
66
21.2k
        mangledName += "coopvec";
67
68
2.00M
    switch (basicType) {
69
594k
    case EbtFloat:              mangledName += 'f';      break;
70
483k
    case EbtInt:                mangledName += 'i';      break;
71
316k
    case EbtUint:               mangledName += 'u';      break;
72
28.2k
    case EbtBool:               mangledName += 'b';      break;
73
48.4k
    case EbtDouble:             mangledName += 'd';      break;
74
77.8k
    case EbtFloat16:            mangledName += "f16";    break;
75
864
    case EbtBFloat16:           mangledName += "bf16";   break;
76
648
    case EbtFloatE5M2:          mangledName += "fe5m2";  break;
77
648
    case EbtFloatE4M3:          mangledName += "fe4m3";  break;
78
14.7k
    case EbtInt8:               mangledName += "i8";     break;
79
14.2k
    case EbtUint8:              mangledName += "u8";     break;
80
19.1k
    case EbtInt16:              mangledName += "i16";    break;
81
17.9k
    case EbtUint16:             mangledName += "u16";    break;
82
24.1k
    case EbtInt64:              mangledName += "i64";    break;
83
36.1k
    case EbtUint64:             mangledName += "u64";    break;
84
144
    case EbtAtomicUint:         mangledName += "au";     break;
85
0
    case EbtAccStruct:          mangledName += "as";     break;
86
0
    case EbtRayQuery:           mangledName += "rq";     break;
87
0
    case EbtSpirvType:          mangledName += "spv-t";  break;
88
0
    case EbtHitObjectNV:        mangledName += "ho";     break;
89
0
    case EbtHitObjectEXT:       mangledName += "ho";     break;
90
999
    case EbtTensorLayoutNV:     mangledName += "tl";     break;
91
513
    case EbtTensorViewNV:       mangledName += "tv";     break;
92
289k
    case EbtSampler:
93
289k
        switch (sampler.type) {
94
44.2k
        case EbtFloat16: mangledName += "f16"; break;
95
51.1k
        case EbtInt:   mangledName += "i"; break;
96
51.1k
        case EbtUint:  mangledName += "u"; break;
97
7.02k
        case EbtInt64:   mangledName += "i64"; break;
98
7.02k
        case EbtUint64:  mangledName += "u64"; break;
99
128k
        default: break; // some compilers want this
100
289k
        }
101
289k
        if (sampler.isImageClass())
102
50.7k
            mangledName += "I";  // a normal image or subpass
103
238k
        else if (sampler.isPureSampler())
104
68.6k
            mangledName += "p";  // a "pure" sampler
105
169k
        else if (!sampler.isCombined())
106
83.9k
            mangledName += "t";  // a "pure" texture
107
85.7k
        else
108
85.7k
            mangledName += "s";  // traditional combined sampler
109
289k
        if (sampler.isArrayed())
110
84.3k
            mangledName += "A";
111
289k
        if (sampler.isShadow())
112
43.5k
            mangledName += "S";
113
289k
        if (sampler.isExternal())
114
106
            mangledName += "E";
115
289k
        if (sampler.isYuv())
116
256
            mangledName += "Y";
117
289k
        switch (sampler.dim) {
118
104k
        case Esd2D:       mangledName += "2";  break;
119
19.3k
        case Esd3D:       mangledName += "3";  break;
120
36.8k
        case EsdCube:     mangledName += "C";  break;
121
38.4k
        case Esd1D:       mangledName += "1";  break;
122
13.3k
        case EsdRect:     mangledName += "R2"; break;
123
5.10k
        case EsdBuffer:   mangledName += "B";  break;
124
2.64k
        case EsdSubpass:  mangledName += "P";  break;
125
68.6k
        default: break; // some compilers want this
126
289k
        }
127
128
289k
#ifdef ENABLE_HLSL
129
289k
        if (sampler.hasReturnStruct()) {
130
            // Name mangle for sampler return struct uses struct table index.
131
0
            mangledName += "-tx-struct";
132
133
0
            char text[16]; // plenty enough space for the small integers.
134
0
            snprintf(text, sizeof(text), "%u-", sampler.getStructReturnIndex());
135
0
            mangledName += text;
136
289k
        } else {
137
289k
            switch (sampler.getVectorSize()) {
138
17.1k
            case 1: mangledName += "1"; break;
139
50.1k
            case 2: mangledName += "2"; break;
140
6.93k
            case 3: mangledName += "3"; break;
141
214k
            case 4: break; // default to prior name mangle behavior
142
289k
            }
143
289k
        }
144
289k
#endif
145
146
289k
        if (sampler.isMultiSample())
147
13.9k
            mangledName += "M";
148
289k
        break;
149
324
    case EbtStruct:
150
324
    case EbtBlock:
151
324
        if (basicType == EbtStruct)
152
324
            mangledName += "struct-";
153
0
        else
154
0
            mangledName += "block-";
155
324
        if (typeName)
156
324
            mangledName += *typeName;
157
1.94k
        for (unsigned int i = 0; i < structure->size(); ++i) {
158
1.62k
            if ((*structure)[i].type->getBasicType() == EbtVoid)
159
0
                continue;
160
1.62k
            mangledName += '-';
161
1.62k
            (*structure)[i].type->buildMangledName(mangledName);
162
1.62k
        }
163
324
        break;
164
38.3k
    default:
165
38.3k
        break;
166
2.00M
    }
167
168
2.00M
    if (getVectorSize() > 0)
169
1.59M
        mangledName += static_cast<char>('0' + getVectorSize());
170
417k
    else {
171
417k
        mangledName += static_cast<char>('0' + getMatrixCols());
172
417k
        mangledName += static_cast<char>('0' + getMatrixRows());
173
417k
    }
174
175
2.00M
    if (typeParameters) {
176
0
        const int maxSize = 11;
177
0
        char buf[maxSize];
178
0
        for (int i = 0; i < typeParameters->arraySizes->getNumDims(); ++i) {
179
0
            if (typeParameters->arraySizes->getDimNode(i)) {
180
0
                if (typeParameters->arraySizes->getDimNode(i)->getAsSymbolNode())
181
0
                    snprintf(buf, maxSize, "s%lld", typeParameters->arraySizes->getDimNode(i)->getAsSymbolNode()->getId());
182
0
                else
183
0
                    snprintf(buf, maxSize, "s%p", typeParameters->arraySizes->getDimNode(i));
184
0
            } else
185
0
                snprintf(buf, maxSize, "%d", typeParameters->arraySizes->getDimSize(i));
186
0
            mangledName += '<';
187
0
            mangledName += buf;
188
0
            mangledName += '>';
189
0
        }
190
0
    }
191
192
2.00M
    if (arraySizes) {
193
37.2k
        const int maxSize = 11;
194
37.2k
        char buf[maxSize];
195
74.5k
        for (int i = 0; i < arraySizes->getNumDims(); ++i) {
196
37.2k
            if (arraySizes->getDimNode(i)) {
197
0
                if (arraySizes->getDimNode(i)->getAsSymbolNode())
198
0
                    snprintf(buf, maxSize, "s%lld", arraySizes->getDimNode(i)->getAsSymbolNode()->getId());
199
0
                else
200
0
                    snprintf(buf, maxSize, "s%p", (void*)(arraySizes->getDimNode(i)));
201
0
            } else
202
37.2k
                snprintf(buf, maxSize, "%d", arraySizes->getDimSize(i));
203
37.2k
            mangledName += '[';
204
37.2k
            mangledName += buf;
205
37.2k
            mangledName += ']';
206
37.2k
        }
207
37.2k
    }
208
2.00M
}
209
210
//
211
// Dump functions.
212
//
213
214
void TSymbol::dumpExtensions(TInfoSink& infoSink) const
215
404k
{
216
404k
    int numExtensions = getNumExtensions();
217
404k
    if (numExtensions) {
218
45.1k
        infoSink.debug << " <";
219
220
90.3k
        for (int i = 0; i < numExtensions; i++)
221
45.1k
            infoSink.debug << getExtensions()[i] << ",";
222
223
45.1k
        infoSink.debug << ">";
224
45.1k
    }
225
404k
}
226
227
void TVariable::dump(TInfoSink& infoSink, bool complete) const
228
1.60k
{
229
1.60k
    if (complete) {
230
1.60k
        infoSink.debug << getName().c_str() << ": " << type.getCompleteString();
231
1.60k
        dumpExtensions(infoSink);
232
1.60k
    } else {
233
0
        infoSink.debug << getName().c_str() << ": " << type.getStorageQualifierString() << " "
234
0
                       << type.getBasicTypeString();
235
236
0
        if (type.isArray())
237
0
            infoSink.debug << "[0]";
238
0
    }
239
240
1.60k
    infoSink.debug << "\n";
241
1.60k
}
242
243
void TFunction::dump(TInfoSink& infoSink, bool complete) const
244
402k
{
245
402k
    if (complete) {
246
402k
        infoSink.debug << getName().c_str() << ": " << returnType.getCompleteString() << " " << getName().c_str()
247
402k
                       << "(";
248
249
402k
        int numParams = getParamCount();
250
1.36M
        for (int i = 0; i < numParams; i++) {
251
957k
            const TParameter &param = parameters[i];
252
957k
            infoSink.debug << param.type->getCompleteString() << " "
253
957k
                           << (param.type->isStruct() ? "of " + param.type->getTypeName() + " " : "")
254
957k
                           << (param.name ? *param.name : "") << (i < numParams - 1 ? "," : "");
255
957k
        }
256
257
402k
        infoSink.debug << ")";
258
402k
        dumpExtensions(infoSink);
259
402k
    } else {
260
0
        infoSink.debug << getName().c_str() << ": " << returnType.getBasicTypeString() << " "
261
0
                       << getMangledName().c_str() << "n";
262
0
    }
263
264
402k
    infoSink.debug << "\n";
265
402k
}
266
267
void TAnonMember::dump(TInfoSink& TInfoSink, bool) const
268
32
{
269
32
    TInfoSink.debug << "anonymous member " << getMemberNumber() << " of " << getAnonContainer().getName().c_str()
270
32
                    << "\n";
271
32
}
272
273
void TSymbolTableLevel::dump(TInfoSink& infoSink, bool complete) const
274
291
{
275
291
    tLevel::const_iterator it;
276
404k
    for (it = level.begin(); it != level.end(); ++it)
277
404k
        (*it).second->dump(infoSink, complete);
278
291
}
279
280
void TSymbolTable::dump(TInfoSink& infoSink, bool complete) const
281
97
{
282
388
    for (int level = currentLevel(); level >= 0; --level) {
283
291
        infoSink.debug << "LEVEL " << level << "\n";
284
291
        table[level]->dump(infoSink, complete);
285
291
    }
286
97
}
287
288
//
289
// Functions have buried pointers to delete.
290
//
291
TFunction::~TFunction()
292
1.38M
{
293
4.80M
    for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i)
294
3.41M
        delete (*i).type;
295
1.38M
}
296
297
//
298
// Symbol table levels are a map of pointers to symbols that have to be deleted.
299
//
300
TSymbolTableLevel::~TSymbolTableLevel()
301
4.54k
{
302
1.41M
    for (tLevel::iterator it = level.begin(); it != level.end(); ++it) {
303
1.40M
        const TString& name = it->first;
304
1.40M
        auto retargetIter = std::find_if(retargetedSymbols.begin(), retargetedSymbols.end(),
305
1.40M
                                      [&name](const std::pair<TString, TString>& i) { return i.first == name; });
306
1.40M
        if (retargetIter == retargetedSymbols.end())
307
1.40M
            delete (*it).second;
308
1.40M
    }
309
310
311
4.54k
    delete [] defaultPrecision;
312
4.54k
}
313
314
//
315
// Change all function entries in the table with the non-mangled name
316
// to be related to the provided built-in operation.
317
//
318
void TSymbolTableLevel::relateToOperator(const char* name, TOperator op)
319
941k
{
320
941k
    tLevel::const_iterator candidate = level.lower_bound(name);
321
10.8M
    while (candidate != level.end()) {
322
10.4M
        const TString& candidateName = (*candidate).first;
323
10.4M
        TString::size_type parenAt = candidateName.find_first_of('(');
324
10.4M
        if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0) {
325
9.87M
            TFunction* function = (*candidate).second->getAsFunction();
326
9.87M
            function->relateToOperator(op);
327
9.87M
        } else
328
554k
            break;
329
9.87M
        ++candidate;
330
9.87M
    }
331
941k
}
332
333
// Make all function overloads of the given name require an extension(s).
334
// Should only be used for a version/profile that actually needs the extension(s).
335
void TSymbolTableLevel::setFunctionExtensions(const char* name, int num, const char* const extensions[])
336
15.5k
{
337
15.5k
    tLevel::const_iterator candidate = level.lower_bound(name);
338
104k
    while (candidate != level.end()) {
339
101k
        const TString& candidateName = (*candidate).first;
340
101k
        TString::size_type parenAt = candidateName.find_first_of('(');
341
101k
        if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0) {
342
88.5k
            TSymbol* symbol = candidate->second;
343
88.5k
            symbol->setExtensions(num, extensions);
344
88.5k
        } else
345
13.3k
            break;
346
88.5k
        ++candidate;
347
88.5k
    }
348
15.5k
}
349
350
// Call the callback function to determine the required extensions
351
void TSymbolTableLevel::setFunctionExtensionsCallback(const char* name, std::function<std::vector<const char *>(const char *)> const &func)
352
540
{
353
540
    tLevel::const_iterator candidate = level.lower_bound(name);
354
18.5k
    while (candidate != level.end()) {
355
18.5k
        const TString& candidateName = (*candidate).first;
356
18.5k
        TString::size_type parenAt = candidateName.find_first_of('(');
357
18.5k
        if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0) {
358
18.0k
            TSymbol* symbol = candidate->second;
359
360
18.0k
            auto exts = func(candidateName.c_str());
361
18.0k
            symbol->setExtensions(exts.size(), exts.data());
362
18.0k
        } else
363
540
            break;
364
18.0k
        ++candidate;
365
18.0k
    }
366
540
}
367
368
// Make a single function require an extension(s). i.e., this will only set the extensions for the symbol that matches 'name' exactly.
369
// This is different from setFunctionExtensions, which uses std::map::lower_bound to effectively set all symbols that start with 'name'.
370
// Should only be used for a version/profile that actually needs the extension(s).
371
void TSymbolTableLevel::setSingleFunctionExtensions(const char* name, int num, const char* const extensions[])
372
0
{
373
0
    if (auto candidate = level.find(name); candidate != level.end()) {
374
0
        candidate->second->setExtensions(num, extensions);
375
0
    }
376
0
}
377
378
//
379
// Make all symbols in this table level read only.
380
//
381
void TSymbolTableLevel::readOnly()
382
3.62k
{
383
8.39M
    for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
384
8.38M
        (*it).second->makeReadOnly();
385
3.62k
}
386
387
//
388
// Copy a symbol, but the copy is writable; call readOnly() afterward if that's not desired.
389
//
390
TSymbol::TSymbol(const TSymbol& copyOf)
391
597k
{
392
597k
    name = NewPoolTString(copyOf.name->c_str());
393
597k
    mangledName = NewPoolTString(copyOf.mangledName->c_str());
394
597k
    uniqueId = copyOf.uniqueId;
395
597k
    writable = true;
396
597k
}
397
398
7.22k
TVariable::TVariable(const TVariable& copyOf) : TSymbol(copyOf)
399
7.22k
{
400
7.22k
    type.deepCopy(copyOf.type);
401
7.22k
    userType = copyOf.userType;
402
403
    // we don't support specialization-constant subtrees in cloned tables, only extensions
404
7.22k
    constSubtree = nullptr;
405
7.22k
    extensions = nullptr;
406
7.22k
    memberExtensions = nullptr;
407
7.22k
    if (copyOf.getNumExtensions() > 0)
408
3.65k
        setExtensions(copyOf.getNumExtensions(), copyOf.getExtensions());
409
7.22k
    if (copyOf.hasMemberExtensions()) {
410
516
        for (int m = 0; m < (int)copyOf.type.getStruct()->size(); ++m) {
411
444
            if (copyOf.getNumMemberExtensions(m) > 0)
412
348
                setMemberExtensions(m, copyOf.getNumMemberExtensions(m), copyOf.getMemberExtensions(m));
413
444
        }
414
72
    }
415
416
7.22k
    if (! copyOf.constArray.empty()) {
417
1.35k
        assert(! copyOf.type.isStruct());
418
1.35k
        TConstUnionArray newArray(copyOf.constArray, 0, copyOf.constArray.size());
419
1.35k
        constArray = newArray;
420
1.35k
    }
421
7.22k
}
422
423
TVariable* TVariable::clone() const
424
7.22k
{
425
7.22k
    TVariable *variable = new TVariable(*this);
426
427
7.22k
    return variable;
428
7.22k
}
429
430
590k
TFunction::TFunction(const TFunction& copyOf) : TSymbol(copyOf)
431
590k
{
432
2.02M
    for (unsigned int i = 0; i < copyOf.parameters.size(); ++i) {
433
1.43M
        TParameter param{};
434
1.43M
        parameters.push_back(param);
435
1.43M
        (void)parameters.back().copyParam(copyOf.parameters[i]);
436
1.43M
    }
437
438
590k
    extensions = nullptr;
439
590k
    if (copyOf.getNumExtensions() > 0)
440
74.9k
        setExtensions(copyOf.getNumExtensions(), copyOf.getExtensions());
441
590k
    returnType.deepCopy(copyOf.returnType);
442
590k
    mangledName = copyOf.mangledName;
443
590k
    op = copyOf.op;
444
590k
    defined = copyOf.defined;
445
590k
    prototyped = copyOf.prototyped;
446
590k
    implicitThis = copyOf.implicitThis;
447
590k
    variadic = copyOf.variadic;
448
590k
    illegalImplicitThis = copyOf.illegalImplicitThis;
449
590k
    defaultParamCount = copyOf.defaultParamCount;
450
590k
    spirvInst = copyOf.spirvInst;
451
590k
}
452
453
TFunction* TFunction::clone() const
454
590k
{
455
590k
    TFunction *function = new TFunction(*this);
456
457
590k
    return function;
458
590k
}
459
460
TAnonMember* TAnonMember::clone() const
461
0
{
462
    // Anonymous members of a given block should be cloned at a higher level,
463
    // where they can all be assured to still end up pointing to a single
464
    // copy of the original container.
465
0
    assert(0);
466
467
0
    return nullptr;
468
0
}
469
470
TSymbolTableLevel* TSymbolTableLevel::clone() const
471
1.89k
{
472
1.89k
    TSymbolTableLevel *symTableLevel = new TSymbolTableLevel();
473
1.89k
    symTableLevel->anonId = anonId;
474
1.89k
    symTableLevel->thisLevel = thisLevel;
475
1.89k
    symTableLevel->retargetedSymbols.clear();
476
1.89k
    for (auto &s : retargetedSymbols) {
477
0
        symTableLevel->retargetedSymbols.push_back({s.first, s.second});
478
0
    }
479
1.89k
    std::vector<bool> containerCopied(anonId, false);
480
1.89k
    tLevel::const_iterator iter;
481
599k
    for (iter = level.begin(); iter != level.end(); ++iter) {
482
597k
        const TAnonMember* anon = iter->second->getAsAnonMember();
483
597k
        if (anon) {
484
            // Insert all the anonymous members of this same container at once,
485
            // avoid inserting the remaining members in the future, once this has been done,
486
            // allowing them to all be part of the same new container.
487
144
            if (! containerCopied[anon->getAnonId()]) {
488
36
                TVariable* container = anon->getAnonContainer().clone();
489
36
                container->changeName(NewPoolTString(""));
490
                // insert the container and all its members
491
36
                symTableLevel->insert(*container, false);
492
36
                containerCopied[anon->getAnonId()] = true;
493
36
            }
494
597k
        } else {
495
597k
            const TString& name = iter->first;
496
597k
            auto retargetIter = std::find_if(retargetedSymbols.begin(), retargetedSymbols.end(),
497
597k
                                          [&name](const std::pair<TString, TString>& i) { return i.first == name; });
498
597k
            if (retargetIter != retargetedSymbols.end())
499
0
                continue;
500
597k
            symTableLevel->insert(*iter->second->clone(), false);
501
597k
        }
502
597k
    }
503
    // Now point retargeted symbols to the newly created versions of them
504
1.89k
    for (auto &s : retargetedSymbols) {
505
0
        TSymbol* sym = symTableLevel->find(s.second);
506
0
        if (!sym)
507
0
            continue;
508
0
        symTableLevel->insert(s.first, sym);
509
0
    }
510
511
1.89k
    return symTableLevel;
512
1.89k
}
513
514
void TSymbolTable::copyTable(const TSymbolTable& copyOf)
515
1.89k
{
516
1.89k
    assert(adoptedLevels == copyOf.adoptedLevels);
517
518
1.89k
    uniqueId = copyOf.uniqueId;
519
1.89k
    noBuiltInRedeclarations = copyOf.noBuiltInRedeclarations;
520
1.89k
    separateNameSpaces = copyOf.separateNameSpaces;
521
3.78k
    for (unsigned int i = copyOf.adoptedLevels; i < copyOf.table.size(); ++i)
522
1.89k
        table.push_back(copyOf.table[i]->clone());
523
1.89k
}
524
525
} // end namespace glslang