Skip to content

Commit 39ddfd8

Browse files
authored
Merge branch 'main' into users/xlauko/cir-cast-op-format
2 parents 2c17b86 + 6e0d519 commit 39ddfd8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1463
-736
lines changed

clang/docs/OpenMPSupport.rst

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -580,9 +580,12 @@ implementation.
580580
| need_device_addr modifier for adjust_args clause | :part:`partial` | :none:`unclaimed` | Parsing/Sema: https://github.com/llvm/llvm-project/pull/143442 |
581581
| | | | https://github.com/llvm/llvm-project/pull/149586 |
582582
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
583-
| Prescriptive num_threads | :part:`In Progress` | :none:`unclaimed` | ro-i |
583+
| Prescriptive num_threads | :good:`done` | :none:`unclaimed` | https://github.com/llvm/llvm-project/pull/160659 |
584+
| | | | https://github.com/llvm/llvm-project/pull/146403 |
585+
| | | | https://github.com/llvm/llvm-project/pull/146404 |
586+
| | | | https://github.com/llvm/llvm-project/pull/146405 |
584587
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
585-
| Message and severity clauses | :part:`In Progress` | :none:`unclaimed` | ro-i |
588+
| Message and severity clauses | :good:`done` | :none:`unclaimed` | https://github.com/llvm/llvm-project/pull/146093 |
586589
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
587590
| Local clause on declare target | :part:`In Progress` | :none:`unclaimed` | |
588591
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
//===- HLSLResource.h - Routines for HLSL resources and bindings ----------===//
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+
// This file provides shared routines to help analyze HLSL resources and
10+
// theirs bindings during Sema and CodeGen.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef LLVM_CLANG_AST_HLSLRESOURCE_H
15+
#define LLVM_CLANG_AST_HLSLRESOURCE_H
16+
17+
#include "clang/AST/ASTContext.h"
18+
#include "clang/AST/Attr.h"
19+
#include "clang/AST/Attrs.inc"
20+
#include "clang/AST/DeclBase.h"
21+
#include "clang/Basic/TargetInfo.h"
22+
#include "clang/Support/Compiler.h"
23+
#include "llvm/Support/raw_ostream.h"
24+
25+
namespace clang {
26+
27+
class HLSLResourceBindingAttr;
28+
class HLSLRVkBindingAttr;
29+
30+
namespace hlsl {
31+
32+
struct ResourceBindingAttrs {
33+
HLSLResourceBindingAttr *RegBinding;
34+
HLSLVkBindingAttr *VkBinding;
35+
36+
ResourceBindingAttrs(const Decl *D) {
37+
RegBinding = D->getAttr<HLSLResourceBindingAttr>();
38+
bool IsSpirv = D->getASTContext().getTargetInfo().getTriple().isSPIRV();
39+
VkBinding = IsSpirv ? D->getAttr<HLSLVkBindingAttr>() : nullptr;
40+
}
41+
42+
bool hasBinding() const { return RegBinding || VkBinding; }
43+
bool isExplicit() const {
44+
return (RegBinding && RegBinding->hasRegisterSlot()) || VkBinding;
45+
}
46+
47+
unsigned getSlot() const {
48+
assert(isExplicit() && "no explicit binding");
49+
if (VkBinding)
50+
return VkBinding->getBinding();
51+
if (RegBinding && RegBinding->hasRegisterSlot())
52+
return RegBinding->getSlotNumber();
53+
llvm_unreachable("no explicit binding");
54+
}
55+
56+
unsigned getSpace() const {
57+
if (VkBinding)
58+
return VkBinding->getSet();
59+
if (RegBinding)
60+
return RegBinding->getSpaceNumber();
61+
return 0;
62+
}
63+
64+
bool hasImplicitOrderID() const {
65+
return RegBinding && RegBinding->hasImplicitBindingOrderID();
66+
}
67+
68+
unsigned getImplicitOrderID() const {
69+
assert(hasImplicitOrderID());
70+
return RegBinding->getImplicitBindingOrderID();
71+
}
72+
};
73+
74+
} // namespace hlsl
75+
76+
} // namespace clang
77+
78+
#endif // LLVM_CLANG_AST_HLSLRESOURCE_H

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,6 @@ struct MissingFeatures {
248248
static bool metaDataNode() { return false; }
249249
static bool moduleNameHash() { return false; }
250250
static bool msabi() { return false; }
251-
static bool needsGlobalCtorDtor() { return false; }
252251
static bool nrvo() { return false; }
253252
static bool objCBlocks() { return false; }
254253
static bool objCGC() { return false; }

clang/include/clang/Driver/CommonArgs.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,11 @@ std::string complexRangeKindToStr(LangOptions::ComplexRangeKind Range);
304304
// Render a frontend option corresponding to ComplexRangeKind.
305305
std::string renderComplexRangeOption(LangOptions::ComplexRangeKind Range);
306306

307+
// Set the complex range and output a warning as needed.
308+
void setComplexRange(const Driver &D, StringRef NewOpt,
309+
LangOptions::ComplexRangeKind NewRange, StringRef &LastOpt,
310+
LangOptions::ComplexRangeKind &Range);
311+
307312
} // end namespace tools
308313
} // end namespace driver
309314
} // end namespace clang

