[clang] 66f1dcd - [Windows SEH] Fix the frame-ptr of a nested-filter within a _finally

2020-07-12 Thread Ten Tzen via cfe-commits

Author: Ten Tzen
Date: 2020-07-12T01:37:56-07:00
New Revision: 66f1dcd872dba189ee054fb016f4bff535fb5afc

URL: 
https://github.com/llvm/llvm-project/commit/66f1dcd872dba189ee054fb016f4bff535fb5afc
DIFF: 
https://github.com/llvm/llvm-project/commit/66f1dcd872dba189ee054fb016f4bff535fb5afc.diff

LOG: [Windows SEH] Fix the frame-ptr of a nested-filter within a _finally

This change fixed a SEH bug (exposed by test58 & test61 in MSVC test xcpt4u.c);
when an Except-filter is located inside a finally, the frame-pointer generated 
today
via intrinsic @llvm.eh.recoverfp is the frame-pointer of the immediate
parent _finally, not the frame-ptr of outermost host function.

The fix is to retrieve the Establisher's frame-pointer that was previously 
saved in
parent's frame.
The prolog of a filter inside a _finally should be like code below:

%0 = call i8* @llvm.eh.recoverfp(i8* bitcast (@"?fin$0@0@main@@"), 
i8*%frame_pointer)
%1 = call i8* @llvm.localrecover(i8* bitcast (@"?fin$0@0@main@@"), i8*%0, i32 0)
%2 = bitcast i8* %1 to i8**
%3 = load i8*, i8** %2, align 8

Differential Revision: https://reviews.llvm.org/D77982

Added: 
clang/test/CodeGen/windows-seh-filter-inFinally.c

Modified: 
clang/lib/CodeGen/CGException.cpp
clang/lib/CodeGen/CodeGenFunction.h

Removed: 




diff  --git a/clang/lib/CodeGen/CGException.cpp 
b/clang/lib/CodeGen/CGException.cpp
index 2494f38b3159..bdf70252b5ad 100644
--- a/clang/lib/CodeGen/CGException.cpp
+++ b/clang/lib/CodeGen/CGException.cpp
@@ -1815,6 +1815,48 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction 
&ParentCGF,
 llvm::Constant *ParentI8Fn =
 llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy);
 ParentFP = Builder.CreateCall(RecoverFPIntrin, {ParentI8Fn, EntryFP});
+
+// if the parent is a _finally, the passed-in ParentFP is the FP
+// of parent _finally, not Establisher's FP (FP of outermost function).
+// Establkisher FP is 2nd paramenter passed into parent _finally.
+// Fortunately, it's always saved in parent's frame. The following
+// code retrieves it, and escapes it so that spill instruction won't be
+// optimized away.
+if (ParentCGF.ParentCGF != nullptr) {
+  // Locate and escape Parent's frame_pointer.addr alloca
+  // Depending on target, should be 1st/2nd one in LocalDeclMap.
+  // Let's just scan for ImplicitParamDecl with VoidPtrTy.
+  llvm::AllocaInst *FramePtrAddrAlloca = nullptr;
+  for (auto &I : ParentCGF.LocalDeclMap) {
+const VarDecl *D = cast(I.first);
+if (isa(D) &&
+D->getType() == getContext().VoidPtrTy) {
+  assert(D->getName().startswith("frame_pointer"));
+  FramePtrAddrAlloca = cast(I.second.getPointer());
+  break;
+}
+  }
+  assert(FramePtrAddrAlloca);
+  auto InsertPair = ParentCGF.EscapedLocals.insert(
+  std::make_pair(FramePtrAddrAlloca, ParentCGF.EscapedLocals.size()));
+  int FrameEscapeIdx = InsertPair.first->second;
+
+  // an example of a filter's prolog::
+  // %0 = call i8* @llvm.eh.recoverfp(bitcast(@"?fin$0@0@main@@"),..)
+  // %1 = call i8* @llvm.localrecover(bitcast(@"?fin$0@0@main@@"),..)
+  // %2 = bitcast i8* %1 to i8**
+  // %3 = load i8*, i8* *%2, align 8
+  //   ==> %3 is the frame-pointer of outermost host function
+  llvm::Function *FrameRecoverFn = llvm::Intrinsic::getDeclaration(
+  &CGM.getModule(), llvm::Intrinsic::localrecover);
+  llvm::Constant *ParentI8Fn =
+  llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy);
+  ParentFP = Builder.CreateCall(
+  FrameRecoverFn, {ParentI8Fn, ParentFP,
+   llvm::ConstantInt::get(Int32Ty, FrameEscapeIdx)});
+  ParentFP = Builder.CreateBitCast(ParentFP, CGM.VoidPtrPtrTy);
+  ParentFP = Builder.CreateLoad(Address(ParentFP, getPointerAlign()));
+}
   }
 
   // Create llvm.localrecover calls for all captures.
