Skip to content

Commit cf165c5

Browse files
committed
Merge remote-tracking branch 'origin/main' into vplan-caniv-defined-by-region-dont-reset-start-value-tmp
2 parents d103bef + 82b5934 commit cf165c5

File tree

135 files changed

+18493
-415
lines changed

Some content is hidden

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

135 files changed

+18493
-415
lines changed

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ struct MissingFeatures {
119119
static bool opCallLandingPad() { return false; }
120120
static bool opCallContinueBlock() { return false; }
121121
static bool opCallChain() { return false; }
122+
static bool opCallExceptionAttr() { return false; }
122123

123124
// CXXNewExpr
124125
static bool exprNewNullCheck() { return false; }

clang/lib/Basic/Targets.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,8 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
222222
return std::make_unique<OHOSTargetInfo<ARMleTargetInfo>>(Triple, Opts);
223223
case llvm::Triple::FreeBSD:
224224
return std::make_unique<FreeBSDTargetInfo<ARMleTargetInfo>>(Triple, Opts);
225+
case llvm::Triple::Fuchsia:
226+
return std::make_unique<FuchsiaTargetInfo<ARMleTargetInfo>>(Triple, Opts);
225227
case llvm::Triple::NetBSD:
226228
return std::make_unique<NetBSDTargetInfo<ARMleTargetInfo>>(Triple, Opts);
227229
case llvm::Triple::OpenBSD:
@@ -254,6 +256,8 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
254256
return std::make_unique<AppleMachOARMTargetInfo>(Triple, Opts);
255257

256258
switch (os) {
259+
case llvm::Triple::Fuchsia:
260+
return std::make_unique<FuchsiaTargetInfo<ARMbeTargetInfo>>(Triple, Opts);
257261
case llvm::Triple::Linux:
258262
return std::make_unique<LinuxTargetInfo<ARMbeTargetInfo>>(Triple, Opts);
259263
case llvm::Triple::NetBSD:

clang/lib/Basic/Targets/ARM.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple,
260260
: TargetInfo(Triple), FPMath(FP_Default), IsAAPCS(true), LDREX(0),
261261
HW_FP(0) {
262262
bool IsFreeBSD = Triple.isOSFreeBSD();
263+
bool IsFuchsia = Triple.isOSFuchsia();
263264
bool IsOpenBSD = Triple.isOSOpenBSD();
264265
bool IsNetBSD = Triple.isOSNetBSD();
265266
bool IsHaiku = Triple.isOSHaiku();
@@ -332,7 +333,7 @@ ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple,
332333
default:
333334
if (IsNetBSD)
334335
setABI("apcs-gnu");
335-
else if (IsFreeBSD || IsOpenBSD || IsHaiku || IsOHOS)
336+
else if (IsFreeBSD || IsFuchsia || IsOpenBSD || IsHaiku || IsOHOS)
336337
setABI("aapcs-linux");
337338
else
338339
setABI("aapcs");

clang/lib/Basic/Targets/RISCV.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,11 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
192192
Builder.defineMacro("__riscv_muldiv");
193193
}
194194

195-
if (ISAInfo->hasExtension("a")) {
195+
// The "a" extension is composed of "zalrsc" and "zaamo"
196+
if (ISAInfo->hasExtension("a"))
196197
Builder.defineMacro("__riscv_atomic");
198+
199+
if (ISAInfo->hasExtension("zalrsc")) {
197200
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
198201
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
199202
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");

clang/lib/Basic/Targets/RISCV.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,8 @@ class LLVM_LIBRARY_VISIBILITY RISCV32TargetInfo : public RISCVTargetInfo {
195195
void setMaxAtomicWidth() override {
196196
MaxAtomicPromoteWidth = 128;
197197

198-
if (ISAInfo->hasExtension("a"))
198+
// "a" implies "zalrsc" which is sufficient to inline atomics
199+
if (ISAInfo->hasExtension("zalrsc"))
199200
MaxAtomicInlineWidth = 32;
200201
}
201202
};
@@ -225,7 +226,8 @@ class LLVM_LIBRARY_VISIBILITY RISCV64TargetInfo : public RISCVTargetInfo {
225226
void setMaxAtomicWidth() override {
226227
MaxAtomicPromoteWidth = 128;
227228

228-
if (ISAInfo->hasExtension("a"))
229+
// "a" implies "zalrsc" which is sufficient to inline atomics
230+
if (ISAInfo->hasExtension("zalrsc"))
229231
MaxAtomicInlineWidth = 64;
230232
}
231233
};

clang/lib/CIR/CodeGen/CIRGenCXXABI.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ CIRGenCXXABI::AddedStructorArgCounts CIRGenCXXABI::addImplicitConstructorArgs(
3737
addedArgs.suffix.size());
3838
}
3939

40+
CatchTypeInfo CIRGenCXXABI::getCatchAllTypeInfo() {
41+
return CatchTypeInfo{{}, 0};
42+
}
43+
4044
void CIRGenCXXABI::buildThisParam(CIRGenFunction &cgf,
4145
FunctionArgList &params) {
4246
const auto *md = cast<CXXMethodDecl>(cgf.curGD.getDecl());

clang/lib/CIR/CodeGen/CIRGenCXXABI.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#define LLVM_CLANG_LIB_CIR_CIRGENCXXABI_H
1616

1717
#include "CIRGenCall.h"
18+
#include "CIRGenCleanup.h"
1819
#include "CIRGenFunction.h"
1920
#include "CIRGenModule.h"
2021

@@ -155,6 +156,8 @@ class CIRGenCXXABI {
155156
/// Loads the incoming C++ this pointer as it was passed by the caller.
156157
mlir::Value loadIncomingCXXThis(CIRGenFunction &cgf);
157158

159+
virtual CatchTypeInfo getCatchAllTypeInfo();
160+
158161
/// Get the implicit (second) parameter that comes after the "this" pointer,
159162
/// or nullptr if there is isn't one.
160163
virtual mlir::Value getCXXDestructorImplicitParam(CIRGenFunction &cgf,

clang/lib/CIR/CodeGen/CIRGenCleanup.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,13 @@ void EHScopeStack::popCleanup() {
108108
assert(!cir::MissingFeatures::ehCleanupBranchFixups());
109109
}
110110

111+
EHCatchScope *EHScopeStack::pushCatch(unsigned numHandlers) {
112+
char *buffer = allocate(EHCatchScope::getSizeForNumHandlers(numHandlers));
113+
assert(!cir::MissingFeatures::innermostEHScope());
114+
EHCatchScope *scope = new (buffer) EHCatchScope(numHandlers);
115+
return scope;
116+
}
117+
111118
static void emitCleanup(CIRGenFunction &cgf, EHScopeStack::Cleanup *cleanup) {
112119
// Ask the cleanup to emit itself.
113120
assert(cgf.haveInsertPoint() && "expected insertion point");

clang/lib/CIR/CodeGen/CIRGenCleanup.h

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@
2020

2121
namespace clang::CIRGen {
2222

23+
/// The MS C++ ABI needs a pointer to RTTI data plus some flags to describe the
24+
/// type of a catch handler, so we use this wrapper.
25+
struct CatchTypeInfo {
26+
mlir::TypedAttr rtti;
27+
unsigned flags;
28+
};
29+
2330
/// A protected scope for zero-cost EH handling.
2431
class EHScope {
2532
class CommonBitFields {
@@ -29,6 +36,12 @@ class EHScope {
2936
enum { NumCommonBits = 3 };
3037

3138
protected:
39+
class CatchBitFields {
40+
friend class EHCatchScope;
41+
unsigned : NumCommonBits;
42+
unsigned numHandlers : 32 - NumCommonBits;
43+
};
44+
3245
class CleanupBitFields {
3346
friend class EHCleanupScope;
3447
unsigned : NumCommonBits;
@@ -58,6 +71,7 @@ class EHScope {
5871

5972
union {
6073
CommonBitFields commonBits;
74+
CatchBitFields catchBits;
6175
CleanupBitFields cleanupBits;
6276
};
6377

@@ -67,6 +81,71 @@ class EHScope {
6781
EHScope(Kind kind) { commonBits.kind = kind; }
6882

6983
Kind getKind() const { return static_cast<Kind>(commonBits.kind); }
84+
85+
bool mayThrow() const {
86+
// Traditional LLVM codegen also checks for `!block->use_empty()`, but
87+
// in CIRGen the block content is not important, just used as a way to
88+
// signal `hasEHBranches`.
89+
assert(!cir::MissingFeatures::ehstackBranches());
90+
return false;
91+
}
92+
};
93+
94+
/// A scope which attempts to handle some, possibly all, types of
95+
/// exceptions.
96+
///
97+
/// Objective C \@finally blocks are represented using a cleanup scope
98+
/// after the catch scope.
99+
100+
class EHCatchScope : public EHScope {
101+
// In effect, we have a flexible array member
102+
// Handler Handlers[0];
103+
// But that's only standard in C99, not C++, so we have to do
104+
// annoying pointer arithmetic instead.
105+
106+
public:
107+
struct Handler {
108+
/// A type info value, or null MLIR attribute for a catch-all
109+
CatchTypeInfo type;
110+
111+
/// The catch handler for this type.
112+
mlir::Region *region;
113+
};
114+
115+
private:
116+
friend class EHScopeStack;
117+
118+
Handler *getHandlers() { return reinterpret_cast<Handler *>(this + 1); }
119+
120+
public:
121+
static size_t getSizeForNumHandlers(unsigned n) {
122+
return sizeof(EHCatchScope) + n * sizeof(Handler);
123+
}
124+
125+
EHCatchScope(unsigned numHandlers) : EHScope(Catch) {
126+
catchBits.numHandlers = numHandlers;
127+
assert(catchBits.numHandlers == numHandlers && "NumHandlers overflow?");
128+
}
129+
130+
unsigned getNumHandlers() const { return catchBits.numHandlers; }
131+
132+
void setHandler(unsigned i, CatchTypeInfo type, mlir::Region *region) {
133+
assert(i < getNumHandlers());
134+
getHandlers()[i].type = type;
135+
getHandlers()[i].region = region;
136+
}
137+
138+
// Clear all handler blocks.
139+
// FIXME: it's better to always call clearHandlerBlocks in DTOR and have a
140+
// 'takeHandler' or some such function which removes ownership from the
141+
// EHCatchScope object if the handlers should live longer than EHCatchScope.
142+
void clearHandlerBlocks() {
143+
// The blocks are owned by TryOp, nothing to delete.
144+
}
145+
146+
static bool classof(const EHScope *scope) {
147+
return scope->getKind() == Catch;
148+
}
70149
};
71150

72151
/// A cleanup scope which generates the cleanup blocks lazily.
@@ -147,5 +226,13 @@ EHScopeStack::find(stable_iterator savePoint) const {
147226
return iterator(endOfBuffer - savePoint.size);
148227
}
149228

229+
inline void EHScopeStack::popCatch() {
230+
assert(!empty() && "popping exception stack when not empty");
231+
232+
EHCatchScope &scope = llvm::cast<EHCatchScope>(*begin());
233+
assert(!cir::MissingFeatures::innermostEHScope());
234+
deallocate(EHCatchScope::getSizeForNumHandlers(scope.getNumHandlers()));
235+
}
236+
150237
} // namespace clang::CIRGen
151238
#endif // CLANG_LIB_CIR_CODEGEN_CIRGENCLEANUP_H

clang/lib/CIR/CodeGen/CIRGenException.cpp

Lines changed: 149 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,153 @@ mlir::LogicalResult CIRGenFunction::emitCXXTryStmt(const CXXTryStmt &s) {
6969
if (s.getTryBlock()->body_empty())
7070
return mlir::LogicalResult::success();
7171

72-
cgm.errorNYI("exitCXXTryStmt: CXXTryStmt with non-empty body");
73-
return mlir::LogicalResult::success();
72+
mlir::Location loc = getLoc(s.getSourceRange());
73+
// Create a scope to hold try local storage for catch params.
74+
75+
mlir::OpBuilder::InsertPoint scopeIP;
76+
cir::ScopeOp::create(
77+
builder, loc,
78+
/*scopeBuilder=*/[&](mlir::OpBuilder &b, mlir::Location loc) {
79+
scopeIP = builder.saveInsertionPoint();
80+
});
81+
82+
mlir::OpBuilder::InsertionGuard guard(builder);
83+
builder.restoreInsertionPoint(scopeIP);
84+
mlir::LogicalResult result = emitCXXTryStmtUnderScope(s);
85+
cir::YieldOp::create(builder, loc);
86+
return result;
87+
}
88+
89+
mlir::LogicalResult
90+
CIRGenFunction::emitCXXTryStmtUnderScope(const CXXTryStmt &s) {
91+
const llvm::Triple &t = getTarget().getTriple();
92+
// If we encounter a try statement on in an OpenMP target region offloaded to
93+
// a GPU, we treat it as a basic block.
94+
const bool isTargetDevice =
95+
(cgm.getLangOpts().OpenMPIsTargetDevice && (t.isNVPTX() || t.isAMDGCN()));
96+
if (isTargetDevice) {
97+
cgm.errorNYI(
98+
"emitCXXTryStmtUnderScope: OpenMP target region offloaded to GPU");
99+
return mlir::success();
100+
}
101+
102+
unsigned numHandlers = s.getNumHandlers();
103+
mlir::Location tryLoc = getLoc(s.getBeginLoc());
104+
mlir::OpBuilder::InsertPoint beginInsertTryBody;
105+
106+
bool hasCatchAll = false;
107+
for (unsigned i = 0; i != numHandlers; ++i) {
108+
hasCatchAll |= s.getHandler(i)->getExceptionDecl() == nullptr;
109+
if (hasCatchAll)
110+
break;
111+
}
112+
113+
// Create the scope to represent only the C/C++ `try {}` part. However,
114+
// don't populate right away. Create regions for the catch handlers,
115+
// but don't emit the handler bodies yet. For now, only make sure the
116+
// scope returns the exception information.
117+
auto tryOp = cir::TryOp::create(
118+
builder, tryLoc,
119+
/*tryBuilder=*/
120+
[&](mlir::OpBuilder &b, mlir::Location loc) {
121+
beginInsertTryBody = builder.saveInsertionPoint();
122+
},
123+
/*handlersBuilder=*/
124+
[&](mlir::OpBuilder &b, mlir::Location loc,
125+
mlir::OperationState &result) {
126+
mlir::OpBuilder::InsertionGuard guard(b);
127+
128+
// We create an extra region for an unwind catch handler in case the
129+
// catch-all handler doesn't exists
130+
unsigned numRegionsToCreate =
131+
hasCatchAll ? numHandlers : numHandlers + 1;
132+
133+
for (unsigned i = 0; i != numRegionsToCreate; ++i) {
134+
mlir::Region *region = result.addRegion();
135+
builder.createBlock(region);
136+
}
137+
});
138+
139+
// Finally emit the body for try/catch.
140+
{
141+
mlir::Location loc = tryOp.getLoc();
142+
mlir::OpBuilder::InsertionGuard guard(builder);
143+
builder.restoreInsertionPoint(beginInsertTryBody);
144+
CIRGenFunction::LexicalScope tryScope{*this, loc,
145+
builder.getInsertionBlock()};
146+
147+
tryScope.setAsTry(tryOp);
148+
149+
// Attach the basic blocks for the catch regions.
150+
enterCXXTryStmt(s, tryOp);
151+
152+
// Emit the body for the `try {}` part.
153+
{
154+
mlir::OpBuilder::InsertionGuard guard(builder);
155+
CIRGenFunction::LexicalScope tryBodyScope{*this, loc,
156+
builder.getInsertionBlock()};
157+
if (emitStmt(s.getTryBlock(), /*useCurrentScope=*/true).failed())
158+
return mlir::failure();
159+
}
160+
161+
// Emit catch clauses.
162+
exitCXXTryStmt(s);
163+
}
164+
165+
return mlir::success();
166+
}
167+
168+
void CIRGenFunction::enterCXXTryStmt(const CXXTryStmt &s, cir::TryOp tryOp,
169+
bool isFnTryBlock) {
170+
unsigned numHandlers = s.getNumHandlers();
171+
EHCatchScope *catchScope = ehStack.pushCatch(numHandlers);
172+
for (unsigned i = 0; i != numHandlers; ++i) {
173+
const CXXCatchStmt *catchStmt = s.getHandler(i);
174+
if (catchStmt->getExceptionDecl()) {
175+
cgm.errorNYI("enterCXXTryStmt: CatchStmt with ExceptionDecl");
176+
return;
177+
}
178+
179+
// No exception decl indicates '...', a catch-all.
180+
mlir::Region *handler = &tryOp.getHandlerRegions()[i];
181+
catchScope->setHandler(i, cgm.getCXXABI().getCatchAllTypeInfo(), handler);
182+
183+
// Under async exceptions, catch(...) needs to catch HW exception too
184+
// Mark scope with SehTryBegin as a SEH __try scope
185+
if (getLangOpts().EHAsynch) {
186+
cgm.errorNYI("enterCXXTryStmt: EHAsynch");
187+
return;
188+
}
189+
}
190+
}
191+
192+
void CIRGenFunction::exitCXXTryStmt(const CXXTryStmt &s, bool isFnTryBlock) {
193+
unsigned numHandlers = s.getNumHandlers();
194+
EHCatchScope &catchScope = cast<EHCatchScope>(*ehStack.begin());
195+
assert(catchScope.getNumHandlers() == numHandlers);
196+
cir::TryOp tryOp = curLexScope->getTry();
197+
198+
// If the catch was not required, bail out now.
199+
if (!catchScope.mayThrow()) {
200+
catchScope.clearHandlerBlocks();
201+
ehStack.popCatch();
202+
203+
// Drop all basic block from all catch regions.
204+
SmallVector<mlir::Block *> eraseBlocks;
205+
for (mlir::Region &handlerRegion : tryOp.getHandlerRegions()) {
206+
if (handlerRegion.empty())
207+
continue;
208+
209+
for (mlir::Block &b : handlerRegion.getBlocks())
210+
eraseBlocks.push_back(&b);
211+
}
212+
213+
for (mlir::Block *b : eraseBlocks)
214+
b->erase();
215+
216+
tryOp.setHandlerTypesAttr({});
217+
return;
218+
}
219+
220+
cgm.errorNYI("exitCXXTryStmt: Required catch");
74221
}

0 commit comments

Comments
 (0)