Repository: shader-slang/slang
File: source/slang/slang-emit-c-like.cpp (C++)

Code before:
        {
            StringBuilder sb;
            sb << "BufferPointer_";
            sb << getName(inst->getOperand(0));
            sb << "_" << Int32(getID(inst));
            return sb.produceString();
        }
    default:
        break;
    }
    // Otherwise fall back to a construct temporary name
    // for the instruction.
    StringBuilder sb;
    sb << "_S";
    sb << Int32(getID(inst));

    return sb.produceString();
}

String CLikeSourceEmitter::getName(IRInst* inst)
{
    String name;
    if(!m_mapInstToName.tryGetValue(inst, name))
    {
        // unmangle names, when emitting header
        if (shouldEmitOnlyHeader())
        {
            if (auto nameHintDecor = inst->findDecoration<IRNameHintDecoration>())
            {
                StringBuilder sb;
                appendScrubbedName(nameHintDecor->getName(), sb);
                name = sb.produceString();
            }
        }
        else
        {
            name = generateName(inst);
        }
        m_mapInstToName.add(inst, name);
    }
    return name;
}

String CLikeSourceEmitter::getUnmangledName(IRInst* inst)
{
    if (auto nameHintDecor = inst->findDecoration<IRNameHintDecoration>())
        return nameHintDecor->getName();
    return getName(inst);
}

void CLikeSourceEmitter::emitSimpleValueImpl(IRInst* inst)

Review comment (performance):
I think we should bottleneck name generating logic through the same branch regardless of `shouldEmitOnlyHeader` setting so our cpp code can actually match the header code. Is there a reason why we need different behavior then just calling `generateName` here?

Code after:
        // is some wiggle room
        const Index maxTokenLength = 1024 - 8;

        const Index length = out.getLength();

        if (length > maxTokenLength)
        {
            // We are going to output with a prefix and a hash of the full name
            const auto hash = getStableHashCode64(out.getBuffer(), length);
            // Two hex chars per byte
            const Index hashSize = sizeof(hash) * 2;

            // Work out a size that is within range taking into account the hash size and extra
            // chars
            Index reducedBaseLength = maxTokenLength - hashSize - 1;
            // If it has a trailing _ remove it.
            // We know because of scrubbing there can only be single _
            reducedBaseLength -= Index(out[reducedBaseLength - 1] == '_');

            // Reduce the length
            out.reduceLength(reducedBaseLength);
            // Let's add a _ to separate from the rest of the name
            out.appendChar('_');
            // Append the hash in hex
            out.append(hash);

            SLANG_ASSERT(out.getLength() <= maxTokenLength);
        }
    }
}

inline String CLikeSourceEmitter::maybeMakeEntryPointNameValid(String name, DiagnosticSink* sink)
{
    if (isCPUTarget(getTargetReq()) || isCUDATarget(getTargetReq()) ||
        isMetalTarget(getTargetReq()))
    {
        if (name == "main")
        {
            String newName = _generateUniqueName(name.getUnownedSlice());
            sink->diagnose(SourceLoc(), Diagnostics::mainEntryPointRenamed, name, newName);
            return newName;
        }
    }
    return name;
}

String CLikeSourceEmitter::generateEntryPointNameImpl(IREntryPointDecoration* entryPointDecor)
{
    String name = entryPointDecor->getName()->getStringSlice();
    return maybeMakeEntryPointNameValid(name, getSink());
}