@@ -2013,6 +2055,7 @@ void CodeGenFunction::pushSEHCleanup(CleanupKind Kind,
 
 void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) {
   CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true);
+  HelperCGF.ParentCGF = this;
   if (const SEHFinallyStmt *Finally = S.getFinallyHandler()) {
 // Outline the finally block.
 llvm::Function *FinallyFunc =

diff  --git a/clang/lib/CodeGen/CodeGenFunction.h 
b/clang/lib/CodeGen/CodeGenFunction.h
index b1841d646643..1fc2ed76ca9e 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -264,6 +264,9 @@ class CodeGenFunction : public CodeGenTypeCache {
   CodeGenModule &CGM;  // Per-module state.
   const TargetInfo &Target;
 
+  // For EH/SEH outlined funclets, this field points to parent's CGF
+  CodeGenFunction *ParentCGF = nullptr;
+
   typedef std::pair ComplexPairTy;
   LoopInfoStack LoopStack;
   CGBuilderTy Builder;

diff 

[clang] 797ad70 - [Windows SEH]: HARDWARE EXCEPTION HANDLING (MSVC -EHa) - Part 1

2021-05-17 Thread Ten Tzen via cfe-commits

Author: Ten Tzen
Date: 2021-05-17T22:42:17-07:00
New Revision: 797ad701522988e212495285dade8efac41a24d4

URL: 
https://github.com/llvm/llvm-project/commit/797ad701522988e212495285dade8efac41a24d4
DIFF: 
https://github.com/llvm/llvm-project/commit/797ad701522988e212495285dade8efac41a24d4.diff

LOG: [Windows SEH]: HARDWARE EXCEPTION HANDLING (MSVC -EHa) - Part 1

This patch is the Part-1 (FE Clang) implementation of HW Exception handling.

This new feature adds the support of Hardware Exception for Microsoft Windows
SEH (Structured Exception Handling).
This is the first step of this project; only X86_64 target is enabled in this 
patch.

Compiler options:
For clang-cl.exe, the option is -EHa, the same as MSVC.
For clang.exe, the extra option is -fasync-exceptions,
plus -triple x86_64-windows -fexceptions and -fcxx-exceptions as usual.

NOTE:: Without the -EHa or -fasync-exceptions, this patch is a NO-DIFF change.

The rules for C code:
For C-code, one way (MSVC approach) to achieve SEH -EHa semantic is to follow
three rules:
* First, no exception can move in or out of _try region., i.e., no "potential
  faulty instruction can be moved across _try boundary.
* Second, the order of exceptions for instructions 'directly' under a _try
  must be preserved (not applied to those in callees).
* Finally, global states (local/global/heap variables) that can be read
  outside of _try region must be updated in memory (not just in register)
  before the subsequent exception occurs.

The impact to C++ code:
Although SEH is a feature for C code, -EHa does have a profound effect on C++
side. When a C++ function (in the same compilation unit with option -EHa ) is
called by a SEH C function, a hardware exception occurs in C++ code can also
be handled properly by an upstream SEH _try-handler or a C++ catch(...).
As such, when that happens in the middle of an object's life scope, the dtor
must be invoked the same way as C++ Synchronous Exception during unwinding
process.

Design:
A natural way to achieve the rules above in LLVM today is to allow an EH edge
added on memory/computation instruction (previous iload/istore idea) so that
exception path is modeled in Flow graph preciously. However, tracking every
single memory instruction and potential faulty instruction can create many
Invokes, complicate flow graph and possibly result in negative performance
impact for downstream optimization and code generation. Making all
optimizations be aware of the new semantic is also substantial.

This design does not intend to model exception path at instruction level.
Instead, the proposed design tracks and reports EH state at BLOCK-level to
reduce the complexity of flow graph and minimize the performance-impact on CPP
code under -EHa option.

One key element of this design is the ability to compute State number at
block-level. Our algorithm is based on the following rationales:

A _try scope is always a SEME (Single Entry Multiple Exits) region as jumping
into a _try is not allowed. The single entry must start with a seh_try_begin()
invoke with a correct State number that is the initial state of the SEME.
Through control-flow, state number is propagated into all blocks. Side exits
marked by seh_try_end() will unwind to parent state based on existing
SEHUnwindMap[].
Note side exits can ONLY jump into parent scopes (lower state number).
Thus, when a block succeeds various states from its predecessors, the lowest
State triumphs others.  If some exits flow to unreachable, propagation on those
paths terminate, not affecting remaining blocks.
For CPP code, object lifetime region is usually a SEME as SEH _try.
However there is one rare exception: jumping into a lifetime that has Dtor but
has no Ctor is warned, but allowed:

Warning: jump bypasses variable with a non-trivial destructor

In that case, the region is actually a MEME (multiple entry multiple exits).
Our solution is to inject a eha_scope_begin() invoke in the side entry block to
ensure a correct State.

Implementation:
Part-1: Clang implementation described below.

Two intrinsic are created to track CPP object scopes; eha_scope_begin() and 
eha_scope_end().
_scope_begin() is immediately added after ctor() is called and EHStack is 
pushed.
So it must be an invoke, not a call. With that it's also guaranteed an
EH-cleanup-pad is created regardless whether there exists a call in this scope.
_scope_end is added before dtor(). These two intrinsics make the computation of
Block-State possible in downstream code gen pass, even in the presence of
ctor/dtor inlining.

Two intrinsic, seh_try_begin() and seh_try_end(), are added for C-code to mark
_try boundary and to prevent from exceptions being moved across _try boundary.
All memory instructions inside a _try are considered as 'volatile' to assure
2nd and 3rd rules for C-code above. This is a little sub-optimized. But it's
acceptable as the amount of code directly under _try is very small.

Part-2 (will be in Part-2 patch): LLVM implementation 

RE: [EXTERNAL] [PATCH] D80344: [Windows SEH]: HARDWARE EXCEPTION HANDLING (MSVC -EHa) - Part 1

2021-06-02 Thread Ten Tzen via cfe-commits
Hi, Alexandre
Thank you for reporting this .  From the callstack it does not seem related to 
this patch.  
Could you share the repro case @__compile.rsp temp.i with me?
Thanks,

--Ten

-Original Message-
From: Alexandre Ganea via Phabricator  
Sent: Tuesday, June 1, 2021 12:44 PM
To: Ten Tzen ; andrew.kay...@intel.com; r...@google.com; 
david.majne...@gmail.com; pengfei.w...@intel.com; eli.fried...@gmail.com; 
Joseph Tremoulet ; aaron.lee.sm...@gmail.com; 
jdoerf...@anl.gov; lebedev...@gmail.com; rich...@metafoo.co.uk; 
aaron.ball...@gmail.com; rjmcc...@gmail.com; jan_svob...@apple.com
Cc: markus.boec...@gmail.com; alexandre.ga...@ubisoft.com; 
reviews.llvm@jfbastien.com; belli...@codingworkshop.eu.org; 
dexonsm...@apple.com; aeuba...@google.com; riccib...@gmail.com; 
dany.grumb...@gmail.com; nemanja.i@gmail.com; kristof.be...@arm.com; 
kit.bar...@gmail.com; cfe-commits@lists.llvm.org; llvm-comm...@lists.llvm.org; 
bhuvanendra.kum...@amd.com; ...@gmail.com; dougp...@gmail.com; 
mlek...@skidmore.edu; blitzrak...@gmail.com; shen...@google.com; 
ztur...@roblox.com; yuanfang.c...@sony.com; david.gr...@arm.com; 
kuh...@google.com
Subject: [EXTERNAL] [PATCH] D80344: [Windows SEH]: HARDWARE EXCEPTION HANDLING 
(MSVC -EHa) - Part 1

aganea added a comment.

Hello, this patch introduces a regression in one of our codebases. The 
compilation of several TUs fails with the following callstack:

  PLEASE submit a bug report to 
https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugs.llvm.org%2F&data=04%7C01%7Ctentzen%40microsoft.com%7C0d1857a9e02f491b171a08d92535a510%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637581734644682500%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=aaj5xRDyKWxqKzJHHsxMLCxa%2BuEu%2FSuNy5X7%2FxTUuFs%3D&reserved=0
 and include the crash backtrace, preprocessed source, and associated run 
script.
  Stack dump:
  0.  Program arguments: /media/project2/llvm-project/stage0/bin/clang-cl 
@__compile.rsp temp.i
  1.   parser at end of file
  2.  Optimizer
   #0 0x043c2633 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) 
/media/project2/llvm-project/llvm/lib/Support/Unix/Signals.inc:565:13
   #1 0x043c08f0 llvm::sys::RunSignalHandlers() 
/media/project2/llvm-project/llvm/lib/Support/Signals.cpp:77:18
   #2 0x043c1d7d llvm::sys::CleanupOnSignal(unsigned long) 
/media/project2/llvm-project/llvm/lib/Support/Unix/Signals.inc:0:3
   #3 0x04343206 (anonymous 
namespace)::CrashRecoveryContextImpl::HandleCrash(int, unsigned long) 
/media/project2/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp:75:5
   #4 0x04343206 CrashRecoverySignalHandler(int) 
/media/project2/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp:388:51
   #5 0x7f58152c4a90 __restore_rt sigaction.c:0:0
   #6 0x03c5c11f 
llvm::ilist_sentinel >::empty() const 
/media/project2/llvm-project/llvm/include/llvm/ADT/ilist_node.h:248:36
   #7 0x03c5c11f llvm::simple_ilist::empty() const 
/media/project2/llvm-project/llvm/include/llvm/ADT/simple_ilist.h:131:55
   #8 0x03c5c11f llvm::BasicBlock::empty() const 
/media/project2/llvm-project/llvm/include/llvm/IR/BasicBlock.h:307:66
   #9 0x03c5c11f llvm::BasicBlock::removePredecessor(llvm::BasicBlock*, 
bool) /media/project2/llvm-project/llvm/lib/IR/BasicBlock.cpp:328:7
  #10 0x04432005 markAliveBlocks(llvm::Function&, 
