Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ line upon naming the release. Refer to previous for appropriate section names.

#### HLSL Language

- Updated implementation of `string` types to conform to restrictions for
intangible objects aligning with TC57's direction (see:
[hlsl-tc57/tc57#200](https://github.com/hlsl-tc57/tc57/issues/200)).
- The `shared` and `uniform` keywords are removed in HLSL 202x, with
compatibility warnings available for earlier language versions
[#8482](https://github.com/microsoft/DirectXShaderCompiler/issues/8482).
Expand Down
26 changes: 23 additions & 3 deletions lib/DXIL/DxilTypeSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "dxc/Support/Global.h"
#include "dxc/Support/WinFunctions.h"

#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/raw_ostream.h"
Expand Down Expand Up @@ -393,6 +394,21 @@ DxilTypeSystem::AddStructAnnotation(const StructType *pStructType,
return pA;
}

static bool ContainsString(const Type *Ty,
SmallPtrSetImpl<const Type *> &CheckedTypes) {
if (!CheckedTypes.insert(Ty).second)
return false;
if (Ty->isPointerTy())
return Ty->getPointerElementType()->isIntegerTy(8);
if (auto *AT = dyn_cast<ArrayType>(Ty))
return ContainsString(AT->getElementType(), CheckedTypes);
if (auto *ST = dyn_cast<StructType>(Ty))
for (Type *Element : ST->elements())
if (ContainsString(Element, CheckedTypes))
return true;
return false;
}

void DxilTypeSystem::FinishStructAnnotation(DxilStructAnnotation &SA) {
const llvm::StructType *ST = SA.GetStructType();
DXASSERT(SA.GetNumFields() == ST->getNumElements(),
Expand All @@ -411,9 +427,13 @@ void DxilTypeSystem::FinishStructAnnotation(DxilStructAnnotation &SA) {
SA.SetContainsTargetTypes();
}

// Mark if empty
if (SA.GetCBufferSize() == 0)
SA.MarkEmptyStruct();
// Zero cbuffer-layout size does not imply an empty struct:
// string-only aggregates still contain values that must be copied.
if (SA.GetCBufferSize() == 0) {
SmallPtrSet<const Type *, 8> CheckedTypes;
if (!ContainsString(ST, CheckedTypes))
SA.MarkEmptyStruct();
}
}

DxilStructAnnotation *
Expand Down
9 changes: 9 additions & 0 deletions lib/HLSL/HLLegalizeParameter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,15 @@ bool HLLegalizeParameter::runOnModule(Module &M) {

void HLLegalizeParameter::patchWriteOnInParam(Function &F, Argument &Arg,
const DataLayout &DL) {
// Skip i8 pointer arguments, these should only occur for strings.
// Note: this is an utter disaster if we ever want to support i8 data types in
// HLSL. So that will be fun...
if (Arg.getType()->isPointerTy()) {
Type *EltTy = Arg.getType()->getPointerElementType();
if (EltTy->isIntegerTy() && EltTy->getIntegerBitWidth() == 8)
return;
}

// TODO: Adding lifetime intrinsics isn't easy here, have to analyze uses.
Type *Ty = Arg.getType()->getPointerElementType();
AllocaInst *temp = createAllocaForPatch(F, Ty);
Expand Down
2 changes: 1 addition & 1 deletion tools/clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -849,8 +849,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
CanQualType Min12IntTy, Min10FloatTy;
CanQualType LitIntTy, LitFloatTy;
CanQualType HalfFloatTy, Min16FloatTy, Min16IntTy, Min16UIntTy;
CanQualType HLSLStringTy;
CanQualType Int8_4PackedTy, UInt8_4PackedTy;
QualType HLSLStringTy;
CanQualType LinAlgMatrixTy;
// HLSL Changes end

Expand Down
2 changes: 1 addition & 1 deletion tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -7908,7 +7908,7 @@ def err_hlsl_missing_attr: Error<
def err_hlsl_missing_inout_attr: Error<
"stream-output object must be an inout parameter">;
def err_hlsl_unsupported_string_decl: Error<
"%select{array|parameter|return value}0 of type string is not supported">;
"%select{array|parameter|return value|field}0 of type string is not supported">;
def err_hlsl_missing_out_attr: Error<
"%0 object must be an out parameter">;
def err_hlsl_missing_in_attr: Error<
Expand Down
4 changes: 3 additions & 1 deletion tools/clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1110,7 +1110,9 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) {
InitBuiltinType(UInt8_4PackedTy, BuiltinType::UInt8_4Packed);
InitBuiltinType(LinAlgMatrixTy, BuiltinType::LinAlgMatrix);

HLSLStringTy = this->getPointerType(CharTy);
// This shouldn't actually be a canonical type, since it effectively must be
// const.
HLSLStringTy = this->getPointerType(CharTy.withConst());

hlsl::InitializeASTContextForHLSL(*this); // Previously in constructor, guarded by !DelayInitialization
}
Expand Down
10 changes: 6 additions & 4 deletions tools/clang/lib/CodeGen/CGDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,18 @@
//
//===----------------------------------------------------------------------===//

#include "CodeGenFunction.h"
#include "CGCleanup.h"
#include "CGDebugInfo.h"
#include "CGHLSLRuntime.h" // HLSL Change
#include "CGOpenCLRuntime.h"
#include "CodeGenFunction.h" // HLSL Change (clang-format)
#include "CodeGenModule.h"
#include "dxc/DXIL/DxilMetadataHelper.h" // HLSL Change
#include "clang/AST/ASTContext.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/HlslTypes.h" // HLSL Change
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/CGFunctionInfo.h"
Expand All @@ -28,8 +31,6 @@
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Type.h"
#include "CGHLSLRuntime.h" // HLSL Change
#include "dxc/DXIL/DxilMetadataHelper.h" // HLSL Change
using namespace clang;
using namespace CodeGen;

Expand Down Expand Up @@ -1773,7 +1774,8 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg,
}
} else {
// HLSL Change Starts
if (getLangOpts().HLSL && Arg->getType()->isPointerTy()) {
if (getLangOpts().HLSL && Arg->getType()->isPointerTy() &&
!hlsl::IsStringType(Ty)) {
// HLSL doesn't have pointer.
// Only case pointer type will generated is this pointer for methods.
// Don't store this pointer, just use the parameter directly.
Expand Down
48 changes: 41 additions & 7 deletions tools/clang/lib/CodeGen/CGHLSLMS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4157,6 +4157,12 @@ void CGMSHLSLRuntime::FlattenValToInitList(CodeGenFunction &CGF,
CGBuilderTy &Builder = CGF.Builder;
llvm::Type *valTy = val->getType();

if (hlsl::IsStringType(Ty) && valTy == CGF.ConvertType(Ty)) {
elts.emplace_back(val);
eltTys.emplace_back(Ty);
return;
Comment thread
llvm-beanz marked this conversation as resolved.
Resolved
}

if (valTy->isPointerTy()) {
llvm::Type *valEltTy = valTy->getPointerElementType();
if (valEltTy->isVectorTy() || valEltTy->isSingleValueType()) {
Expand Down Expand Up @@ -4347,6 +4353,9 @@ static void AddMissingCastOpsInInitList(SmallVector<Value *, 4> &elts,
for (FieldDecl *field : RD->fields())
AddMissingCastOpsInInitList(elts, eltTys, idx, field->getType(), CGF);
}
} else if (IsStringType(Ty)) {
DXASSERT_NOMSG(IsStringType(eltTys[idx]));
idx++;
} else {
// Basic type.
elts[idx] = ConvertScalarOrVector(CGF, elts[idx], eltTys[idx], Ty);
Expand Down Expand Up @@ -4743,8 +4752,8 @@ static void FlatConstToList(CodeGenTypes &Types, bool bDefaultRowMajor,
EltVals, EltQualTys);
}
} else {
// At this point, we should have scalars in their memory representation
DXASSERT_NOMSG(QualTy->isBuiltinType());
// Scalar leaves, including string pointers, are in memory representation.
DXASSERT_NOMSG(QualTy->isBuiltinType() || hlsl::IsStringType(QualTy));
EltVals.emplace_back(C);
EltQualTys.emplace_back(QualTy);
}
Expand Down Expand Up @@ -4922,11 +4931,16 @@ static Constant *BuildConstInitializer(CodeGenTypes &Types,
return BuildConstStruct(Types, bDefaultRowMajor, QualTy, EltVals,
EltQualTys, EltIdx);
} else {
DXASSERT_NOMSG(QualTy->isBuiltinType());
DXASSERT_NOMSG(QualTy->isBuiltinType() || hlsl::IsStringType(QualTy));
Constant *EltVal = EltVals[EltIdx];
QualType EltQualTy = EltQualTys[EltIdx];
EltIdx++;

if (hlsl::IsStringType(QualTy)) {
DXASSERT_NOMSG(hlsl::IsStringType(EltQualTy));
return EltVal;
}

// Initializer constants are in their memory representation.
if (EltQualTy == QualTy && MemRepr)
return EltVal;
Expand Down Expand Up @@ -5549,7 +5563,10 @@ void CGMSHLSLRuntime::FlattenAggregatePtrToGepList(
CodeGenFunction &CGF, Value *Ptr, SmallVector<Value *, 4> &idxList,
clang::QualType Type, llvm::Type *Ty, SmallVector<Value *, 4> &GepList,
SmallVector<QualType, 4> &EltTyList) {
if (llvm::PointerType *PT = dyn_cast<llvm::PointerType>(Ty)) {
if (hlsl::IsStringType(Type) && Ty == CGF.ConvertType(Type)) {
GepList.push_back(CGF.Builder.CreateInBoundsGEP(Ptr, idxList));
EltTyList.push_back(Type);
} else if (llvm::PointerType *PT = dyn_cast<llvm::PointerType>(Ty)) {
Constant *idx = Constant::getIntegerValue(
IntegerType::get(Ty->getContext(), 32), APInt(32, 0));
idxList.emplace_back(idx);
Expand Down Expand Up @@ -5673,8 +5690,10 @@ void CGMSHLSLRuntime::LoadElements(CodeGenFunction &CGF, ArrayRef<Value *> Ptrs,
for (size_t i = 0, e = Ptrs.size(); i < e; i++) {
Value *Ptr = Ptrs[i];
llvm::Type *Ty = Ptr->getType()->getPointerElementType();
DXASSERT_LOCALVAR(Ty, Ty->isIntegerTy() || Ty->isFloatingPointTy(),
"Expected only element types.");
DXASSERT_LOCALVAR(Ty,
Ty->isIntegerTy() || Ty->isFloatingPointTy() ||
hlsl::IsStringType(QualTys[i]),
"Expected only element types or strings.");
Value *Val = CGF.Builder.CreateLoad(Ptr);
Val = CGF.EmitFromMemory(Val, QualTys[i]);
Vals.push_back(Val);
Expand All @@ -5691,6 +5710,11 @@ void CGMSHLSLRuntime::ConvertAndStoreElements(CodeGenFunction &CGF,
QualType DstQualTy = DstQualTys[i];
Value *SrcVal = SrcVals[i];
QualType SrcQualTy = SrcQualTys[i];
if (hlsl::IsStringType(DstQualTy)) {
DXASSERT_NOMSG(hlsl::IsStringType(SrcQualTy));
CGF.Builder.CreateStore(SrcVal, DstPtr);
Comment on lines +5713 to +5715
continue;
}
DXASSERT(SrcVal->getType()->isIntegerTy() ||
SrcVal->getType()->isFloatingPointTy(),
"Expected only element types.");
Expand Down Expand Up @@ -6002,6 +6026,12 @@ static void SimpleFlatValCopy(CodeGenFunction &CGF, Value *SrcVal,
DXASSERT(DstTy == CGF.ConvertTypeForMem(DstQualTy),
"QualType/Type mismatch!");

if (hlsl::IsStringType(DstQualTy)) {
DXASSERT_NOMSG(hlsl::IsStringType(SrcQualTy));
CGF.Builder.CreateStore(SrcVal, DstPtr);
return;
}

llvm::VectorType *DstVecTy = dyn_cast<llvm::VectorType>(DstTy);
QualType DstScalarQualTy = DstQualTy;
if (DstVecTy) {
Expand Down Expand Up @@ -6030,7 +6060,11 @@ void CGMSHLSLRuntime::EmitHLSLSplat(CodeGenFunction &CGF, Value *SrcVal,
SmallVector<Value *, 4> &idxList,
QualType Type, QualType SrcType,
llvm::Type *Ty) {
if (llvm::PointerType *PT = dyn_cast<llvm::PointerType>(Ty)) {
if (hlsl::IsStringType(Type) && Ty == CGF.ConvertType(Type)) {
DXASSERT_NOMSG(hlsl::IsStringType(SrcType));
Value *DestGEP = CGF.Builder.CreateInBoundsGEP(DestPtr, idxList);
CGF.Builder.CreateStore(SrcVal, DestGEP);
} else if (llvm::PointerType *PT = dyn_cast<llvm::PointerType>(Ty)) {
idxList.emplace_back(CGF.Builder.getInt32(0));

EmitHLSLSplat(CGF, SrcVal, DestPtr, idxList, Type, SrcType,
Expand Down
8 changes: 8 additions & 0 deletions tools/clang/lib/SPIRV/DeclResultIdMapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1432,11 +1432,19 @@ DeclResultIdMapper::createOrUpdateStringVar(const VarDecl *var) {
// generate an OpString for it.
if (!var->hasInit()) {
emitError("Found uninitialized string variable.", var->getLocation());
registerVariableForDecl(var, createDeclSpirvInfo(spvBuilder.getString("")));
return nullptr;
}

const StringLiteral *stringLiteral =
dyn_cast<StringLiteral>(var->getInit()->IgnoreParenCasts());
if (!stringLiteral) {
emitError(
"string variable initializer must be a string literal with -spirv",
var->getInit()->getExprLoc());
registerVariableForDecl(var, createDeclSpirvInfo(spvBuilder.getString("")));
return nullptr;
}
SpirvString *init = spvBuilder.getString(stringLiteral->getString());
registerVariableForDecl(var, createDeclSpirvInfo(init));
return init;
Expand Down
15 changes: 13 additions & 2 deletions tools/clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10381,9 +10381,10 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
// HLSL Change Starts
if (getLangOpts().HLSL) {
const bool IsParm = true;
if (hlsl::IsStringType(parmDeclType)) {
if (getLangOpts().SPIRV && hlsl::IsStringType(parmDeclType)) {
static const unsigned selectParamIdx = 1;
Diag(D.getLocStart(), diag::err_hlsl_unsupported_string_decl) << selectParamIdx;
Diag(D.getLocStart(), diag::err_hlsl_unsupported_string_decl)
<< selectParamIdx;
D.setInvalidType();
}
if (!DiagnoseHLSLDecl(D, Context.getTranslationUnitDecl(), /*BitWidth*/ nullptr, TInfo, IsParm)) {
Expand Down Expand Up @@ -12919,6 +12920,16 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
T = Context.IntTy;
}

// HLSL Change Starts
if (!InvalidDecl && getLangOpts().HLSL && getLangOpts().SPIRV &&
hlsl::IsStringType(T)) {
static const unsigned selectFieldIdx = 3;
Diag(Loc, diag::err_hlsl_unsupported_string_decl) << selectFieldIdx;
Record->setInvalidDecl();
InvalidDecl = true;
}
// HLSL Change Ends

QualType EltTy = Context.getBaseElementType(T);
if (!EltTy->isDependentType()) {
if (RequireCompleteType(Loc, EltTy, diag::err_field_incomplete)) {
Expand Down
Loading
Loading