clang/lib/CIR/CodeGen/CIRGenCXX.cpp

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,89 @@
1515

1616
#include "clang/AST/GlobalDecl.h"
1717
#include "clang/CIR/MissingFeatures.h"
18+
#include "llvm/Support/SaveAndRestore.h"
1819

1920
using namespace clang;
2021
using namespace clang::CIRGen;
2122

23+
static void emitDeclInit(CIRGenFunction &cgf, const VarDecl *varDecl,
24+
cir::GlobalOp globalOp) {
25+
assert((varDecl->hasGlobalStorage() ||
26+
(varDecl->hasLocalStorage() &&
27+
cgf.getContext().getLangOpts().OpenCLCPlusPlus)) &&
28+
"VarDecl must have global or local (in the case of OpenCL) storage!");
29+
assert(!varDecl->getType()->isReferenceType() &&
30+
"Should not call emitDeclInit on a reference!");
31+
32+
CIRGenBuilderTy &builder = cgf.getBuilder();
33+
34+
// Set up the ctor region.
35+
mlir::OpBuilder::InsertionGuard guard(builder);
36+
mlir::Block *block = builder.createBlock(&globalOp.getCtorRegion());
37+
CIRGenFunction::LexicalScope lexScope{cgf, globalOp.getLoc(),
38+
builder.getInsertionBlock()};
39+
lexScope.setAsGlobalInit();
40+
builder.setInsertionPointToStart(block);
41+
42+
Address declAddr(cgf.cgm.getAddrOfGlobalVar(varDecl),
43+
cgf.cgm.getASTContext().getDeclAlign(varDecl));
44+
45+
QualType type = varDecl->getType();
46+
LValue lv = cgf.makeAddrLValue(declAddr, type);
47+
48+
const Expr *init = varDecl->getInit();
49+
switch (CIRGenFunction::getEvaluationKind(type)) {
50+
case cir::TEK_Scalar:
51+
assert(!cir::MissingFeatures::objCGC());
52+
cgf.emitScalarInit(init, cgf.getLoc(varDecl->getLocation()), lv, false);
53+
break;
54+
case cir::TEK_Complex:
55+
cgf.cgm.errorNYI(varDecl->getSourceRange(), "complex global initializer");
56+
break;
57+
case cir::TEK_Aggregate:
58+
assert(!cir::MissingFeatures::aggValueSlotGC());
59+
cgf.emitAggExpr(init,
60+
AggValueSlot::forLValue(lv, AggValueSlot::IsDestructed,
61+
AggValueSlot::IsNotAliased,
62+
AggValueSlot::DoesNotOverlap));
63+
break;
64+
}
65+
66+
// Finish the ctor region.
67+
builder.setInsertionPointToEnd(block);
68+
cir::YieldOp::create(builder, globalOp.getLoc());
69+
}
70+
71+
static void emitDeclDestroy(CIRGenFunction &cgf, const VarDecl *vd,
72+
cir::GlobalOp addr) {
73+
// Honor __attribute__((no_destroy)) and bail instead of attempting
74+
// to emit a reference to a possibly nonexistent destructor, which
75+
// in turn can cause a crash. This will result in a global constructor
76+
// that isn't balanced out by a destructor call as intended by the
77+
// attribute. This also checks for -fno-c++-static-destructors and
78+
// bails even if the attribute is not present.
79+
QualType::DestructionKind dtorKind = vd->needsDestruction(cgf.getContext());
80+
81+
// FIXME: __attribute__((cleanup)) ?
82+
83+
switch (dtorKind) {
84+
case QualType::DK_none:
85+
return;
86+
87+
case QualType::DK_cxx_destructor:
88+
break;
89+
90+
case QualType::DK_objc_strong_lifetime:
91+
case QualType::DK_objc_weak_lifetime:
92+
case QualType::DK_nontrivial_c_struct:
93+
// We don't care about releasing objects during process teardown.
94+
assert(!vd->getTLSKind() && "should have rejected this");
95+
return;
96+
}
97+
98+
cgf.cgm.errorNYI(vd->getSourceRange(), "global with destructor");
99+
}
100+
22101
cir::FuncOp CIRGenModule::codegenCXXStructor(GlobalDecl gd) {
23102
const CIRGenFunctionInfo &fnInfo =
24103
getTypes().arrangeCXXStructorDeclaration(gd);
@@ -38,3 +117,63 @@ cir::FuncOp CIRGenModule::codegenCXXStructor(GlobalDecl gd) {
38117
assert(!cir::MissingFeatures::opFuncAttributesForDefinition());
39118
return fn;
40119
}
120+
121+
// Global variables requiring non-trivial initialization are handled
122+
// differently in CIR than in classic codegen. Classic codegen emits
123+
// a global init function (__cxx_global_var_init) and inserts
124+
// initialization for each global there. In CIR, we attach a ctor
125+
// region to the global variable and insert the initialization code
126+
// into the ctor region. This will be moved into the
127+
// __cxx_global_var_init function during the LoweringPrepare pass.
128+
void CIRGenModule::emitCXXGlobalVarDeclInit(const VarDecl *varDecl,
129+
cir::GlobalOp addr,
130+
bool performInit) {
131+
QualType ty = varDecl->getType();
132+
133+
// TODO: handle address space
134+
// The address space of a static local variable (addr) may be different
135+
// from the address space of the "this" argument of the constructor. In that
136+
// case, we need an addrspacecast before calling the constructor.
137+
//
138+
// struct StructWithCtor {
139+
// __device__ StructWithCtor() {...}
140+
// };
141+
// __device__ void foo() {
142+
// __shared__ StructWithCtor s;
143+
// ...
144+
// }
145+
//
146+
// For example, in the above CUDA code, the static local variable s has a
147+
// "shared" address space qualifier, but the constructor of StructWithCtor
148+
// expects "this" in the "generic" address space.
149+
assert(!cir::MissingFeatures::addressSpace());
150+
151+
// Create a CIRGenFunction to emit the initializer. While this isn't a true
152+
// function, the handling works the same way.
153+
CIRGenFunction cgf{*this, builder, true};
154+
llvm::SaveAndRestore<CIRGenFunction *> savedCGF(curCGF, &cgf);
155+
curCGF->curFn = addr;
156+
157+
CIRGenFunction::SourceLocRAIIObject fnLoc{cgf,
158+
getLoc(varDecl->getLocation())};
159+
160+
assert(!cir::MissingFeatures::astVarDeclInterface());
161+
162+
if (!ty->isReferenceType()) {
163+
assert(!cir::MissingFeatures::openMP());
164+
165+
bool needsDtor = varDecl->needsDestruction(getASTContext()) ==
166+
QualType::DK_cxx_destructor;
167+
// PerformInit, constant store invariant / destroy handled below.
168+
if (performInit)
169+
emitDeclInit(cgf, varDecl, addr);
170+
171+
if (varDecl->getType().isConstantStorage(getASTContext(), true, !needsDtor))
172+
errorNYI(varDecl->getSourceRange(), "global with constant storage");
173+
else
174+
emitDeclDestroy(cgf, varDecl, addr);
175+
return;
176+
}
177+
178+
errorNYI(varDecl->getSourceRange(), "global with reference type");
179+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//===----------------------------------------------------------------------===//
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+
// This contains code dealing with code generation of C++ declarations
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "CIRGenModule.h"
14+
#include "clang/AST/Attr.h"
15+
#include "clang/Basic/LangOptions.h"
16+
17+
using namespace clang;
18+
using namespace clang::CIRGen;
19+
20+
void CIRGenModule::emitCXXGlobalVarDeclInitFunc(const VarDecl *vd,
21+
cir::GlobalOp addr,
22+
bool performInit) {
23+
assert(!cir::MissingFeatures::cudaSupport());
24+
25+
assert(!cir::MissingFeatures::deferredCXXGlobalInit());
26+
27+
emitCXXGlobalVarDeclInit(vd, addr, performInit);
28+
}

clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -775,7 +775,9 @@ class ConstExprEmitter
775775
}
776776

777777
mlir::Attribute VisitCXXConstructExpr(CXXConstructExpr *e, QualType ty) {
778-
cgm.errorNYI(e->getBeginLoc(), "ConstExprEmitter::VisitCXXConstructExpr");
778+
if (!e->getConstructor()->isTrivial())
779+
return nullptr;
780+
cgm.errorNYI(e->getBeginLoc(), "trivial constructor const handling");
779781
return {};
780782
}
781783

clang/lib/CIR/CodeGen/CIRGenFunction.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -342,10 +342,12 @@ void CIRGenFunction::LexicalScope::cleanup() {
342342
cir::ReturnOp CIRGenFunction::LexicalScope::emitReturn(mlir::Location loc) {
343343
CIRGenBuilderTy &builder = cgf.getBuilder();
344344

345-
if (!cgf.curFn.getFunctionType().hasVoidReturn()) {
345+
auto fn = dyn_cast<cir::FuncOp>(cgf.curFn);
346+
assert(fn && "emitReturn from non-function");
347+
if (!fn.getFunctionType().hasVoidReturn()) {
346348
// Load the value from `__retval` and return it via the `cir.return` op.
347349
auto value = builder.create<cir::LoadOp>(
348-
loc, cgf.curFn.getFunctionType().getReturnType(), *cgf.fnRetAlloca);
350+
loc, fn.getFunctionType().getReturnType(), *cgf.fnRetAlloca);
349351
return builder.create<cir::ReturnOp>(loc,
350352
llvm::ArrayRef(value.getResult()));
351353
}
@@ -459,7 +461,9 @@ void CIRGenFunction::startFunction(GlobalDecl gd, QualType returnType,
459461
const auto *md = cast<CXXMethodDecl>(d);
460462
if (md->getParent()->isLambda() && md->getOverloadedOperator() == OO_Call) {
461463
// We're in a lambda.
462-
curFn.setLambda(true);
464+
auto fn = dyn_cast<cir::FuncOp>(curFn);
465+
assert(fn && "lambda in non-function region");
466+
fn.setLambda(true);
463467

464468
// Figure out the captures.
465469
md->getParent()->getCaptureFields(lambdaCaptureFields,

clang/lib/CIR/CodeGen/CIRGenFunction.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,10 @@ class CIRGenFunction : public CIRGenTypeCache {
9898
/// This is the inner-most code context, which includes blocks.
9999
const clang::Decl *curCodeDecl = nullptr;
100100

101-
/// The function for which code is currently being generated.
102-
cir::FuncOp curFn;
101+
/// The current function or global initializer that is generated code for.
102+
/// This is usually a cir::FuncOp, but it can also be a cir::GlobalOp for
103+
/// global initializers.
104+
mlir::Operation *curFn = nullptr;
103105

104106
using DeclMapTy = llvm::DenseMap<const clang::Decl *, Address>;
105107
/// This keeps track of the CIR allocas or globals for local C
@@ -116,7 +118,11 @@ class CIRGenFunction : public CIRGenTypeCache {
116118
CIRGenModule &getCIRGenModule() { return cgm; }
117119
const CIRGenModule &getCIRGenModule() const { return cgm; }
118120

119-
mlir::Block *getCurFunctionEntryBlock() { return &curFn.getRegion().front(); }
121+
mlir::Block *getCurFunctionEntryBlock() {
122+
// We currently assume this isn't called for a global initializer.
123+
auto fn = mlir::cast<cir::FuncOp>(curFn);
124+
return &fn.getRegion().front();
125+
}
120126

121127
/// Sanitizers enabled for this function.
122128
clang::SanitizerSet sanOpts;

0 commit comments

Comments
 (0)