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