llvm::SmallPtrSetImpl&, llvm::DomTreeUpdater*) 
/media/project2/llvm-project/llvm/lib/Transforms/Utils/Local.cpp:2290:15
  #11 0x04432005 llvm::removeUnreachableBlocks(llvm::Function&, 
llvm::DomTreeUpdater*, llvm::MemorySSAUpdater*) 
/media/project2/llvm-project/llvm/lib/Transforms/Utils/Local.cpp:2402:18
  #12 0x042e72c7 simplifyFunctionCFGImpl(llvm::Function&, 
llvm::TargetTransformInfo const&, llvm::DominatorTree*, 
llvm::SimplifyCFGOptions const&) 
/media/project2/llvm-project/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp:0:22
  #13 0x042e72c7 simplifyFunctionCFG(llvm::Function&, 
llvm::TargetTransformInfo const&, llvm::DominatorTree*, 
llvm::SimplifyCFGOptions const&) 
/media/project2/llvm-project/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp:275:18
  #14 0x042e70d1 llvm::SimplifyCFGPass::run(llvm::Function&, 
llvm::AnalysisManager&) 
/media/project2/llvm-project/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp:321:7
  #15 0x02e605bd llvm::detail::PassModel >::run(llvm::Function&, 
llvm::AnalysisManager&) BPFTargetMachine.cpp:0:0
  #16 0x03d54659 llvm::SmallPtrSet::operator=(llvm::SmallPtrSet&&) 
