
The module currently stores the target triple as a string. This means that any code that wants to actually use the triple first has to instantiate a Triple, which is somewhat expensive. The change in #121652 caused a moderate compile-time regression due to this. While it would be easy enough to work around, I think that architecturally, it makes more sense to store the parsed Triple in the module, so that it can always be directly queried. For this change, I've opted not to add any magic conversions between std::string and Triple for backwards-compatibilty purses, and instead write out needed Triple()s or str()s explicitly. This is because I think a decent number of them should be changed to work on Triple as well, to avoid unnecessary conversions back and forth. The only interesting part in this patch is that the default triple is Triple("") instead of Triple() to preserve existing behavior. The former defaults to using the ELF object format instead of unknown object format. We should fix that as well.
148 lines
5.4 KiB
C++
148 lines
5.4 KiB
C++
//=- DXILMetadataAnalysis.cpp - Representation of Module metadata -*- C++ -*=//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Analysis/DXILMetadataAnalysis.h"
|
|
#include "llvm/ADT/APInt.h"
|
|
#include "llvm/ADT/StringExtras.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/IR/Constants.h"
|
|
#include "llvm/IR/Instructions.h"
|
|
#include "llvm/IR/Metadata.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "llvm/InitializePasses.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
|
#define DEBUG_TYPE "dxil-metadata-analysis"
|
|
|
|
using namespace llvm;
|
|
using namespace dxil;
|
|
|
|
static ModuleMetadataInfo collectMetadataInfo(Module &M) {
|
|
ModuleMetadataInfo MMDAI;
|
|
const Triple &TT = M.getTargetTriple();
|
|
MMDAI.DXILVersion = TT.getDXILVersion();
|
|
MMDAI.ShaderModelVersion = TT.getOSVersion();
|
|
MMDAI.ShaderProfile = TT.getEnvironment();
|
|
NamedMDNode *ValidatorVerNode = M.getNamedMetadata("dx.valver");
|
|
if (ValidatorVerNode) {
|
|
auto *ValVerMD = cast<MDNode>(ValidatorVerNode->getOperand(0));
|
|
auto *MajorMD = mdconst::extract<ConstantInt>(ValVerMD->getOperand(0));
|
|
auto *MinorMD = mdconst::extract<ConstantInt>(ValVerMD->getOperand(1));
|
|
MMDAI.ValidatorVersion =
|
|
VersionTuple(MajorMD->getZExtValue(), MinorMD->getZExtValue());
|
|
}
|
|
|
|
// For all HLSL Shader functions
|
|
for (auto &F : M.functions()) {
|
|
if (!F.hasFnAttribute("hlsl.shader"))
|
|
continue;
|
|
|
|
EntryProperties EFP(&F);
|
|
// Get "hlsl.shader" attribute
|
|
Attribute EntryAttr = F.getFnAttribute("hlsl.shader");
|
|
assert(EntryAttr.isValid() &&
|
|
"Invalid value specified for HLSL function attribute hlsl.shader");
|
|
StringRef EntryProfile = EntryAttr.getValueAsString();
|
|
Triple T("", "", "", EntryProfile);
|
|
EFP.ShaderStage = T.getEnvironment();
|
|
// Get numthreads attribute value, if one exists
|
|
StringRef NumThreadsStr =
|
|
F.getFnAttribute("hlsl.numthreads").getValueAsString();
|
|
if (!NumThreadsStr.empty()) {
|
|
SmallVector<StringRef> NumThreadsVec;
|
|
NumThreadsStr.split(NumThreadsVec, ',');
|
|
assert(NumThreadsVec.size() == 3 && "Invalid numthreads specified");
|
|
// Read in the three component values of numthreads
|
|
[[maybe_unused]] bool Success =
|
|
llvm::to_integer(NumThreadsVec[0], EFP.NumThreadsX, 10);
|
|
assert(Success && "Failed to parse X component of numthreads");
|
|
Success = llvm::to_integer(NumThreadsVec[1], EFP.NumThreadsY, 10);
|
|
assert(Success && "Failed to parse Y component of numthreads");
|
|
Success = llvm::to_integer(NumThreadsVec[2], EFP.NumThreadsZ, 10);
|
|
assert(Success && "Failed to parse Z component of numthreads");
|
|
}
|
|
MMDAI.EntryPropertyVec.push_back(EFP);
|
|
}
|
|
return MMDAI;
|
|
}
|
|
|
|
void ModuleMetadataInfo::print(raw_ostream &OS) const {
|
|
OS << "Shader Model Version : " << ShaderModelVersion.getAsString() << "\n";
|
|
OS << "DXIL Version : " << DXILVersion.getAsString() << "\n";
|
|
OS << "Target Shader Stage : "
|
|
<< Triple::getEnvironmentTypeName(ShaderProfile) << "\n";
|
|
OS << "Validator Version : " << ValidatorVersion.getAsString() << "\n";
|
|
for (const auto &EP : EntryPropertyVec) {
|
|
OS << " " << EP.Entry->getName() << "\n";
|
|
OS << " Function Shader Stage : "
|
|
<< Triple::getEnvironmentTypeName(EP.ShaderStage) << "\n";
|
|
OS << " NumThreads: " << EP.NumThreadsX << "," << EP.NumThreadsY << ","
|
|
<< EP.NumThreadsZ << "\n";
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// DXILMetadataAnalysis and DXILMetadataAnalysisPrinterPass
|
|
|
|
// Provide an explicit template instantiation for the static ID.
|
|
AnalysisKey DXILMetadataAnalysis::Key;
|
|
|
|
llvm::dxil::ModuleMetadataInfo
|
|
DXILMetadataAnalysis::run(Module &M, ModuleAnalysisManager &AM) {
|
|
return collectMetadataInfo(M);
|
|
}
|
|
|
|
PreservedAnalyses
|
|
DXILMetadataAnalysisPrinterPass::run(Module &M, ModuleAnalysisManager &AM) {
|
|
llvm::dxil::ModuleMetadataInfo &Data = AM.getResult<DXILMetadataAnalysis>(M);
|
|
|
|
Data.print(OS);
|
|
return PreservedAnalyses::all();
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// DXILMetadataAnalysisWrapperPass
|
|
|
|
DXILMetadataAnalysisWrapperPass::DXILMetadataAnalysisWrapperPass()
|
|
: ModulePass(ID) {
|
|
initializeDXILMetadataAnalysisWrapperPassPass(
|
|
*PassRegistry::getPassRegistry());
|
|
}
|
|
|
|
DXILMetadataAnalysisWrapperPass::~DXILMetadataAnalysisWrapperPass() = default;
|
|
|
|
void DXILMetadataAnalysisWrapperPass::getAnalysisUsage(
|
|
AnalysisUsage &AU) const {
|
|
AU.setPreservesAll();
|
|
}
|
|
|
|
bool DXILMetadataAnalysisWrapperPass::runOnModule(Module &M) {
|
|
MetadataInfo.reset(new ModuleMetadataInfo(collectMetadataInfo(M)));
|
|
return false;
|
|
}
|
|
|
|
void DXILMetadataAnalysisWrapperPass::releaseMemory() { MetadataInfo.reset(); }
|
|
|
|
void DXILMetadataAnalysisWrapperPass::print(raw_ostream &OS,
|
|
const Module *) const {
|
|
if (!MetadataInfo) {
|
|
OS << "No module metadata info has been built!\n";
|
|
return;
|
|
}
|
|
MetadataInfo->print(dbgs());
|
|
}
|
|
|
|
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
|
LLVM_DUMP_METHOD
|
|
void DXILMetadataAnalysisWrapperPass::dump() const { print(dbgs(), nullptr); }
|
|
#endif
|
|
|
|
INITIALIZE_PASS(DXILMetadataAnalysisWrapperPass, "dxil-metadata-analysis",
|
|
"DXIL Module Metadata analysis", false, true)
|
|
char DXILMetadataAnalysisWrapperPass::ID = 0;
|