Skip to content

Commit fa2fc21

Browse files
committed
Merge from 'main' to 'sycl-web' (intel#32)
CONFLICT (content): Merge conflict in clang/test/SemaSYCL/address-space-conversions.cpp CONFLICT (content): Merge conflict in clang/lib/AST/ItaniumMangle.cpp
2 parents c6c41b7 + 2ab513c commit fa2fc21

File tree

129 files changed

+2229
-985
lines changed

Some content is hidden

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

129 files changed

+2229
-985
lines changed

clang/docs/SYCLSupport.rst

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,20 @@ the address space qualifier inference as detailed in
3434

3535
The default address space is "generic-memory", which is a virtual address space
3636
that overlaps the global, local, and private address spaces. SYCL mode enables
37-
explicit conversions to/from the default address space from/to the address
38-
space-attributed type and implicit conversions from the address space-attributed
39-
type to the default address space. All named address spaces are disjoint and
40-
sub-sets of default address space.
37+
following conversions:
38+
39+
- explicit conversions to/from the default address space from/to the address
40+
space-attributed type
41+
- implicit conversions from the address space-attributed type to the default
42+
address space
43+
- explicit conversions to/from the global address space from/to the
44+
``__attribute__((opencl_global_device))`` or
45+
``__attribute__((opencl_global_host))`` address space-attributed type
46+
- implicit conversions from the ``__attribute__((opencl_global_device))`` or
47+
``__attribute__((opencl_global_host))`` address space-attributed type to the
48+
global address space
49+
50+
All named address spaces are disjoint and sub-sets of default address space.
4151

4252
The SPIR target allocates SYCL namespace scope variables in the global address
4353
space.
@@ -93,6 +103,10 @@ space attributes for pointers:
93103
- SYCL address_space enumeration
94104
* - ``__attribute__((opencl_global))``
95105
- global_space, constant_space
106+
* - ``__attribute__((opencl_global_device))``
107+
- global_space
108+
* - ``__attribute__((opencl_global_host))``
109+
- global_space
96110
* - ``__attribute__((opencl_local))``
97111
- local_space
98112
* - ``__attribute__((opencl_private))``

clang/include/clang/AST/Stmt.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1798,6 +1798,7 @@ class ValueStmt : public Stmt {
17981798
class LabelStmt : public ValueStmt {
17991799
LabelDecl *TheDecl;
18001800
Stmt *SubStmt;
1801+
bool SideEntry = false;
18011802

18021803
public:
18031804
/// Build a label statement.
@@ -1833,6 +1834,8 @@ class LabelStmt : public ValueStmt {
18331834
static bool classof(const Stmt *T) {
18341835
return T->getStmtClass() == LabelStmtClass;
18351836
}
1837+
bool isSideEntry() const { return SideEntry; }
1838+
void setSideEntry(bool SE) { SideEntry = SE; }
18361839
};
18371840

18381841
/// Represents an attribute applied to a statement.

clang/include/clang/Basic/LangOptions.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ LANGOPT(ZVector , 1, 0, "System z vector extensions")
132132
LANGOPT(Exceptions , 1, 0, "exception handling")
133133
LANGOPT(ObjCExceptions , 1, 0, "Objective-C exceptions")
134134
LANGOPT(CXXExceptions , 1, 0, "C++ exceptions")
135+
LANGOPT(EHAsynch , 1, 0, "C/C++ EH Asynch exceptions")
135136
ENUM_LANGOPT(ExceptionHandling, ExceptionHandlingKind, 3,
136137
ExceptionHandlingKind::None, "exception handling")
137138
LANGOPT(IgnoreExceptions , 1, 0, "ignore exceptions")

clang/include/clang/Driver/Options.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1342,6 +1342,9 @@ def fcreate_profile : Flag<["-"], "fcreate-profile">, Group<f_Group>;
13421342
defm cxx_exceptions: BoolFOption<"cxx-exceptions",
13431343
LangOpts<"CXXExceptions">, DefaultFalse,
13441344
PosFlag<SetTrue, [CC1Option], "Enable C++ exceptions">, NegFlag<SetFalse>>;
1345+
defm async_exceptions: BoolFOption<"async-exceptions",
1346+
LangOpts<"EHAsynch">, DefaultFalse,
1347+
PosFlag<SetTrue, [CC1Option], "Enable EH Asynchronous exceptions">, NegFlag<SetFalse>>;
13451348
def fcxx_modules : Flag <["-"], "fcxx-modules">, Group<f_Group>,
13461349
Flags<[NoXarchOption]>;
13471350
def fdebug_pass_arguments : Flag<["-"], "fdebug-pass-arguments">, Group<f_Group>;

clang/lib/AST/ASTImporter.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8389,7 +8389,11 @@ Expected<Decl *> ASTImporter::Import(Decl *FromD) {
83898389
// traverse of the 'to' context).
83908390
auto PosF = ImportedFromDecls.find(ToD);
83918391
if (PosF != ImportedFromDecls.end()) {
8392-
SharedState->removeDeclFromLookup(ToD);
8392+
// In the case of TypedefNameDecl we create the Decl first and only
8393+
// then we import and set its DeclContext. So, the DC might not be set
8394+
// when we reach here.
8395+
if (ToD->getDeclContext())
8396+
SharedState->removeDeclFromLookup(ToD);
83938397
ImportedFromDecls.erase(PosF);
83948398
}
83958399

clang/lib/AST/ItaniumMangle.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2611,7 +2611,8 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals, const DependentAddressSp
26112611
case LangAS::opencl_generic:
26122612
ASString = "CLgeneric";
26132613
break;
2614-
// <SYCL-addrspace> ::= "SY" [ "global" | "local" | "private" ]
2614+
// <SYCL-addrspace> ::= "SY" [ "global" | "local" | "private" |
2615+
// "device" | "host" ]
26152616
case LangAS::sycl_global:
26162617
ASString = "SYglobal";
26172618
break;

clang/lib/AST/JSONNodeDumper.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,6 +1451,7 @@ void JSONNodeDumper::VisitCaseStmt(const CaseStmt *CS) {
14511451
void JSONNodeDumper::VisitLabelStmt(const LabelStmt *LS) {
14521452
JOS.attribute("name", LS->getName());
14531453
JOS.attribute("declId", createPointerRepresentation(LS->getDecl()));
1454+
attributeOnlyIfTrue("sideEntry", LS->isSideEntry());
14541455
}
14551456
void JSONNodeDumper::VisitGotoStmt(const GotoStmt *GS) {
14561457
JOS.attribute("targetLabelDeclId",

clang/lib/AST/TextNodeDumper.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,6 +923,8 @@ void TextNodeDumper::VisitWhileStmt(const WhileStmt *Node) {
923923

924924
void TextNodeDumper::VisitLabelStmt(const LabelStmt *Node) {
925925
OS << " '" << Node->getName() << "'";
926+
if (Node->isSideEntry())
927+
OS << " side_entry";
926928
}
927929

928930
void TextNodeDumper::VisitGotoStmt(const GotoStmt *Node) {

clang/lib/CodeGen/CGCleanup.cpp

Lines changed: 99 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,11 @@ void *EHScopeStack::pushCleanup(CleanupKind Kind, size_t Size) {
194194
if (IsLifetimeMarker)
195195
Scope->setLifetimeMarker();
196196

197+
// With Windows -EHa, Invoke llvm.seh.scope.begin() for EHCleanup
198+
if (CGF->getLangOpts().EHAsynch && IsEHCleanup &&
199+
CGF->getTarget().getCXXABI().isMicrosoft())
200+
CGF->EmitSehCppScopeBegin();
201+
197202
return Scope->getCleanupBuffer();
198203
}
199204

@@ -759,14 +764,31 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
759764
if (Scope.isEHCleanup())
760765
cleanupFlags.setIsEHCleanupKind();
761766

767+
// Under -EHa, invoke seh.scope.end() to mark scope end before dtor
768+
bool IsEHa = getLangOpts().EHAsynch && !Scope.isLifetimeMarker();
769+
const EHPersonality &Personality = EHPersonality::get(*this);
762770
if (!RequiresNormalCleanup) {
771+
// Mark CPP scope end for passed-by-value Arg temp
772+
// per Windows ABI which is "normally" Cleanup in callee
773+
if (IsEHa && getInvokeDest()) {
774+
if (Personality.isMSVCXXPersonality())
775+
EmitSehCppScopeEnd();
776+
}
763777
destroyOptimisticNormalEntry(*this, Scope);
764778
EHStack.popCleanup();
765779
} else {
766780
// If we have a fallthrough and no other need for the cleanup,
767781
// emit it directly.
768-
if (HasFallthrough && !HasPrebranchedFallthrough &&
769-
!HasFixups && !HasExistingBranches) {
782+
if (HasFallthrough && !HasPrebranchedFallthrough && !HasFixups &&
783+
!HasExistingBranches) {
784+
785+
// mark SEH scope end for fall-through flow
786+
if (IsEHa && getInvokeDest()) {
787+
if (Personality.isMSVCXXPersonality())
788+
EmitSehCppScopeEnd();
789+
else
790+
EmitSehTryScopeEnd();
791+
}
770792

771793
destroyOptimisticNormalEntry(*this, Scope);
772794
EHStack.popCleanup();
@@ -801,6 +823,14 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
801823
// should already be branched to it.
802824
EmitBlock(NormalEntry);
803825

826+
// intercept normal cleanup to mark SEH scope end
827+
if (IsEHa) {
828+
if (Personality.isMSVCXXPersonality())
829+
EmitSehCppScopeEnd();
830+
else
831+
EmitSehTryScopeEnd();
832+
}
833+
804834
// III. Figure out where we're going and build the cleanup
805835
// epilogue.
806836

@@ -1248,11 +1278,17 @@ void CodeGenFunction::DeactivateCleanupBlock(EHScopeStack::stable_iterator C,
12481278
// to the current RunCleanupsScope.
12491279
if (C == EHStack.stable_begin() &&
12501280
CurrentCleanupScopeDepth.strictlyEncloses(C)) {
1251-
// If it's a normal cleanup, we need to pretend that the
1252-
// fallthrough is unreachable.
1253-
CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
1254-
PopCleanupBlock();
1255-
Builder.restoreIP(SavedIP);
1281+
// Per comment below, checking EHAsynch is not really necessary
1282+
// it's there to assure zero-impact w/o EHAsynch option
1283+
if (!Scope.isNormalCleanup() && getLangOpts().EHAsynch) {
1284+
PopCleanupBlock();
1285+
} else {
1286+
// If it's a normal cleanup, we need to pretend that the
1287+
// fallthrough is unreachable.
1288+
CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
1289+
PopCleanupBlock();
1290+
Builder.restoreIP(SavedIP);
1291+
}
12561292
return;
12571293
}
12581294

@@ -1276,3 +1312,59 @@ void CodeGenFunction::EmitCXXTemporary(const CXXTemporary *Temporary,
12761312
pushDestroy(NormalAndEHCleanup, Ptr, TempType, destroyCXXObject,
12771313
/*useEHCleanup*/ true);
12781314
}
1315+
1316+
// Need to set "funclet" in OperandBundle properly for noThrow
1317+
// intrinsic (see CGCall.cpp)
1318+
static void EmitSehScope(CodeGenFunction &CGF,
1319+
llvm::FunctionCallee &SehCppScope) {
1320+
llvm::BasicBlock *InvokeDest = CGF.getInvokeDest();
1321+
assert(CGF.Builder.GetInsertBlock() && InvokeDest);
1322+
llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont");
1323+
SmallVector<llvm::OperandBundleDef, 1> BundleList =
1324+
CGF.getBundlesForFunclet(SehCppScope.getCallee());
1325+
if (CGF.CurrentFuncletPad)
1326+
BundleList.emplace_back("funclet", CGF.CurrentFuncletPad);
1327+
CGF.Builder.CreateInvoke(SehCppScope, Cont, InvokeDest, None, BundleList);
1328+
CGF.EmitBlock(Cont);
1329+
}
1330+
1331+
// Invoke a llvm.seh.scope.begin at the beginning of a CPP scope for -EHa
1332+
void CodeGenFunction::EmitSehCppScopeBegin() {
1333+
assert(getLangOpts().EHAsynch);
1334+
llvm::FunctionType *FTy =
1335+
llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
1336+
llvm::FunctionCallee SehCppScope =
1337+
CGM.CreateRuntimeFunction(FTy, "llvm.seh.scope.begin");
1338+
EmitSehScope(*this, SehCppScope);
1339+
}
1340+
1341+
// Invoke a llvm.seh.scope.end at the end of a CPP scope for -EHa
1342+
// llvm.seh.scope.end is emitted before popCleanup, so it's "invoked"
1343+
void CodeGenFunction::EmitSehCppScopeEnd() {
1344+
assert(getLangOpts().EHAsynch);
1345+
llvm::FunctionType *FTy =
1346+
llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
1347+
llvm::FunctionCallee SehCppScope =
1348+
CGM.CreateRuntimeFunction(FTy, "llvm.seh.scope.end");
1349+
EmitSehScope(*this, SehCppScope);
1350+
}
1351+
1352+
// Invoke a llvm.seh.try.begin at the beginning of a SEH scope for -EHa
1353+
void CodeGenFunction::EmitSehTryScopeBegin() {
1354+
assert(getLangOpts().EHAsynch);
1355+
llvm::FunctionType *FTy =
1356+
llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
1357+
llvm::FunctionCallee SehCppScope =
1358+
CGM.CreateRuntimeFunction(FTy, "llvm.seh.try.begin");
1359+
EmitSehScope(*this, SehCppScope);
1360+
}
1361+
1362+
// Invoke a llvm.seh.try.end at the end of a SEH scope for -EHa
1363+
void CodeGenFunction::EmitSehTryScopeEnd() {
1364+
assert(getLangOpts().EHAsynch);
1365+
llvm::FunctionType *FTy =
1366+
llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
1367+
llvm::FunctionCallee SehCppScope =
1368+
CGM.CreateRuntimeFunction(FTy, "llvm.seh.try.end");
1369+
EmitSehScope(*this, SehCppScope);
1370+
}

clang/lib/CodeGen/CGException.cpp

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,18 @@ static llvm::FunctionCallee getFreeExceptionFn(CodeGenModule &CGM) {
3939
return CGM.CreateRuntimeFunction(FTy, "__cxa_free_exception");
4040
}
4141

42+
static llvm::FunctionCallee getSehTryBeginFn(CodeGenModule &CGM) {
43+
llvm::FunctionType *FTy =
44+
llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
45+
return CGM.CreateRuntimeFunction(FTy, "llvm.seh.try.begin");
46+
}
47+
48+
static llvm::FunctionCallee getSehTryEndFn(CodeGenModule &CGM) {
49+
llvm::FunctionType *FTy =
50+
llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
51+
return CGM.CreateRuntimeFunction(FTy, "llvm.seh.try.end");
52+
}
53+
4254
static llvm::FunctionCallee getUnexpectedFn(CodeGenModule &CGM) {
4355
// void __cxa_call_unexpected(void *thrown_exception);
4456

@@ -467,7 +479,8 @@ void CodeGenFunction::EmitStartEHSpec(const Decl *D) {
467479
ExceptionSpecificationType EST = Proto->getExceptionSpecType();
468480
if (isNoexceptExceptionSpec(EST) && Proto->canThrow() == CT_Cannot) {
469481
// noexcept functions are simple terminate scopes.
470-
EHStack.pushTerminate();
482+
if (!getLangOpts().EHAsynch) // -EHa: HW exception still can occur
483+
EHStack.pushTerminate();
471484
} else if (EST == EST_Dynamic || EST == EST_DynamicNone) {
472485
// TODO: Revisit exception specifications for the MS ABI. There is a way to
473486
// encode these in an object file but MSVC doesn't do anything with it.
@@ -544,7 +557,7 @@ void CodeGenFunction::EmitEndEHSpec(const Decl *D) {
544557
if (!FD) {
545558
// Check if CapturedDecl is nothrow and pop terminate scope for it.
546559
if (const CapturedDecl* CD = dyn_cast_or_null<CapturedDecl>(D)) {
547-
if (CD->isNothrow())
560+
if (CD->isNothrow() && !EHStack.empty())
548561
EHStack.popTerminate();
549562
}
550563
return;
@@ -554,7 +567,8 @@ void CodeGenFunction::EmitEndEHSpec(const Decl *D) {
554567
return;
555568

556569
ExceptionSpecificationType EST = Proto->getExceptionSpecType();
557-
if (isNoexceptExceptionSpec(EST) && Proto->canThrow() == CT_Cannot) {
570+
if (isNoexceptExceptionSpec(EST) && Proto->canThrow() == CT_Cannot &&
571+
!EHStack.empty() /* possible empty when under async exceptions */) {
558572
EHStack.popTerminate();
559573
} else if (EST == EST_Dynamic || EST == EST_DynamicNone) {
560574
// TODO: Revisit exception specifications for the MS ABI. There is a way to
@@ -610,6 +624,10 @@ void CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
610624
} else {
611625
// No exception decl indicates '...', a catch-all.
612626
CatchScope->setHandler(I, CGM.getCXXABI().getCatchAllTypeInfo(), Handler);
627+
// Under async exceptions, catch(...) need to catch HW exception too
628+
// Mark scope with SehTryBegin as a SEH __try scope
629+
if (getLangOpts().EHAsynch)
630+
EmitRuntimeCallOrInvoke(getSehTryBeginFn(CGM));
613631
}
614632
}
615633
}
@@ -724,7 +742,7 @@ llvm::BasicBlock *CodeGenFunction::getInvokeDestImpl() {
724742
// If exceptions are disabled/ignored and SEH is not in use, then there is no
725743
// invoke destination. SEH "works" even if exceptions are off. In practice,
726744
// this means that C++ destructors and other EH cleanups don't run, which is
727-
// consistent with MSVC's behavior.
745+
// consistent with MSVC's behavior, except in the presence of -EHa
728746
const LangOptions &LO = CGM.getLangOpts();
729747
if (!LO.Exceptions || LO.IgnoreExceptions) {
730748
if (!LO.Borland && !LO.MicrosoftExt)
@@ -1606,7 +1624,23 @@ void CodeGenFunction::EmitSEHTryStmt(const SEHTryStmt &S) {
16061624
JumpDest TryExit = getJumpDestInCurrentScope("__try.__leave");
16071625

16081626
SEHTryEpilogueStack.push_back(&TryExit);
1627+
1628+
llvm::BasicBlock *TryBB = nullptr;
1629+
// IsEHa: emit an invoke to _seh_try_begin() runtime for -EHa
1630+
if (getLangOpts().EHAsynch) {
1631+
EmitRuntimeCallOrInvoke(getSehTryBeginFn(CGM));
1632+
if (SEHTryEpilogueStack.size() == 1) // outermost only
1633+
TryBB = Builder.GetInsertBlock();
1634+
}
1635+
16091636
EmitStmt(S.getTryBlock());
1637+
1638+
// Volatilize all blocks in Try, till current insert point
1639+
if (TryBB) {
1640+
llvm::SmallPtrSet<llvm::BasicBlock *, 10> Visited;
1641+
VolatilizeTryBlocks(TryBB, Visited);
1642+
}
1643+
16101644
SEHTryEpilogueStack.pop_back();
16111645

16121646
if (!TryExit.getBlock()->use_empty())
@@ -1617,6 +1651,35 @@ void CodeGenFunction::EmitSEHTryStmt(const SEHTryStmt &S) {
16171651
ExitSEHTryStmt(S);
16181652
}
16191653

1654+
// Recursively walk through blocks in a _try
1655+
// and make all memory instructions volatile
1656+
void CodeGenFunction::VolatilizeTryBlocks(
1657+
llvm::BasicBlock *BB, llvm::SmallPtrSet<llvm::BasicBlock *, 10> &V) {
1658+
if (BB == SEHTryEpilogueStack.back()->getBlock() /* end of Try */ ||
1659+
!V.insert(BB).second /* already visited */ ||
1660+
!BB->getParent() /* not emitted */ || BB->empty())
1661+
return;
1662+
1663+
if (!BB->isEHPad()) {
1664+
for (llvm::BasicBlock::iterator J = BB->begin(), JE = BB->end(); J != JE;
1665+
++J) {
1666+
if (auto LI = dyn_cast<llvm::LoadInst>(J)) {
1667+
LI->setVolatile(true);
1668+
} else if (auto SI = dyn_cast<llvm::StoreInst>(J)) {
1669+
SI->setVolatile(true);
1670+
} else if (auto* MCI = dyn_cast<llvm::MemIntrinsic>(J)) {
1671+
MCI->setVolatile(llvm::ConstantInt::get(Builder.getInt1Ty(), 1));
1672+
}
1673+
}
1674+
}
1675+
const llvm::Instruction *TI = BB->getTerminator();
1676+
if (TI) {
1677+
unsigned N = TI->getNumSuccessors();
1678+
for (unsigned I = 0; I < N; I++)
1679+
VolatilizeTryBlocks(TI->getSuccessor(I), V);
1680+
}
1681+
}
1682+
16201683
namespace {
16211684
struct PerformSEHFinally final : EHScopeStack::Cleanup {
16221685
llvm::Function *OutlinedFinally;
@@ -2118,6 +2181,12 @@ void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S) {
21182181
return;
21192182
}
21202183

2184+
// IsEHa: emit an invoke _seh_try_end() to mark end of FT flow
2185+
if (getLangOpts().EHAsynch && Builder.GetInsertBlock()) {
2186+
llvm::FunctionCallee SehTryEnd = getSehTryEndFn(CGM);
2187+
EmitRuntimeCallOrInvoke(SehTryEnd);
2188+
}
2189+
21212190
// Otherwise, we must have an __except block.
21222191
const SEHExceptStmt *Except = S.getExceptHandler();
21232192
assert(Except && "__try must have __finally xor __except");

0 commit comments

Comments
 (0)