/media/project2/llvm-project/llvm/include/llvm/ADT/SmallPtrSet.h:488:13
  #17 0x03d54659 
llvm::PreservedAnalyses::operator=(llvm::PreservedAnalyses&&) 
/media/project2/llvm-project/llvm/include/llvm/IR/PassManager.h:155:7
  #18 0x03d54659 llvm::PassManager >::run(llvm::Function&, 
llvm::AnalysisManager&) 
/media/project2/llvm-pro

[clang] 33ba8bd - [Windows SEH]: Fix -O2 crash for Windows -EHa

2021-06-04 Thread Ten Tzen via cfe-commits

Author: Ten Tzen
Date: 2021-06-04T14:07:44-07:00
New Revision: 33ba8bd2c942062731a17e1b864b5953e3d79f1a

URL: 
https://github.com/llvm/llvm-project/commit/33ba8bd2c942062731a17e1b864b5953e3d79f1a
DIFF: 
https://github.com/llvm/llvm-project/commit/33ba8bd2c942062731a17e1b864b5953e3d79f1a.diff

LOG: [Windows SEH]: Fix -O2 crash for Windows -EHa

This patch fixes a Windows -EHa crash induced by previous commit 
797ad701522988e212495285dade8efac41a24d4.
The crash was caused by "LifetimeMarker" scope (with option -O2) that should 
not be considered as SEH Scope.

