1 //===--- HLSLExternalSemaSource.cpp - HLSL Sema Source --------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 //
10 //===----------------------------------------------------------------------===//
11
12 #include "clang/Sema/HLSLExternalSemaSource.h"
13 #include "clang/AST/ASTContext.h"
14 #include "clang/AST/DeclCXX.h"
15 #include "clang/Basic/AttrKinds.h"
16 #include "clang/Sema/Sema.h"
17
18 using namespace clang;
19
~HLSLExternalSemaSource()20 HLSLExternalSemaSource::~HLSLExternalSemaSource() {}
21
InitializeSema(Sema & S)22 void HLSLExternalSemaSource::InitializeSema(Sema &S) {
23 SemaPtr = &S;
24 ASTContext &AST = SemaPtr->getASTContext();
25 IdentifierInfo &HLSL = AST.Idents.get("hlsl", tok::TokenKind::identifier);
26 HLSLNamespace =
27 NamespaceDecl::Create(AST, AST.getTranslationUnitDecl(), false,
28 SourceLocation(), SourceLocation(), &HLSL, nullptr);
29 HLSLNamespace->setImplicit(true);
30 AST.getTranslationUnitDecl()->addDecl(HLSLNamespace);
31 defineHLSLVectorAlias();
32
33 // This adds a `using namespace hlsl` directive. In DXC, we don't put HLSL's
34 // built in types inside a namespace, but we are planning to change that in
35 // the near future. In order to be source compatible older versions of HLSL
36 // will need to implicitly use the hlsl namespace. For now in clang everything
37 // will get added to the namespace, and we can remove the using directive for
38 // future language versions to match HLSL's evolution.
39 auto *UsingDecl = UsingDirectiveDecl::Create(
40 AST, AST.getTranslationUnitDecl(), SourceLocation(), SourceLocation(),
41 NestedNameSpecifierLoc(), SourceLocation(), HLSLNamespace,
42 AST.getTranslationUnitDecl());
43
44 AST.getTranslationUnitDecl()->addDecl(UsingDecl);
45 }
46
defineHLSLVectorAlias()47 void HLSLExternalSemaSource::defineHLSLVectorAlias() {
48 ASTContext &AST = SemaPtr->getASTContext();
49
50 llvm::SmallVector<NamedDecl *> TemplateParams;
51
52 auto *TypeParam = TemplateTypeParmDecl::Create(
53 AST, HLSLNamespace, SourceLocation(), SourceLocation(), 0, 0,
54 &AST.Idents.get("element", tok::TokenKind::identifier), false, false);
55 TypeParam->setDefaultArgument(AST.getTrivialTypeSourceInfo(AST.FloatTy));
56
57 TemplateParams.emplace_back(TypeParam);
58
59 auto *SizeParam = NonTypeTemplateParmDecl::Create(
60 AST, HLSLNamespace, SourceLocation(), SourceLocation(), 0, 1,
61 &AST.Idents.get("element_count", tok::TokenKind::identifier), AST.IntTy,
62 false, AST.getTrivialTypeSourceInfo(AST.IntTy));
63 Expr *LiteralExpr =
64 IntegerLiteral::Create(AST, llvm::APInt(AST.getIntWidth(AST.IntTy), 4),
65 AST.IntTy, SourceLocation());
66 SizeParam->setDefaultArgument(LiteralExpr);
67 TemplateParams.emplace_back(SizeParam);
68
69 auto *ParamList =
70 TemplateParameterList::Create(AST, SourceLocation(), SourceLocation(),
71 TemplateParams, SourceLocation(), nullptr);
72
73 IdentifierInfo &II = AST.Idents.get("vector", tok::TokenKind::identifier);
74
75 QualType AliasType = AST.getDependentSizedExtVectorType(
76 AST.getTemplateTypeParmType(0, 0, false, TypeParam),
77 DeclRefExpr::Create(
78 AST, NestedNameSpecifierLoc(), SourceLocation(), SizeParam, false,
79 DeclarationNameInfo(SizeParam->getDeclName(), SourceLocation()),
80 AST.IntTy, VK_LValue),
81 SourceLocation());
82
83 auto *Record = TypeAliasDecl::Create(AST, HLSLNamespace, SourceLocation(),
84 SourceLocation(), &II,
85 AST.getTrivialTypeSourceInfo(AliasType));
86 Record->setImplicit(true);
87
88 auto *Template =
89 TypeAliasTemplateDecl::Create(AST, HLSLNamespace, SourceLocation(),
90 Record->getIdentifier(), ParamList, Record);
91
92 Record->setDescribedAliasTemplate(Template);
93 Template->setImplicit(true);
94 Template->setLexicalDeclContext(Record->getDeclContext());
95 HLSLNamespace->addDecl(Template);
96 }
97