mirror of
https://github.com/intel/intel-graphics-compiler.git
synced 2025-10-30 08:18:26 +08:00
relocations symbols should be against *kernel* names, since only those sections are present in ze binary
721 lines
25 KiB
C++
721 lines
25 KiB
C++
/*========================== begin_copyright_notice ============================
|
|
|
|
Copyright (C) 2020-2021 Intel Corporation
|
|
|
|
SPDX-License-Identifier: MIT
|
|
|
|
============================= end_copyright_notice ===========================*/
|
|
|
|
#include "Compiler/DebugInfo/ScalarVISAModule.h"
|
|
#include "Compiler/DebugInfo/Utils.h"
|
|
#include "Compiler/Optimizer/OpenCLPasses/KernelArgs.hpp"
|
|
#include "Compiler/CISACodeGen/ShaderCodeGen.hpp"
|
|
#include "GenISAIntrinsics/GenIntrinsicInst.h"
|
|
#include "common/debug/Debug.hpp"
|
|
|
|
#include "common/LLVMWarningsPush.hpp"
|
|
#include "llvm/IR/Function.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "common/LLVMWarningsPop.hpp"
|
|
|
|
#include "Probe/Assertion.h"
|
|
|
|
using namespace llvm;
|
|
|
|
namespace IGC {
|
|
|
|
/*static*/ bool DebugMetadataInfo::hasDashGOption(CodeGenContext* ctx)
|
|
{
|
|
return ctx->getModuleMetaData()->compOpt.DashGSpecified;
|
|
}
|
|
|
|
/*static*/ bool DebugMetadataInfo::hasAnyDebugInfo(CodeGenContext* ctx, bool& fullDebugInfo, bool& lineNumbersOnly)
|
|
{
|
|
Module* module = ctx->getModule();
|
|
bool hasFullDebugInfo = false;
|
|
fullDebugInfo = false;
|
|
lineNumbersOnly = false;
|
|
|
|
if (Utils::HasDebugInfo(*ctx->getModule()))
|
|
{
|
|
bool hasDbgIntrinsic = false;
|
|
bool hasDbgLoc = false;
|
|
|
|
// Return true if LLVM IR has dbg.declare/dbg.value intrinsic calls.
|
|
// And also !dbgloc data.
|
|
auto& funcList = module->getFunctionList();
|
|
|
|
for (auto funcIt = funcList.begin();
|
|
funcIt != funcList.end() && !hasFullDebugInfo;
|
|
funcIt++)
|
|
{
|
|
auto& func = (*funcIt);
|
|
|
|
for (auto bbIt = func.begin();
|
|
bbIt != func.end() && !hasFullDebugInfo;
|
|
bbIt++)
|
|
{
|
|
auto& bb = (*bbIt);
|
|
|
|
for (auto instIt = bb.begin();
|
|
instIt != bb.end() && !hasFullDebugInfo;
|
|
instIt++)
|
|
{
|
|
auto& inst = (*instIt);
|
|
|
|
if (dyn_cast_or_null<DbgInfoIntrinsic>(&inst))
|
|
{
|
|
hasDbgIntrinsic = true;
|
|
}
|
|
|
|
auto& loc = inst.getDebugLoc();
|
|
|
|
if (loc)
|
|
{
|
|
hasDbgLoc = true;
|
|
}
|
|
|
|
hasFullDebugInfo = hasDbgIntrinsic & hasDbgLoc;
|
|
|
|
fullDebugInfo |= hasFullDebugInfo;
|
|
lineNumbersOnly |= hasDbgLoc;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return (fullDebugInfo | lineNumbersOnly);
|
|
}
|
|
|
|
ScalarVisaModule::ScalarVisaModule(CShader* TheShader,
|
|
llvm::Function *TheFunction,
|
|
bool IsPrimary)
|
|
: m_pShader(TheShader), VISAModule(TheFunction, IsPrimary) {
|
|
UpdateVisaId();
|
|
}
|
|
|
|
std::unique_ptr<IGC::VISAModule> ScalarVisaModule::BuildNew(CShader* S,
|
|
llvm::Function *F,
|
|
bool IsPrimary)
|
|
{
|
|
auto* n = new ScalarVisaModule(S, F, IsPrimary);
|
|
return std::unique_ptr<IGC::VISAModule>(n);
|
|
}
|
|
|
|
unsigned ScalarVisaModule::getPrivateBaseReg() const
|
|
{
|
|
auto pVar = privateBase;
|
|
unsigned privateBaseRegNum = m_pShader->GetDebugInfoData().getVISADclId(pVar, 0);
|
|
return privateBaseRegNum;;
|
|
}
|
|
|
|
int ScalarVisaModule::getPTOReg() const {
|
|
IGC_ASSERT_MESSAGE(hasPTO(), "PTO instruction required");
|
|
Value* pValPTO = dyn_cast_or_null<Value>(m_perThreadOffset);
|
|
IGC_ASSERT_MESSAGE(pValPTO, "pValPTO error");
|
|
// At this point we expect only a register
|
|
CVariable* pVarPTO = GetSymbol(m_perThreadOffset, pValPTO);
|
|
|
|
IGC_ASSERT_MESSAGE(pVarPTO, "Per Thread Offset variable does not exist");
|
|
IGC_ASSERT_MESSAGE(pVarPTO->GetVarType() == EVARTYPE_GENERAL, "Unexpected VISA register type!");
|
|
|
|
int regPTO = getDeclarationID(pVarPTO, false);
|
|
return regPTO;
|
|
}
|
|
int ScalarVisaModule::getFPReg() const {
|
|
CVariable *framePtr = getFramePtr();
|
|
// TBD: IGC_ASSERT_MESSAGE(framePtr, "Frame Pointer does not exist");
|
|
int regFP = getDeclarationID(framePtr, false);
|
|
return regFP;
|
|
}
|
|
|
|
llvm::StringRef ScalarVisaModule::GetVISAFuncName(llvm::StringRef OldName) const
|
|
{
|
|
// when igc.device.enqueue metadata is used, function name
|
|
// doesnt match between llvm::Function and VISA. this
|
|
// lambda checks whether device enqueue is used and if so,
|
|
// it returns function name that VISA uses. this is required
|
|
// to lookup symbol table of the function.
|
|
//
|
|
// when device enqueue is not used, llvm's function name
|
|
// matches that used by VISA.
|
|
auto& Module = *getFunction()->getParent();
|
|
|
|
// check if llvm function name is different than VISA function name
|
|
// due to igc.device.enqueue named MD
|
|
auto EnqueueNamedMD = Module.getNamedMetadata("igc.device.enqueue");
|
|
if (EnqueueNamedMD)
|
|
{
|
|
// !igc.device.enqueue = !{!307}
|
|
// !307 = !{!"__ParentKernel_block_invoke_kernel", !"ParentKernel_dispatch_0"}
|
|
auto NumOpnds = EnqueueNamedMD->getNumOperands();
|
|
for (unsigned int I = 0; I != NumOpnds; ++I)
|
|
{
|
|
auto Pair = EnqueueNamedMD->getOperand(I);
|
|
auto& First = Pair->getOperand(0);
|
|
auto& Second = Pair->getOperand(1);
|
|
if (isa<MDString>(First) && isa<MDString>(Second))
|
|
{
|
|
auto Str = cast<MDString>(Second)->getString();
|
|
if (Str.equals(OldName))
|
|
{
|
|
return cast<MDString>(First)->getString();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return OldName;
|
|
}
|
|
uint64_t ScalarVisaModule::getFPOffset() const {
|
|
return EmitPass::getFPOffset();
|
|
}
|
|
unsigned ScalarVisaModule::getPointerSize() const {
|
|
return IGC::getPointerSize((llvm::Module &)(*GetModule()));
|
|
}
|
|
|
|
uint64_t ScalarVisaModule::getTypeSizeInBits(Type* Ty) const
|
|
{
|
|
IGC_ASSERT(getFunction());
|
|
// TODO: looks like data layout for function pointers is not set
|
|
// correctly. According to the current data layout all pointers are of
|
|
// 64 bits, while vISA/genIsa function pointers are deemed to be 32 bits.
|
|
// Double-check if this is an issue.
|
|
return getFunction()->getParent()->getDataLayout().getTypeSizeInBits(Ty);
|
|
}
|
|
|
|
void ScalarVisaModule::UpdateVisaId()
|
|
{
|
|
auto* Kernel = m_pShader->GetEncoder().GetVISAKernel();
|
|
SetVISAId(Kernel->getvIsaInstCount());
|
|
}
|
|
|
|
void ScalarVisaModule::ValidateVisaId()
|
|
{
|
|
IGC_ASSERT_MESSAGE(GetCurrentVISAId() == m_pShader->GetEncoder().GetVISAKernel()->getvIsaInstCount(), "Missed emitted pattern!");
|
|
}
|
|
|
|
uint16_t ScalarVisaModule::GetSIMDSize() const
|
|
{
|
|
SIMDMode simdMode = m_pShader->m_dispatchSize;
|
|
|
|
return numLanes(simdMode);
|
|
}
|
|
|
|
const Argument* ScalarVisaModule::GetTracedArgument64Ops(const Value* pVal) const
|
|
{
|
|
/* %.privateBuffer111 = bitcast i8* %23 to %opencl.image2d_t addrspace(1)**
|
|
%24 = bitcast %opencl.image2d_t addrspace(1)** %.privateBuffer111 to i64*
|
|
%25 = call { i32, i32 } @llvm.genx.GenISA.ptr.to.pair.p1opencl.image2d_t(%opencl.image2d_t addrspace(1)* %Input)
|
|
%26 = extractvalue { i32, i32 } %25, 0
|
|
%27 = extractvalue { i32, i32 } %25, 1
|
|
%28 = insertelement <2 x i32> undef, i32 %26, i32 0
|
|
%29 = insertelement <2 x i32> %28, i32 %27, i32 1
|
|
%30 = bitcast i64* %24 to <2 x i32>*
|
|
store <2 x i32> %29, <2 x i32>* %30, align 8
|
|
call void @llvm.dbg.declare(metadata %opencl.image2d_t addrspace(1)** %.privateBuffer111, metadata !82, metadata !80), !dbg !83*/
|
|
|
|
const Argument* arg = nullptr;
|
|
const Value* pBaseValue = pVal;
|
|
|
|
bool found = false;
|
|
// Get to bitcast from privateBuffer111
|
|
// % 24 = bitcast %opencl.image2d_t addrspace(1)** %.privateBuffer111 to i64*
|
|
for (auto i = pBaseValue->user_begin(), e = pBaseValue->user_end(); i != e; ++i)
|
|
{
|
|
const Value* pUser = *i;
|
|
|
|
if (isa<const BitCastInst>(pUser))
|
|
{
|
|
pBaseValue = pUser;
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!found) return arg;
|
|
|
|
// Get to bitcast from bitcast
|
|
// %30 = bitcast i64* %24 to <2 x i32>*
|
|
found = false;
|
|
for (auto i = pBaseValue->user_begin(), e = pBaseValue->user_end(); i != e; ++i)
|
|
{
|
|
const Value* pUser = *i;
|
|
|
|
if (isa<const BitCastInst>(pUser))
|
|
{
|
|
pBaseValue = pUser;
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!found) return arg;
|
|
|
|
// Get to store from bitcast
|
|
// store <2 x i32> %29, <2 x i32>* %30, align 8
|
|
found = false;
|
|
for (auto i = pBaseValue->user_begin(), e = pBaseValue->user_end(); i != e; ++i)
|
|
{
|
|
const Value* pUser = *i;
|
|
|
|
if (isa<const StoreInst>(pUser))
|
|
{
|
|
pBaseValue = pUser;
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!found) return arg;
|
|
|
|
// Get to insertelement from store
|
|
// %29 = insertelement <2 x i32> %28, i32 %27, i32 1
|
|
if (!isa<const StoreInst>(pBaseValue))
|
|
{
|
|
return arg;
|
|
}
|
|
auto storeInst = cast<const StoreInst>(pBaseValue);
|
|
pBaseValue = storeInst->getValueOperand();
|
|
|
|
// Get to extractvalue from insertelement
|
|
// %27 = extractvalue { i32, i32 } %25, 1
|
|
if (!isa<const InsertElementInst>(pBaseValue))
|
|
{
|
|
return arg;
|
|
}
|
|
auto insertelement = cast<const InsertElementInst>(pBaseValue);
|
|
pBaseValue = insertelement->getOperand(1);
|
|
|
|
// Get to call from extractvalue
|
|
// %25 = call { i32, i32 } @llvm.genx.GenISA.ptr.to.pair.p1opencl.image2d_t(%opencl.image2d_t addrspace(1)* %Input)
|
|
if (!isa<const ExtractValueInst>(pBaseValue))
|
|
{
|
|
return arg;
|
|
}
|
|
auto extractvalue = cast<const ExtractValueInst>(pBaseValue);
|
|
pBaseValue = extractvalue->getOperand(0);
|
|
|
|
// Get arg0 of intrinsic
|
|
if (!isa<const CallInst>(pBaseValue))
|
|
{
|
|
return arg;
|
|
}
|
|
auto callinst = cast<const CallInst>(pBaseValue);
|
|
|
|
if (!isa<const Argument>(callinst->getArgOperand(0)))
|
|
{
|
|
return arg;
|
|
}
|
|
arg = cast<const Argument>(callinst->getArgOperand(0));
|
|
|
|
return arg;
|
|
}
|
|
|
|
const Argument* ScalarVisaModule::GetTracedArgument(const Value* pVal, bool isAddress) const
|
|
{
|
|
const Value* pBaseValue = pVal;
|
|
while (true)
|
|
{
|
|
if (isAddress)
|
|
{
|
|
const StoreInst* pStore = nullptr;
|
|
// Alloca used to store image or sampler, assumed to have usages:
|
|
// 1. as many loads as needed.
|
|
// 2. One and only one store.
|
|
for (auto i = pBaseValue->user_begin(), e = pBaseValue->user_end(); i != e; ++i)
|
|
{
|
|
const Value* pUser = *i;
|
|
if (isa<const LoadInst>(pUser))
|
|
{
|
|
// Found a load, ignore it.
|
|
continue;
|
|
}
|
|
// Not a load, must be the one and only store.
|
|
if (!isa<const StoreInst>(pUser) || pStore)
|
|
{
|
|
// Is not traceable to argument, break.
|
|
pStore = nullptr;
|
|
break;
|
|
}
|
|
pStore = cast<StoreInst>(pUser);
|
|
}
|
|
// Check that store instruction was found.
|
|
if (!pStore)
|
|
{
|
|
// Is not traceable to argument, break.
|
|
break;
|
|
}
|
|
// Update the baseValue and repeat the check.
|
|
pBaseValue = pStore->getValueOperand();
|
|
isAddress = false;
|
|
}
|
|
if (const Argument * pArg = dyn_cast<const Argument>(pBaseValue))
|
|
{
|
|
// Reached an Argument, return it.
|
|
return pArg;
|
|
}
|
|
else if (const CastInst * pInst = dyn_cast<const CastInst>(pBaseValue))
|
|
{
|
|
// Reached a CastInst (could happen for image).
|
|
// Update the baseValue and repeat the check.
|
|
pBaseValue = pInst->getOperand(0);
|
|
}
|
|
else
|
|
{
|
|
// Is not traceable to argument, break.
|
|
break;
|
|
}
|
|
}
|
|
// If reach this point. Return nullptr.
|
|
return nullptr;
|
|
}
|
|
std::vector<VISAVariableLocation>
|
|
ScalarVisaModule::GetVariableLocation(const llvm::Instruction* pInst) const
|
|
{
|
|
const Value* pVal = nullptr;
|
|
MDNode* pNode = nullptr;
|
|
bool isDbgDclInst = false;
|
|
std::vector<VISAVariableLocation> ret;
|
|
if (const DbgDeclareInst * pDbgAddrInst = dyn_cast<DbgDeclareInst>(pInst))
|
|
{
|
|
pVal = pDbgAddrInst->getAddress();
|
|
pNode = pDbgAddrInst->getVariable();
|
|
isDbgDclInst = true;
|
|
}
|
|
else if (const DbgValueInst * pDbgValInst = dyn_cast<DbgValueInst>(pInst))
|
|
{
|
|
pVal = pDbgValInst->getValue();
|
|
pNode = pDbgValInst->getVariable();
|
|
}
|
|
else
|
|
{
|
|
IGC_ASSERT_MESSAGE(0, "Expected debug info instruction");
|
|
}
|
|
|
|
if (!pVal || isa<UndefValue>(pVal))
|
|
{
|
|
// No debug info value, return empty location!
|
|
ret.push_back(VISAVariableLocation(this));
|
|
return ret;
|
|
}
|
|
|
|
if (const Constant * pConstVal = dyn_cast<Constant>(pVal))
|
|
{
|
|
if (!isa<GlobalVariable>(pVal) && !isa<ConstantExpr>(pVal))
|
|
{
|
|
IGC_ASSERT_MESSAGE(!isDbgDclInst, "address cannot be immediate!");
|
|
ret.push_back(VISAVariableLocation(pConstVal, this));
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
// Try trace value to an argument
|
|
const Argument* pArgument = GetTracedArgument(pVal, isDbgDclInst);
|
|
|
|
if (!pArgument
|
|
&& isDbgDclInst)
|
|
{
|
|
// Check for special pattern when Emu64Ops pass is run
|
|
pArgument = GetTracedArgument64Ops(pVal);
|
|
}
|
|
|
|
if (pArgument)
|
|
{
|
|
IGC_ASSERT_MESSAGE((pArgument->getParent() == GetEntryFunction() || pArgument->getParent()->hasFnAttribute("referenced-indirectly")), "Argument does not belong to current processed function");
|
|
|
|
const Function* curFunc = pArgument->getParent()->hasFnAttribute("referenced-indirectly")
|
|
? pArgument->getParent() : GetEntryFunction();
|
|
// Check if it is argument of image or sampler
|
|
IGC::IGCMD::MetaDataUtils::FunctionsInfoMap::iterator itr =
|
|
m_pShader->GetMetaDataUtils()->findFunctionsInfoItem(const_cast<Function*>(curFunc));
|
|
CodeGenContext* pCtx = m_pShader->GetContext();
|
|
ModuleMetaData* modMD = pCtx->getModuleMetaData();
|
|
|
|
if (itr != m_pShader->GetMetaDataUtils()->end_FunctionsInfo()
|
|
&& modMD->FuncMD.find(const_cast<Function*>(curFunc)) != modMD->FuncMD.end())
|
|
{
|
|
unsigned int explicitArgsNum = curFunc->arg_size() - itr->second->size_ImplicitArgInfoList();
|
|
if (pArgument->getArgNo() < explicitArgsNum &&
|
|
modMD->FuncMD[const_cast<Function*>(curFunc)].m_OpenCLArgBaseTypes.size() > pArgument->getArgNo())
|
|
{
|
|
const std::string typeStr = modMD->FuncMD[const_cast<Function*>(curFunc)].m_OpenCLArgBaseTypes[pArgument->getArgNo()];
|
|
KernelArg::ArgType argType = KernelArg::calcArgType(pArgument, typeStr);
|
|
if (argType == KernelArg::ArgType::SAMPLER)
|
|
{
|
|
// SAMPLER and NOT_TO_ALLOCATE have same enum values so disambiguate these
|
|
auto pr = KernelArg::getBufferType(pArgument, typeStr);
|
|
if(!pr.isSampler)
|
|
{
|
|
// type is actually NOT_TO_ALLOCATE
|
|
argType = KernelArg::ArgType::End;
|
|
}
|
|
}
|
|
FunctionMetaData* funcMD = &modMD->FuncMD[const_cast<Function*>(curFunc)];
|
|
ResourceAllocMD* resAllocMD = &funcMD->resAllocMD;
|
|
IGC_ASSERT_MESSAGE(resAllocMD->argAllocMDList.size() == curFunc->arg_size(), "Invalid ArgAllocMDList");
|
|
ArgAllocMD* argAlloc = &resAllocMD->argAllocMDList[pArgument->getArgNo()];
|
|
unsigned int index = argAlloc->indexType;
|
|
|
|
switch (argType)
|
|
{
|
|
default:
|
|
break;
|
|
case KernelArg::ArgType::SAMPLER:
|
|
IGC_ASSERT_MESSAGE(index < SAMPLER_REGISTER_NUM, "Bad sampler index");
|
|
ret.push_back(VISAVariableLocation(SAMPLER_REGISTER_BEGIN + index, this));
|
|
return ret;
|
|
case KernelArg::ArgType::IMAGE_1D:
|
|
case KernelArg::ArgType::IMAGE_1D_BUFFER:
|
|
case KernelArg::ArgType::IMAGE_2D:
|
|
case KernelArg::ArgType::IMAGE_2D_DEPTH:
|
|
case KernelArg::ArgType::IMAGE_2D_MSAA:
|
|
case KernelArg::ArgType::IMAGE_2D_MSAA_DEPTH:
|
|
case KernelArg::ArgType::IMAGE_3D:
|
|
case KernelArg::ArgType::IMAGE_1D_ARRAY:
|
|
case KernelArg::ArgType::IMAGE_2D_ARRAY:
|
|
case KernelArg::ArgType::IMAGE_2D_DEPTH_ARRAY:
|
|
case KernelArg::ArgType::IMAGE_2D_MSAA_ARRAY:
|
|
case KernelArg::ArgType::IMAGE_2D_MSAA_DEPTH_ARRAY:
|
|
// Found write image
|
|
switch (argAlloc->type)
|
|
{
|
|
case UAVResourceType:
|
|
// Found write image
|
|
index = m_pShader->m_pBtiLayout->GetUavIndex(index);
|
|
IGC_ASSERT_MESSAGE(index < TEXTURE_REGISTER_NUM, "Bad texture index");
|
|
ret.push_back(VISAVariableLocation(TEXTURE_REGISTER_BEGIN + index, this));
|
|
return ret;
|
|
case SRVResourceType:
|
|
// Found read image
|
|
index = m_pShader->m_pBtiLayout->GetTextureIndex(index);
|
|
IGC_ASSERT_MESSAGE(index < TEXTURE_REGISTER_NUM, "Bad texture index");
|
|
ret.push_back(VISAVariableLocation(TEXTURE_REGISTER_BEGIN + index, this));
|
|
return ret;
|
|
default:
|
|
IGC_ASSERT_MESSAGE(0, "Unknown texture resource");
|
|
ret.push_back(VISAVariableLocation(this));
|
|
return ret;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Value* pValue = const_cast<Value*>(pVal);
|
|
|
|
Type* pType = pValue->getType();
|
|
|
|
if (isDbgDclInst)
|
|
{
|
|
if (!pType->isPointerTy()) {
|
|
// TODO: Re-enable this assert once -O2 fixes bug where llvm.dbg.declare points
|
|
// to a non-address value.
|
|
//IGC_ASSERT_MESSAGE(0, "DBG declare intrinsic must point to an address");
|
|
ret.push_back(VISAVariableLocation(this));
|
|
return ret;
|
|
}
|
|
pType = pType->getPointerElementType();
|
|
}
|
|
|
|
bool isInSurface = false;
|
|
bool isGlobalAddrSpace = false;
|
|
unsigned int surfaceReg = 0;
|
|
if (pType->isPointerTy())
|
|
{
|
|
unsigned int addrSpace = pType->getPointerAddressSpace();
|
|
if (addrSpace == ADDRESS_SPACE_LOCAL)
|
|
{
|
|
isInSurface = true;
|
|
surfaceReg = TEXTURE_REGISTER_BEGIN + LOCAL_SURFACE_BTI;
|
|
}
|
|
if (addrSpace == ADDRESS_SPACE_GLOBAL)
|
|
{
|
|
isGlobalAddrSpace = true;
|
|
}
|
|
}
|
|
else if (pVal->getType()->isPointerTy())
|
|
{
|
|
unsigned int addrSpace = pVal->getType()->getPointerAddressSpace();
|
|
if (addrSpace == ADDRESS_SPACE_LOCAL)
|
|
{
|
|
isInSurface = true;
|
|
surfaceReg = TEXTURE_REGISTER_BEGIN + LOCAL_SURFACE_BTI;
|
|
}
|
|
}
|
|
|
|
if (isa<GlobalVariable>(pValue))
|
|
{
|
|
unsigned int offset = m_pShader->GetGlobalMappingValue(pValue);
|
|
if (isInSurface)
|
|
{
|
|
ret.push_back(VISAVariableLocation(surfaceReg, offset, false, isDbgDclInst, 0, false, this));
|
|
return ret;
|
|
}
|
|
ret.push_back(VISAVariableLocation(offset, false, isDbgDclInst, 0, false, false, this));
|
|
return ret;
|
|
}
|
|
|
|
// At this point we expect only a register
|
|
CVariable* pVar = nullptr;
|
|
auto globalSubCVar = m_pShader->GetGlobalCVar(pValue);
|
|
|
|
if (!globalSubCVar) {
|
|
pVar = m_pShader->GetDebugInfoData().getMapping(*pInst->getFunction(), pValue);
|
|
if (!pVar)
|
|
{
|
|
ret.push_back(VISAVariableLocation(this));
|
|
return ret;
|
|
}
|
|
}
|
|
else
|
|
pVar = globalSubCVar;
|
|
|
|
IGC_ASSERT_MESSAGE(false == pVar->IsImmediate(), "Do not expect an immediate value at this level");
|
|
|
|
std::string varName = cast<DIVariable>(pNode)->getName().str();
|
|
unsigned int reg = 0, reg2 = 0;
|
|
unsigned int vectorNumElements = 0;
|
|
|
|
switch (pVar->GetVarType()) {
|
|
case EVARTYPE_GENERAL:
|
|
// We want to attach "Output" attribute to all src variables
|
|
// so that finalizer can extend their liveness to end of
|
|
// the program. This will help debugger examine their
|
|
// values anywhere in the code till they are in scope.
|
|
reg = m_pShader->GetDebugInfoData().getVISADclId(pVar, 0);
|
|
IGC_ASSERT_MESSAGE(reg < GENERAL_REGISTER_NUM, "Bad VISA general register");
|
|
|
|
if (pType->isVectorTy())
|
|
{
|
|
vectorNumElements = (unsigned)cast<IGCLLVM::FixedVectorType>(pType)->getNumElements();
|
|
}
|
|
else if (!pVar->IsUniform())
|
|
{
|
|
vectorNumElements = 1;
|
|
}
|
|
|
|
if (isInSurface)
|
|
{
|
|
ret.push_back(VISAVariableLocation(surfaceReg, GENERAL_REGISTER_BEGIN + reg, true, isDbgDclInst, vectorNumElements, !pVar->IsUniform(), this));
|
|
return ret;
|
|
}
|
|
ret.push_back(VISAVariableLocation(GENERAL_REGISTER_BEGIN + reg, true, isDbgDclInst, vectorNumElements, !pVar->IsUniform(), isGlobalAddrSpace, this));
|
|
if (GetSIMDSize() == 32 && pVar->visaGenVariable[1] && !pVar->IsUniform())
|
|
{
|
|
reg2 = m_pShader->GetDebugInfoData().getVISADclId(pVar, 1);
|
|
ret.push_back(VISAVariableLocation(GENERAL_REGISTER_BEGIN + reg2, true, isDbgDclInst, vectorNumElements, !pVar->IsUniform(), isGlobalAddrSpace, this));
|
|
}
|
|
return ret;
|
|
case EVARTYPE_ADDRESS:
|
|
case EVARTYPE_PREDICATE:
|
|
case EVARTYPE_SURFACE:
|
|
case EVARTYPE_SAMPLER:
|
|
// TODO: Handle case where variable is mapped to flag/address register
|
|
ret.push_back(VISAVariableLocation(this));
|
|
return ret;
|
|
break;
|
|
default:
|
|
IGC_ASSERT_MESSAGE(0, "Unhandled VISA register type!");
|
|
break;
|
|
}
|
|
|
|
IGC_ASSERT_MESSAGE(0, "Empty variable location");
|
|
ret.push_back(VISAVariableLocation(this));
|
|
return ret;
|
|
}
|
|
|
|
bool ScalarVisaModule::IsCatchAllIntrinsic(const llvm::Instruction* pInst) const
|
|
{
|
|
return ((isa<GenIntrinsicInst>(pInst) &&
|
|
cast<GenIntrinsicInst>(pInst)->getIntrinsicID() == GenISAIntrinsic::GenISA_CatchAllDebugLine));
|
|
}
|
|
|
|
// OpenCL keyword constant is used as qualifier to variables whose values remain the
|
|
// same throughout the program. clang inlines constants in to LLVM IR and no metadata
|
|
// is emitted to LLVM IR for such constants. This function iterates over all globals
|
|
// and constants to emit metadata per function.
|
|
void insertOCLMissingDebugConstMetadata(CodeGenContext* ctx)
|
|
{
|
|
Module* M = ctx->getModule();
|
|
bool fullDebugInfo, lineNumbersOnly;
|
|
DebugMetadataInfo::hasAnyDebugInfo(ctx, fullDebugInfo, lineNumbersOnly);
|
|
|
|
if (!fullDebugInfo)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (auto& func : *M)
|
|
{
|
|
if (func.isDeclaration())
|
|
continue;
|
|
|
|
for (auto global_it = M->global_begin();
|
|
global_it != M->global_end();
|
|
global_it++)
|
|
{
|
|
auto g = &*global_it;//(global_it.operator llvm::GlobalVariable *());
|
|
|
|
if (g->isConstant())
|
|
{
|
|
auto init = g->getInitializer();
|
|
|
|
bool isConstForThisFunc = false;
|
|
llvm::SmallVector<llvm::DIGlobalVariableExpression*, 1> GVs;
|
|
g->getDebugInfo(GVs);
|
|
for (unsigned int j = 0; j < GVs.size(); j++)
|
|
{
|
|
auto GVExp = llvm::dyn_cast_or_null<llvm::DIGlobalVariableExpression>(GVs[j]);
|
|
if (GVExp)
|
|
{
|
|
auto GV = GVExp->getVariable();
|
|
auto gblNodeScope = GV->getScope();
|
|
if (isa<DISubprogram>(gblNodeScope))
|
|
{
|
|
auto subprogramName = cast<DISubprogram>(gblNodeScope)->getName().data();
|
|
|
|
if (subprogramName == func.getName())
|
|
{
|
|
isConstForThisFunc = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!GlobalValue::isLocalLinkage(g->getLinkage()) || isConstForThisFunc)
|
|
{
|
|
Utils::UpdateGlobalVarDebugInfo(g, init, &func.getEntryBlock().getInstList().front(), false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool ScalarVisaModule::IsIntelSymbolTableVoidProgram() const
|
|
{
|
|
return IGC::isIntelSymbolTableVoidProgram(const_cast<llvm::Function*>(GetEntryFunction()));
|
|
}
|
|
|
|
CVariable* ScalarVisaModule::GetSymbol(const llvm::Instruction* pInst, llvm::Value* pValue) const
|
|
{
|
|
// CShader's symbols are emptied before compiling a new function.
|
|
// Whereas debug info emission starts after compilation of all functions.
|
|
return m_pShader->GetDebugInfoData().getMapping(*pInst->getFunction(), pValue);
|
|
}
|
|
|
|
int ScalarVisaModule::getDeclarationID(CVariable* pVar, bool isSecondSimd32Instruction) const
|
|
{
|
|
int varId = isSecondSimd32Instruction ? 1 : 0;
|
|
if (isSecondSimd32Instruction) {
|
|
if (!((GetSIMDSize() == 32 && pVar->visaGenVariable[1] && !pVar->IsUniform()))) {
|
|
return -1; // Cannot get 2nd variable in SIMD32 (?) mode
|
|
}
|
|
}
|
|
return m_pShader->GetDebugInfoData().getVISADclId(pVar, varId);
|
|
}
|
|
|
|
} // namespace IGC
|
|
|