This change also turns off -fasync-exceptions by default under -EHa option for 
now.

Differential Revision: https://reviews.llvm.org/D103664#2799944

Added: 


Modified: 
clang/lib/CodeGen/CGCleanup.cpp
clang/lib/Driver/ToolChains/Clang.cpp

Removed: 




diff  --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp
index b439204cf047..b9364fcd2231 100644
--- a/clang/lib/CodeGen/CGCleanup.cpp
+++ b/clang/lib/CodeGen/CGCleanup.cpp
@@ -195,7 +195,7 @@ void *EHScopeStack::pushCleanup(CleanupKind Kind, size_t 
Size) {
 Scope->setLifetimeMarker();
 
   // With Windows -EHa, Invoke llvm.seh.scope.begin() for EHCleanup
-  if (CGF->getLangOpts().EHAsynch && IsEHCleanup &&
+  if (CGF->getLangOpts().EHAsynch && IsEHCleanup && !IsLifetimeMarker &&
   CGF->getTarget().getCXXABI().isMicrosoft())
 CGF->EmitSehCppScopeBegin();
 

diff  --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index ee40df35b850..a0e1208fd709 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7151,8 +7151,6 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID 
InputType,
 if (types::isCXX(InputType))
   CmdArgs.push_back("-fcxx-exceptions");
 CmdArgs.push_back("-fexceptions");
-if (EH.Asynch)
-  CmdArgs.push_back("-fasync-exceptions");
   }
   if (types::isCXX(InputType) && EH.Synch && EH.NoUnwindC)
 CmdArgs.push_back("-fexternc-nounwind");



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits