mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-03 16:03:21 +00:00
[WinEH] Add a funclet layout pass
Windows EH funclets need to be contiguous. The FuncletLayout pass will ensure that the funclets are together and begin with a funclet entry MBB. Differential Revision: http://reviews.llvm.org/D12943 llvm-svn: 247937
This commit is contained in:
parent
5b8a46e771
commit
978902309a
@ -582,6 +582,9 @@ namespace llvm {
|
||||
/// StackSlotColoring - This pass performs stack slot coloring.
|
||||
extern char &StackSlotColoringID;
|
||||
|
||||
/// \brief This pass lays out funclets contiguously.
|
||||
extern char &FuncletLayoutID;
|
||||
|
||||
/// createStackProtectorPass - This pass adds stack protectors to functions.
|
||||
///
|
||||
FunctionPass *createStackProtectorPass(const TargetMachine *TM);
|
||||
|
@ -299,6 +299,7 @@ void initializeFloat2IntPass(PassRegistry&);
|
||||
void initializeLoopDistributePass(PassRegistry&);
|
||||
void initializeSjLjEHPreparePass(PassRegistry&);
|
||||
void initializeDemandedBitsPass(PassRegistry&);
|
||||
void initializeFuncletLayoutPass(PassRegistry &);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -26,6 +26,7 @@ add_llvm_library(LLVMCodeGen
|
||||
ExpandISelPseudos.cpp
|
||||
ExpandPostRAPseudos.cpp
|
||||
FaultMaps.cpp
|
||||
FuncletLayout.cpp
|
||||
GCMetadata.cpp
|
||||
GCMetadataPrinter.cpp
|
||||
GCRootLowering.cpp
|
||||
|
@ -29,6 +29,7 @@ void llvm::initializeCodeGen(PassRegistry &Registry) {
|
||||
initializeExpandISelPseudosPass(Registry);
|
||||
initializeExpandPostRAPass(Registry);
|
||||
initializeFinalizeMachineBundlesPass(Registry);
|
||||
initializeFuncletLayoutPass(Registry);
|
||||
initializeGCMachineCodeAnalysisPass(Registry);
|
||||
initializeGCModuleInfoPass(Registry);
|
||||
initializeIfConverterPass(Registry);
|
||||
|
97
llvm/lib/CodeGen/FuncletLayout.cpp
Normal file
97
llvm/lib/CodeGen/FuncletLayout.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
//===-- FuncletLayout.cpp - Contiguously lay out funclets -----------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements basic block placement transformations which result in
|
||||
// funclets being contiguous.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "llvm/CodeGen/Passes.h"
|
||||
#include "llvm/ADT/MapVector.h"
|
||||
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineModuleInfo.h"
|
||||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "funclet-layout"
|
||||
|
||||
namespace {
|
||||
class FuncletLayout : public MachineFunctionPass {
|
||||
public:
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
FuncletLayout() : MachineFunctionPass(ID) {
|
||||
initializeFuncletLayoutPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
bool runOnMachineFunction(MachineFunction &F) override;
|
||||
};
|
||||
}
|
||||
|
||||
static void
|
||||
collectFuncletMembers(MapVector<MachineBasicBlock *, int> &FuncletMembership,
|
||||
int Funclet, MachineBasicBlock *MBB) {
|
||||
// Don't revisit blocks.
|
||||
if (FuncletMembership.count(MBB) > 0)
|
||||
return;
|
||||
|
||||
// Add this MBB to our funclet.
|
||||
FuncletMembership[MBB] = Funclet;
|
||||
|
||||
bool IsReturn = false;
|
||||
int NumTerminators = 0;
|
||||
for (MachineInstr &MI : MBB->terminators()) {
|
||||
IsReturn |= MI.isReturn();
|
||||
++NumTerminators;
|
||||
}
|
||||
assert((!IsReturn || NumTerminators == 1) &&
|
||||
"Expected only one terminator when a return is present!");
|
||||
|
||||
// Returns are boundaries where funclet transfer can occur, don't follow
|
||||
// successors.
|
||||
if (IsReturn)
|
||||
return;
|
||||
|
||||
for (MachineBasicBlock *SMBB : MBB->successors())
|
||||
if (!SMBB->isEHPad())
|
||||
collectFuncletMembers(FuncletMembership, Funclet, SMBB);
|
||||
}
|
||||
|
||||
char FuncletLayout::ID = 0;
|
||||
char &llvm::FuncletLayoutID = FuncletLayout::ID;
|
||||
INITIALIZE_PASS(FuncletLayout, "funclet-layout",
|
||||
"Contiguously Lay Out Funclets", false, false)
|
||||
|
||||
bool FuncletLayout::runOnMachineFunction(MachineFunction &F) {
|
||||
// We don't have anything to do if there aren't any EH pads.
|
||||
if (!F.getMMI().hasEHFunclets())
|
||||
return false;
|
||||
|
||||
SmallVector<MachineBasicBlock *, 16> FuncletBlocks;
|
||||
for (MachineBasicBlock &MBB : F)
|
||||
if (MBB.isEHFuncletEntry())
|
||||
FuncletBlocks.push_back(&MBB);
|
||||
|
||||
// We don't have anything to do if there aren't any EH pads.
|
||||
if (FuncletBlocks.empty())
|
||||
return false;
|
||||
|
||||
MapVector<MachineBasicBlock *, int> FuncletMembership;
|
||||
for (MachineBasicBlock *MBB : FuncletBlocks)
|
||||
collectFuncletMembers(FuncletMembership, MBB->getNumber(), MBB);
|
||||
|
||||
for (std::pair<llvm::MachineBasicBlock *, int> &FuncletMember :
|
||||
FuncletMembership) {
|
||||
// Move this block to the end of the function.
|
||||
MachineBasicBlock *MBB = FuncletMember.first;
|
||||
MBB->moveAfter(--F.end());
|
||||
}
|
||||
|
||||
// Conservatively assume we changed something.
|
||||
return true;
|
||||
}
|
@ -582,6 +582,8 @@ void TargetPassConfig::addMachinePasses() {
|
||||
|
||||
addPreEmitPass();
|
||||
|
||||
addPass(&FuncletLayoutID, false);
|
||||
|
||||
addPass(&StackMapLivenessID, false);
|
||||
|
||||
AddingMachinePasses = false;
|
||||
|
45
llvm/test/CodeGen/X86/funclet-layout.ll
Normal file
45
llvm/test/CodeGen/X86/funclet-layout.ll
Normal file
@ -0,0 +1,45 @@
|
||||
; RUN: llc -mtriple=x86_64-windows-msvc < %s | FileCheck %s
|
||||
|
||||
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-pc-windows-msvc"
|
||||
|
||||
define void @f(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
|
||||
entry:
|
||||
invoke void @g()
|
||||
to label %unreachable unwind label %catch.dispatch
|
||||
|
||||
catch.dispatch:
|
||||
%cp = catchpad [i8* null, i32 64, i8* null]
|
||||
to label %catch unwind label %catchendblock
|
||||
|
||||
catch:
|
||||
br i1 %B, label %catchret, label %catch
|
||||
|
||||
catchret:
|
||||
catchret %cp to label %try.cont
|
||||
|
||||
try.cont:
|
||||
ret void
|
||||
|
||||
catchendblock:
|
||||
catchendpad unwind to caller
|
||||
|
||||
unreachable:
|
||||
unreachable
|
||||
}
|
||||
|
||||
; CHECK-LABEL: f:
|
||||
|
||||
; The entry funclet contains %entry and %try.cont
|
||||
; CHECK: # %entry
|
||||
; CHECK: # %try.cont
|
||||
; CHECK: retq
|
||||
|
||||
; The catch funclet contains %catch and %catchret
|
||||
; CHECK: # %catch
|
||||
; CHECK: # %catchret
|
||||
; CHECK: retq
|
||||
|
||||
declare void @g()
|
||||
|
||||
declare i32 @__CxxFrameHandler3(...)
|
Loading…
x
Reference in New Issue
Block a user