Skip to content

Commit

Permalink
Merge from 'main' to 'sycl-web' (intel#32)
Browse files Browse the repository at this point in the history
  CONFLICT (content): Merge conflict in clang/test/SemaSYCL/address-space-conversions.cpp
  CONFLICT (content): Merge conflict in clang/lib/AST/ItaniumMangle.cpp
  • Loading branch information
asudarsa committed May 18, 2021
2 parents c6c41b7 + 2ab513c commit fa2fc21
Show file tree
Hide file tree
Showing 129 changed files with 2,229 additions and 985 deletions.
22 changes: 18 additions & 4 deletions clang/docs/SYCLSupport.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,20 @@ the address space qualifier inference as detailed in

The default address space is "generic-memory", which is a virtual address space
that overlaps the global, local, and private address spaces. SYCL mode enables
explicit conversions to/from the default address space from/to the address
space-attributed type and implicit conversions from the address space-attributed
type to the default address space. All named address spaces are disjoint and
sub-sets of default address space.
following conversions:

- explicit conversions to/from the default address space from/to the address
space-attributed type
- implicit conversions from the address space-attributed type to the default
address space
- explicit conversions to/from the global address space from/to the
``__attribute__((opencl_global_device))`` or
``__attribute__((opencl_global_host))`` address space-attributed type
- implicit conversions from the ``__attribute__((opencl_global_device))`` or
``__attribute__((opencl_global_host))`` address space-attributed type to the
global address space

All named address spaces are disjoint and sub-sets of default address space.

The SPIR target allocates SYCL namespace scope variables in the global address
space.
Expand Down Expand Up @@ -93,6 +103,10 @@ space attributes for pointers:
- SYCL address_space enumeration
* - ``__attribute__((opencl_global))``
- global_space, constant_space
* - ``__attribute__((opencl_global_device))``
- global_space
* - ``__attribute__((opencl_global_host))``
- global_space
* - ``__attribute__((opencl_local))``
- local_space
* - ``__attribute__((opencl_private))``
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/AST/Stmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -1798,6 +1798,7 @@ class ValueStmt : public Stmt {
class LabelStmt : public ValueStmt {
LabelDecl *TheDecl;
Stmt *SubStmt;
bool SideEntry = false;

public:
/// Build a label statement.
Expand Down Expand Up @@ -1833,6 +1834,8 @@ class LabelStmt : public ValueStmt {
static bool classof(const Stmt *T) {
return T->getStmtClass() == LabelStmtClass;
}
bool isSideEntry() const { return SideEntry; }
void setSideEntry(bool SE) { SideEntry = SE; }
};

/// Represents an attribute applied to a statement.
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/LangOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ LANGOPT(ZVector , 1, 0, "System z vector extensions")
LANGOPT(Exceptions , 1, 0, "exception handling")
LANGOPT(ObjCExceptions , 1, 0, "Objective-C exceptions")
LANGOPT(CXXExceptions , 1, 0, "C++ exceptions")
LANGOPT(EHAsynch , 1, 0, "C/C++ EH Asynch exceptions")
ENUM_LANGOPT(ExceptionHandling, ExceptionHandlingKind, 3,
ExceptionHandlingKind::None, "exception handling")
LANGOPT(IgnoreExceptions , 1, 0, "ignore exceptions")
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -1342,6 +1342,9 @@ def fcreate_profile : Flag<["-"], "fcreate-profile">, Group<f_Group>;
defm cxx_exceptions: BoolFOption<"cxx-exceptions",
LangOpts<"CXXExceptions">, DefaultFalse,
PosFlag<SetTrue, [CC1Option], "Enable C++ exceptions">, NegFlag<SetFalse>>;
defm async_exceptions: BoolFOption<"async-exceptions",
LangOpts<"EHAsynch">, DefaultFalse,
PosFlag<SetTrue, [CC1Option], "Enable EH Asynchronous exceptions">, NegFlag<SetFalse>>;
def fcxx_modules : Flag <["-"], "fcxx-modules">, Group<f_Group>,
Flags<[NoXarchOption]>;
def fdebug_pass_arguments : Flag<["-"], "fdebug-pass-arguments">, Group<f_Group>;
Expand Down
6 changes: 5 additions & 1 deletion clang/lib/AST/ASTImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8389,7 +8389,11 @@ Expected<Decl *> ASTImporter::Import(Decl *FromD) {
// traverse of the 'to' context).
auto PosF = ImportedFromDecls.find(ToD);
if (PosF != ImportedFromDecls.end()) {
SharedState->removeDeclFromLookup(ToD);
// In the case of TypedefNameDecl we create the Decl first and only
// then we import and set its DeclContext. So, the DC might not be set
// when we reach here.
if (ToD->getDeclContext())
SharedState->removeDeclFromLookup(ToD);
ImportedFromDecls.erase(PosF);
}

Expand Down
3 changes: 2 additions & 1 deletion clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2611,7 +2611,8 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals, const DependentAddressSp
case LangAS::opencl_generic:
ASString = "CLgeneric";
break;
// <SYCL-addrspace> ::= "SY" [ "global" | "local" | "private" ]
// <SYCL-addrspace> ::= "SY" [ "global" | "local" | "private" |
// "device" | "host" ]
case LangAS::sycl_global:
ASString = "SYglobal";
break;
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/JSONNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1451,6 +1451,7 @@ void JSONNodeDumper::VisitCaseStmt(const CaseStmt *CS) {
void JSONNodeDumper::VisitLabelStmt(const LabelStmt *LS) {
JOS.attribute("name", LS->getName());
JOS.attribute("declId", createPointerRepresentation(LS->getDecl()));
attributeOnlyIfTrue("sideEntry", LS->isSideEntry());
}
void JSONNodeDumper::VisitGotoStmt(const GotoStmt *GS) {
JOS.attribute("targetLabelDeclId",
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/AST/TextNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -923,6 +923,8 @@ void TextNodeDumper::VisitWhileStmt(const WhileStmt *Node) {

void TextNodeDumper::VisitLabelStmt(const LabelStmt *Node) {
OS << " '" << Node->getName() << "'";
if (Node->isSideEntry())
OS << " side_entry";
}

void TextNodeDumper::VisitGotoStmt(const GotoStmt *Node) {
Expand Down
106 changes: 99 additions & 7 deletions clang/lib/CodeGen/CGCleanup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,11 @@ void *EHScopeStack::pushCleanup(CleanupKind Kind, size_t Size) {
if (IsLifetimeMarker)
Scope->setLifetimeMarker();

// With Windows -EHa, Invoke llvm.seh.scope.begin() for EHCleanup
if (CGF->getLangOpts().EHAsynch && IsEHCleanup &&
CGF->getTarget().getCXXABI().isMicrosoft())
CGF->EmitSehCppScopeBegin();

return Scope->getCleanupBuffer();
}

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

// Under -EHa, invoke seh.scope.end() to mark scope end before dtor
bool IsEHa = getLangOpts().EHAsynch && !Scope.isLifetimeMarker();
const EHPersonality &Personality = EHPersonality::get(*this);
if (!RequiresNormalCleanup) {
// Mark CPP scope end for passed-by-value Arg temp
// per Windows ABI which is "normally" Cleanup in callee
if (IsEHa && getInvokeDest()) {
if (Personality.isMSVCXXPersonality())
EmitSehCppScopeEnd();
}
destroyOptimisticNormalEntry(*this, Scope);
EHStack.popCleanup();
} else {
// If we have a fallthrough and no other need for the cleanup,
// emit it directly.
if (HasFallthrough && !HasPrebranchedFallthrough &&
!HasFixups && !HasExistingBranches) {
if (HasFallthrough && !HasPrebranchedFallthrough && !HasFixups &&
!HasExistingBranches) {

// mark SEH scope end for fall-through flow
if (IsEHa && getInvokeDest()) {
if (Personality.isMSVCXXPersonality())
EmitSehCppScopeEnd();
else
EmitSehTryScopeEnd();
}

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

// intercept normal cleanup to mark SEH scope end
if (IsEHa) {
if (Personality.isMSVCXXPersonality())
EmitSehCppScopeEnd();
else
EmitSehTryScopeEnd();
}

// III. Figure out where we're going and build the cleanup
// epilogue.

Expand Down Expand Up @@ -1248,11 +1278,17 @@ void CodeGenFunction::DeactivateCleanupBlock(EHScopeStack::stable_iterator C,
// to the current RunCleanupsScope.
if (C == EHStack.stable_begin() &&
CurrentCleanupScopeDepth.strictlyEncloses(C)) {
// If it's a normal cleanup, we need to pretend that the
// fallthrough is unreachable.
CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
PopCleanupBlock();
Builder.restoreIP(SavedIP);
// Per comment below, checking EHAsynch is not really necessary
// it's there to assure zero-impact w/o EHAsynch option
if (!Scope.isNormalCleanup() && getLangOpts().EHAsynch) {
PopCleanupBlock();
} else {
// If it's a normal cleanup, we need to pretend that the
// fallthrough is unreachable.
CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
PopCleanupBlock();
Builder.restoreIP(SavedIP);
}
return;
}

Expand All @@ -1276,3 +1312,59 @@ void CodeGenFunction::EmitCXXTemporary(const CXXTemporary *Temporary,
pushDestroy(NormalAndEHCleanup, Ptr, TempType, destroyCXXObject,
/*useEHCleanup*/ true);
}

// Need to set "funclet" in OperandBundle properly for noThrow
// intrinsic (see CGCall.cpp)
static void EmitSehScope(CodeGenFunction &CGF,
llvm::FunctionCallee &SehCppScope) {
llvm::BasicBlock *InvokeDest = CGF.getInvokeDest();
assert(CGF.Builder.GetInsertBlock() && InvokeDest);
llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont");
SmallVector<llvm::OperandBundleDef, 1> BundleList =
CGF.getBundlesForFunclet(SehCppScope.getCallee());
if (CGF.CurrentFuncletPad)
BundleList.emplace_back("funclet", CGF.CurrentFuncletPad);
CGF.Builder.CreateInvoke(SehCppScope, Cont, InvokeDest, None, BundleList);
CGF.EmitBlock(Cont);
}

// Invoke a llvm.seh.scope.begin at the beginning of a CPP scope for -EHa
void CodeGenFunction::EmitSehCppScopeBegin() {
assert(getLangOpts().EHAsynch);
llvm::FunctionType *FTy =
llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
llvm::FunctionCallee SehCppScope =
CGM.CreateRuntimeFunction(FTy, "llvm.seh.scope.begin");
EmitSehScope(*this, SehCppScope);
}

// Invoke a llvm.seh.scope.end at the end of a CPP scope for -EHa
// llvm.seh.scope.end is emitted before popCleanup, so it's "invoked"
void CodeGenFunction::EmitSehCppScopeEnd() {
assert(getLangOpts().EHAsynch);
llvm::FunctionType *FTy =
llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
llvm::FunctionCallee SehCppScope =
CGM.CreateRuntimeFunction(FTy, "llvm.seh.scope.end");
EmitSehScope(*this, SehCppScope);
}

// Invoke a llvm.seh.try.begin at the beginning of a SEH scope for -EHa
void CodeGenFunction::EmitSehTryScopeBegin() {
assert(getLangOpts().EHAsynch);
llvm::FunctionType *FTy =
llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
llvm::FunctionCallee SehCppScope =
CGM.CreateRuntimeFunction(FTy, "llvm.seh.try.begin");
EmitSehScope(*this, SehCppScope);
}

// Invoke a llvm.seh.try.end at the end of a SEH scope for -EHa
void CodeGenFunction::EmitSehTryScopeEnd() {
assert(getLangOpts().EHAsynch);
llvm::FunctionType *FTy =
llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
llvm::FunctionCallee SehCppScope =
CGM.CreateRuntimeFunction(FTy, "llvm.seh.try.end");
EmitSehScope(*this, SehCppScope);
}
77 changes: 73 additions & 4 deletions clang/lib/CodeGen/CGException.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,18 @@ static llvm::FunctionCallee getFreeExceptionFn(CodeGenModule &CGM) {
return CGM.CreateRuntimeFunction(FTy, "__cxa_free_exception");
}

static llvm::FunctionCallee getSehTryBeginFn(CodeGenModule &CGM) {
llvm::FunctionType *FTy =
llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
return CGM.CreateRuntimeFunction(FTy, "llvm.seh.try.begin");
}

static llvm::FunctionCallee getSehTryEndFn(CodeGenModule &CGM) {
llvm::FunctionType *FTy =
llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
return CGM.CreateRuntimeFunction(FTy, "llvm.seh.try.end");
}

static llvm::FunctionCallee getUnexpectedFn(CodeGenModule &CGM) {
// void __cxa_call_unexpected(void *thrown_exception);

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

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

SEHTryEpilogueStack.push_back(&TryExit);

llvm::BasicBlock *TryBB = nullptr;
// IsEHa: emit an invoke to _seh_try_begin() runtime for -EHa
if (getLangOpts().EHAsynch) {
EmitRuntimeCallOrInvoke(getSehTryBeginFn(CGM));
if (SEHTryEpilogueStack.size() == 1) // outermost only
TryBB = Builder.GetInsertBlock();
}

EmitStmt(S.getTryBlock());

// Volatilize all blocks in Try, till current insert point
if (TryBB) {
llvm::SmallPtrSet<llvm::BasicBlock *, 10> Visited;
VolatilizeTryBlocks(TryBB, Visited);
}

SEHTryEpilogueStack.pop_back();

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

// Recursively walk through blocks in a _try
// and make all memory instructions volatile
void CodeGenFunction::VolatilizeTryBlocks(
llvm::BasicBlock *BB, llvm::SmallPtrSet<llvm::BasicBlock *, 10> &V) {
if (BB == SEHTryEpilogueStack.back()->getBlock() /* end of Try */ ||
!V.insert(BB).second /* already visited */ ||
!BB->getParent() /* not emitted */ || BB->empty())
return;

if (!BB->isEHPad()) {
for (llvm::BasicBlock::iterator J = BB->begin(), JE = BB->end(); J != JE;
++J) {
if (auto LI = dyn_cast<llvm::LoadInst>(J)) {
LI->setVolatile(true);
} else if (auto SI = dyn_cast<llvm::StoreInst>(J)) {
SI->setVolatile(true);
} else if (auto* MCI = dyn_cast<llvm::MemIntrinsic>(J)) {
MCI->setVolatile(llvm::ConstantInt::get(Builder.getInt1Ty(), 1));
}
}
}
const llvm::Instruction *TI = BB->getTerminator();
if (TI) {
unsigned N = TI->getNumSuccessors();
for (unsigned I = 0; I < N; I++)
VolatilizeTryBlocks(TI->getSuccessor(I), V);
}
}

namespace {
struct PerformSEHFinally final : EHScopeStack::Cleanup {
llvm::Function *OutlinedFinally;
Expand Down Expand Up @@ -2118,6 +2181,12 @@ void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S) {
return;
}

// IsEHa: emit an invoke _seh_try_end() to mark end of FT flow
if (getLangOpts().EHAsynch && Builder.GetInsertBlock()) {
llvm::FunctionCallee SehTryEnd = getSehTryEndFn(CGM);
EmitRuntimeCallOrInvoke(SehTryEnd);
}

// Otherwise, we must have an __except block.
const SEHExceptStmt *Except = S.getExceptHandler();
assert(Except && "__try must have __finally xor __except");
Expand Down
Loading

0 comments on commit fa2fc21

Please sign in to comment.