https://github.com/shader-slang/slang
Tip revision: e59516fa8c3a16eb7b99a928c5b85b97bf44fd72 authored by Yong He on 01 February 2022, 00:26:03 UTC
Revise entrypoint renaming interface. (#2113)
Revise entrypoint renaming interface. (#2113)
Tip revision: e59516f
slang-ir-entry-point-raw-ptr-params.cpp
// slang-ir-entry-point-raw-ptr-params.cpp
#include "slang-ir-entry-point-raw-ptr-params.h"
#include "slang-ir-insts.h"
namespace Slang
{
// This pass transforms the entry points in a module
// so that any entry-point parameters of pointer
// type (or a pointer-like type like `ConstantBuffer<T>`)
// are replaced with parameters of raw pointer (`void*`)
// type, with a cast in teh function body used to
// produce a value of the expected type.
struct ConvertEntryPointPtrParamsToRawPtrsPass
{
IRModule* m_module;
void processModule()
{
SharedIRBuilder sharedBuilder(m_module);
IRBuilder builder(&sharedBuilder);
// We start by getting and caching the raw pointer type.
//
auto rawPtrType = builder.getRawPointerType();
// Now we loop over global-scope instructions searching
// for any entry points.
//
for( auto inst : m_module->getGlobalInsts() )
{
auto func = as<IRFunc>(inst);
if(!func)
continue;
if( !func->findDecoration<IREntryPointDecoration>() )
continue;
// We can only modify entry points with definitions here.
//
auto firstBlock = func->getFirstBlock();
if(!firstBlock)
continue;
// Any code we introduce for casts will need to be inserted
// before the first ordinary instruction in the first block
// of the function (right after the parameters).
//
builder.setInsertBefore(firstBlock->getFirstOrdinaryInst());
// Note: because we are inserting code right after the parameters
// it doesn't work here to use `firstBlock->getParams()`, because
// that captures a begin/end range where the "end" is the
// first ordinary instruction at the time of the call, which will
// chane when we insert code.
//
// TODO: We chould probably change the represnetation of ranges
// of instructions to use first/last instead of begin/end so
// that ranges are robust against changes to instructions outside
// of a range.
//
for( auto param = firstBlock->getFirstParam(); param; param = param->getNextParam() )
{
// We only want to transform parameters of pointer or
// pointer-like type.
//
auto paramType = param->getDataType();
if(!as<IRPtrTypeBase>(paramType) && !as<IRPointerLikeType>(paramType))
continue;
// We will overwrite the type of the parameter to
// be the raw pointer type instead.
//
builder.setDataType(param, rawPtrType);
// We are going to replace uses of the parameter with
// uses of a bit-cast operation based on the parameter,
// but we need to be careful because that bit-cast operation
// will itself be a use (which we don't want to replace
// because that would create a circularity).
//
// Instead we capture the list of uses *before* we create
// the bit cast instruction.
//
List<IRUse*> uses;
for(auto use = param->firstUse; use; use = use->nextUse)
uses.add(use);
// Now we emit a bit-cast operation into the first block
// of the entry-point function to cast the raw-pointer
// parameter to the type that the body code expects.
//
auto cast = builder.emitBitCast(paramType, param);
// Now we can replace all the (captured) uses of the
// parameter with the bit-cast operation instead.
//
for(auto use : uses)
use->set(cast);
}
// Because our operation might have changed the parameter
// types of the function, we need to make sure to fix up
// the IR type of the function to match its parameter list.
//
fixUpFuncType(func);
}
}
};
void convertEntryPointPtrParamsToRawPtrs(
IRModule* module)
{
ConvertEntryPointPtrParamsToRawPtrsPass pass;
pass.m_module = module;
pass.processModule();
}
}