blob: 70c582285136c70785696c79f0c7bdd523d3cacf [file] [log] [blame]
//===----- CGHLSLRuntime.cpp - Interface to HLSL Runtimes -----------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This provides an abstract class for HLSL code generation. Concrete
// subclasses of this implement code generation for specific HLSL
// runtime libraries.
//
//===----------------------------------------------------------------------===//
#include "CGHLSLRuntime.h"
#include "CodeGenModule.h"
#include "clang/Basic/TargetOptions.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
using namespace clang;
using namespace CodeGen;
using namespace hlsl;
using namespace llvm;
namespace {
void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) {
// The validation of ValVersionStr is done at HLSLToolChain::TranslateArgs.
// Assume ValVersionStr is legal here.
VersionTuple Version;
if (Version.tryParse(ValVersionStr) || Version.getBuild() ||
Version.getSubminor() || !Version.getMinor()) {
return;
}
uint64_t Major = Version.getMajor();
uint64_t Minor = *Version.getMinor();
auto &Ctx = M.getContext();
IRBuilder<> B(M.getContext());
MDNode *Val = MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32(Major)),
ConstantAsMetadata::get(B.getInt32(Minor))});
StringRef DxilValKey = "dx.valver";
M.addModuleFlag(llvm::Module::ModFlagBehavior::AppendUnique, DxilValKey, Val);
}
} // namespace
void CGHLSLRuntime::finishCodeGen() {
auto &TargetOpts = CGM.getTarget().getTargetOpts();
llvm::Module &M = CGM.getModule();
addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
}
void CGHLSLRuntime::annotateHLSLResource(const VarDecl *D, GlobalVariable *GV) {
const Type *Ty = D->getType()->getPointeeOrArrayElementType();
if (!Ty)
return;
const auto *RD = Ty->getAsCXXRecordDecl();
if (!RD)
return;
const auto *Attr = RD->getAttr<HLSLResourceAttr>();
if (!Attr)
return;
HLSLResourceAttr::ResourceClass RC = Attr->getResourceType();
uint32_t Counter = ResourceCounters[static_cast<uint32_t>(RC)]++;
NamedMDNode *ResourceMD = nullptr;
switch (RC) {
case HLSLResourceAttr::ResourceClass::UAV:
ResourceMD = CGM.getModule().getOrInsertNamedMetadata("hlsl.uavs");
break;
default:
assert(false && "Unsupported buffer type!");
return;
}
assert(ResourceMD != nullptr &&
"ResourceMD must have been set by the switch above.");
auto &Ctx = CGM.getModule().getContext();
IRBuilder<> B(Ctx);
QualType QT(Ty, 0);
ResourceMD->addOperand(MDNode::get(
Ctx, {ValueAsMetadata::get(GV), MDString::get(Ctx, QT.getAsString()),
ConstantAsMetadata::get(B.getInt32(Counter))}));
}
void clang::CodeGen::CGHLSLRuntime::setHLSLFunctionAttributes(
llvm::Function *F, const FunctionDecl *FD) {
if (HLSLShaderAttr *ShaderAttr = FD->getAttr<HLSLShaderAttr>()) {
const StringRef ShaderAttrKindStr = "dx.shader";
F->addFnAttr(ShaderAttrKindStr,
ShaderAttr->ConvertShaderTypeToStr(ShaderAttr->getType()));
}
}