Skip to content

Commit

Permalink
Move the personality function from LandingPadInst to Function
Browse files Browse the repository at this point in the history
The personality routine currently lives in the LandingPadInst.

This isn't desirable because:
- All LandingPadInsts in the same function must have the same
  personality routine.  This means that each LandingPadInst beyond the
  first has an operand which produces no additional information.

- There is ongoing work to introduce EH IR constructs other than
  LandingPadInst.  Moving the personality routine off of any one
  particular Instruction and onto the parent function seems a lot better
  than have N different places a personality function can sneak onto an
  exceptional function.

Differential Revision: http://reviews.llvm.org/D10429

llvm-svn: 239940
  • Loading branch information
majnemer committed Jun 17, 2015
1 parent f329914 commit 7fddecc
Show file tree
Hide file tree
Showing 313 changed files with 1,350 additions and 1,258 deletions.
4 changes: 3 additions & 1 deletion llvm/docs/BitCodeFormat.rst
Expand Up @@ -741,7 +741,7 @@ global variable. The operand fields are:
MODULE_CODE_FUNCTION Record
^^^^^^^^^^^^^^^^^^^^^^^^^^^

``[FUNCTION, type, callingconv, isproto, linkage, paramattr, alignment, section, visibility, gc, prologuedata, dllstorageclass, comdat, prefixdata]``
``[FUNCTION, type, callingconv, isproto, linkage, paramattr, alignment, section, visibility, gc, prologuedata, dllstorageclass, comdat, prefixdata, personalityfn]``

The ``FUNCTION`` record (code 8) marks the declaration or definition of a
function. The operand fields are:
Expand Down Expand Up @@ -795,6 +795,8 @@ function. The operand fields are:
* *prefixdata*: If non-zero, the value index of the prefix data for this function,
plus 1.

* *personalityfn*: If non-zero, the value index of the personality function for this function,
plus 1.

MODULE_CODE_ALIAS Record
^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
35 changes: 21 additions & 14 deletions llvm/docs/LangRef.rst
Expand Up @@ -635,8 +635,9 @@ attributes <paramattrs>`), optional :ref:`function attributes <fnattrs>`,
an optional section, an optional alignment,
an optional :ref:`comdat <langref_comdats>`,
an optional :ref:`garbage collector name <gc>`, an optional :ref:`prefix <prefixdata>`,
an optional :ref:`prologue <prologuedata>`, an opening
curly brace, a list of basic blocks, and a closing curly brace.
an optional :ref:`prologue <prologuedata>`,
an optional :ref:`personality <personalityfn>`,
an opening curly brace, a list of basic blocks, and a closing curly brace.

LLVM function declarations consist of the "``declare``" keyword, an
optional :ref:`linkage type <linkage>`, an optional :ref:`visibility
Expand Down Expand Up @@ -683,7 +684,8 @@ Syntax::
[cconv] [ret attrs]
<ResultType> @<FunctionName> ([argument list])
[unnamed_addr] [fn Attrs] [section "name"] [comdat [($name)]]
[align N] [gc] [prefix Constant] [prologue Constant] { ... }
[align N] [gc] [prefix Constant] [prologue Constant]
[personality Constant] { ... }

The argument list is a comma seperated sequence of arguments where each
argument is of the following form
Expand Down Expand Up @@ -1130,6 +1132,14 @@ A function may have prologue data but no body. This has similar semantics
to the ``available_externally`` linkage in that the data may be used by the
optimizers but will not be emitted in the object file.

.. _personalityfn:

Personality Function
-------------

The ``personality`` attribute permits functions to specify what function
to use for exception handling.

.. _attrgrp:

Attribute Groups
Expand Down Expand Up @@ -7283,8 +7293,8 @@ Syntax:

::

<resultval> = landingpad <resultty> personality <type> <pers_fn> <clause>+
<resultval> = landingpad <resultty> personality <type> <pers_fn> cleanup <clause>*
<resultval> = landingpad <resultty> <clause>+
<resultval> = landingpad <resultty> cleanup <clause>*

<clause> := catch <type> <value>
<clause> := filter <array constant type> <array constant>
Expand All @@ -7296,14 +7306,13 @@ The '``landingpad``' instruction is used by `LLVM's exception handling
system <ExceptionHandling.html#overview>`_ to specify that a basic block
is a landing pad --- one where the exception lands, and corresponds to the
code found in the ``catch`` portion of a ``try``/``catch`` sequence. It
defines values supplied by the personality function (``pers_fn``) upon
defines values supplied by the :ref:`personality function <personalityfn>` upon
re-entry to the function. The ``resultval`` has the type ``resultty``.

Arguments:
""""""""""

This instruction takes a ``pers_fn`` value. This is the personality
function associated with the unwinding mechanism. The optional
The optional
``cleanup`` flag indicates that the landing pad block is a cleanup.

A ``clause`` begins with the clause type --- ``catch`` or ``filter`` --- and
Expand All @@ -7318,7 +7327,7 @@ Semantics:
""""""""""

The '``landingpad``' instruction defines the values which are set by the
personality function (``pers_fn``) upon re-entry to the function, and
:ref:`personality function <personalityfn>` upon re-entry to the function, and
therefore the "result type" of the ``landingpad`` instruction. As with
calling conventions, how the personality function results are
represented in LLVM IR is target specific.
Expand All @@ -7341,22 +7350,20 @@ The ``landingpad`` instruction has several restrictions:
pad block.
- A basic block that is not a landing pad block may not include a
'``landingpad``' instruction.
- All '``landingpad``' instructions in a function must have the same
personality function.

Example:
""""""""

.. code-block:: llvm
;; A landing pad which can catch an integer.
%res = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
%res = landingpad { i8*, i32 }
catch i8** @_ZTIi
;; A landing pad that is a cleanup.
%res = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
%res = landingpad { i8*, i32 }
cleanup
;; A landing pad which can catch an integer and can only throw a double.
%res = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
%res = landingpad { i8*, i32 }
catch i8** @_ZTIi
filter [1 x i8**] [@_ZTId]
Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/Analysis/LibCallSemantics.h
Expand Up @@ -206,7 +206,7 @@ class InvokeInst;
llvm_unreachable("invalid enum");
}

bool canSimplifyInvokeNoUnwind(const InvokeInst *II);
bool canSimplifyInvokeNoUnwind(const Function *F);

} // end namespace llvm

Expand Down
3 changes: 2 additions & 1 deletion llvm/include/llvm/Bitcode/LLVMBitCodes.h
Expand Up @@ -342,7 +342,7 @@ namespace bitc {
// align, vol,
// ordering, synchscope]
FUNC_CODE_INST_RESUME = 39, // RESUME: [opval]
FUNC_CODE_INST_LANDINGPAD = 40, // LANDINGPAD: [ty,val,val,num,id0,val0...]
FUNC_CODE_INST_LANDINGPAD_OLD = 40, // LANDINGPAD: [ty,val,val,num,id0,val0...]
FUNC_CODE_INST_LOADATOMIC = 41, // LOAD: [opty, op, align, vol,
// ordering, synchscope]
FUNC_CODE_INST_STOREATOMIC_OLD = 42, // STORE: [ptrty,ptr,val, align, vol
Expand All @@ -352,6 +352,7 @@ namespace bitc {
FUNC_CODE_INST_STOREATOMIC = 45, // STORE: [ptrty,ptr,val, align, vol
FUNC_CODE_INST_CMPXCHG = 46, // CMPXCHG: [ptrty,ptr,valty,cmp,new, align,
// vol,ordering,synchscope]
FUNC_CODE_INST_LANDINGPAD = 47, // LANDINGPAD: [ty,val,num,id0,val0...]
};

enum UseListCodes {
Expand Down
19 changes: 18 additions & 1 deletion llvm/include/llvm/IR/Function.h
Expand Up @@ -25,6 +25,7 @@
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/GlobalObject.h"
#include "llvm/IR/OperandTraits.h"
#include "llvm/Support/Compiler.h"

namespace llvm {
Expand Down Expand Up @@ -119,11 +120,22 @@ class Function : public GlobalObject, public ilist_node<Function> {
public:
static Function *Create(FunctionType *Ty, LinkageTypes Linkage,
const Twine &N = "", Module *M = nullptr) {
return new(0) Function(Ty, Linkage, N, M);
return new(1) Function(Ty, Linkage, N, M);
}

~Function() override;

/// \brief Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);

/// \brief Get the personality function associated with this function.
bool hasPersonalityFn() const { return getNumOperands() != 0; }
Constant *getPersonalityFn() const {
assert(hasPersonalityFn());
return cast<Constant>(Op<0>());
}
void setPersonalityFn(Constant *C);

Type *getReturnType() const; // Return the type of the ret val
FunctionType *getFunctionType() const; // Return the FunctionType for me

Expand Down Expand Up @@ -601,6 +613,11 @@ ilist_traits<Argument>::getSymTab(Function *F) {
return F ? &F->getValueSymbolTable() : nullptr;
}

template <>
struct OperandTraits<Function> : public OptionalOperandTraits<Function> {};

DEFINE_TRANSPARENT_OPERAND_ACCESSORS(Function, Value)

} // End llvm namespace

#endif
4 changes: 2 additions & 2 deletions llvm/include/llvm/IR/IRBuilder.h
Expand Up @@ -1556,9 +1556,9 @@ class IRBuilder : public IRBuilderBase, public Inserter {
return Insert(InsertValueInst::Create(Agg, Val, Idxs), Name);
}

LandingPadInst *CreateLandingPad(Type *Ty, Value *PersFn, unsigned NumClauses,
LandingPadInst *CreateLandingPad(Type *Ty, unsigned NumClauses,
const Twine &Name = "") {
return Insert(LandingPadInst::Create(Ty, PersFn, NumClauses), Name);
return Insert(LandingPadInst::Create(Ty, NumClauses), Name);
}

//===--------------------------------------------------------------------===//
Expand Down
33 changes: 13 additions & 20 deletions llvm/include/llvm/IR/Instructions.h
Expand Up @@ -2437,34 +2437,27 @@ class LandingPadInst : public Instruction {
return User::operator new(s);
}
void growOperands(unsigned Size);
void init(Value *PersFn, unsigned NumReservedValues, const Twine &NameStr);
void init(unsigned NumReservedValues, const Twine &NameStr);

explicit LandingPadInst(Type *RetTy, unsigned NumReservedValues,
const Twine &NameStr, Instruction *InsertBefore);
explicit LandingPadInst(Type *RetTy, unsigned NumReservedValues,
const Twine &NameStr, BasicBlock *InsertAtEnd);

explicit LandingPadInst(Type *RetTy, Value *PersonalityFn,
unsigned NumReservedValues, const Twine &NameStr,
Instruction *InsertBefore);
explicit LandingPadInst(Type *RetTy, Value *PersonalityFn,
unsigned NumReservedValues, const Twine &NameStr,
BasicBlock *InsertAtEnd);
protected:
LandingPadInst *clone_impl() const override;
public:
/// Constructors - NumReservedClauses is a hint for the number of incoming
/// clauses that this landingpad will have (use 0 if you really have no idea).
static LandingPadInst *Create(Type *RetTy, Value *PersonalityFn,
unsigned NumReservedClauses,
static LandingPadInst *Create(Type *RetTy, unsigned NumReservedClauses,
const Twine &NameStr = "",
Instruction *InsertBefore = nullptr);
static LandingPadInst *Create(Type *RetTy, Value *PersonalityFn,
unsigned NumReservedClauses,
static LandingPadInst *Create(Type *RetTy, unsigned NumReservedClauses,
const Twine &NameStr, BasicBlock *InsertAtEnd);

/// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);

/// getPersonalityFn - Get the personality function associated with this
/// landing pad.
Value *getPersonalityFn() const { return getOperand(0); }

/// isCleanup - Return 'true' if this landingpad instruction is a
/// cleanup. I.e., it should be run when unwinding even if its landing pad
/// doesn't catch the exception.
Expand All @@ -2482,21 +2475,21 @@ class LandingPadInst : public Instruction {
/// Get the value of the clause at index Idx. Use isCatch/isFilter to
/// determine what type of clause this is.
Constant *getClause(unsigned Idx) const {
return cast<Constant>(getOperandList()[Idx + 1]);
return cast<Constant>(getOperandList()[Idx]);
}

/// isCatch - Return 'true' if the clause and index Idx is a catch clause.
bool isCatch(unsigned Idx) const {
return !isa<ArrayType>(getOperandList()[Idx + 1]->getType());
return !isa<ArrayType>(getOperandList()[Idx]->getType());
}

/// isFilter - Return 'true' if the clause and index Idx is a filter clause.
bool isFilter(unsigned Idx) const {
return isa<ArrayType>(getOperandList()[Idx + 1]->getType());
return isa<ArrayType>(getOperandList()[Idx]->getType());
}

/// getNumClauses - Get the number of clauses for this landing pad.
unsigned getNumClauses() const { return getNumOperands() - 1; }
unsigned getNumClauses() const { return getNumOperands(); }

/// reserveClauses - Grow the size of the operand list to accommodate the new
/// number of clauses.
Expand All @@ -2512,7 +2505,7 @@ class LandingPadInst : public Instruction {
};

template <>
struct OperandTraits<LandingPadInst> : public HungoffOperandTraits<2> {
struct OperandTraits<LandingPadInst> : public HungoffOperandTraits<1> {
};

DEFINE_TRANSPARENT_OPERAND_ACCESSORS(LandingPadInst, Value)
Expand Down
13 changes: 13 additions & 0 deletions llvm/include/llvm/IR/User.h
Expand Up @@ -150,6 +150,19 @@ class User : public Value {
NumUserOperands = NumOps;
}

/// Set the number of operands on a Function.
///
/// Function always allocates space for a single operands, but
/// doesn't always use it.
///
/// FIXME: As that the number of operands is used to find the start of
/// the allocated memory in operator delete, we need to always think we have
/// 1 operand before delete.
void setFunctionNumOperands(unsigned NumOps) {
assert(NumOps <= 1 && "Function can only have 0 or 1 operands");
NumUserOperands = NumOps;
}

/// \brief Subclasses with hung off uses need to manage the operand count
/// themselves. In these instances, the operand count isn't used to find the
/// OperandList, so there's no issue in having the operand count change.
Expand Down
5 changes: 2 additions & 3 deletions llvm/lib/Analysis/LibCallSemantics.cpp
Expand Up @@ -80,9 +80,8 @@ EHPersonality llvm::classifyEHPersonality(const Value *Pers) {
.Default(EHPersonality::Unknown);
}

bool llvm::canSimplifyInvokeNoUnwind(const InvokeInst *II) {
const LandingPadInst *LP = II->getLandingPadInst();
EHPersonality Personality = classifyEHPersonality(LP->getPersonalityFn());
bool llvm::canSimplifyInvokeNoUnwind(const Function *F) {
EHPersonality Personality = classifyEHPersonality(F->getPersonalityFn());
// We can't simplify any invokes to nounwind functions if the personality
// function wants to catch asynch exceptions. The nounwind attribute only
// implies that the function does not throw synchronous exceptions.
Expand Down
15 changes: 8 additions & 7 deletions llvm/lib/AsmParser/LLParser.cpp
Expand Up @@ -4057,7 +4057,7 @@ bool LLParser::ParseTypeAndBasicBlock(BasicBlock *&BB, LocTy &Loc,
/// FunctionHeader
/// ::= OptionalLinkage OptionalVisibility OptionalCallingConv OptRetAttrs
/// OptUnnamedAddr Type GlobalName '(' ArgList ')' OptFuncAttrs OptSection
/// OptionalAlign OptGC OptionalPrefix OptionalPrologue
/// OptionalAlign OptGC OptionalPrefix OptionalPrologue OptPersonalityFn
bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
// Parse the linkage.
LocTy LinkageLoc = Lex.getLoc();
Expand Down Expand Up @@ -4139,6 +4139,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
LocTy UnnamedAddrLoc;
Constant *Prefix = nullptr;
Constant *Prologue = nullptr;
Constant *PersonalityFn = nullptr;
Comdat *C;

if (ParseArgumentList(ArgList, isVarArg) ||
Expand All @@ -4155,7 +4156,9 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
(EatIfPresent(lltok::kw_prefix) &&
ParseGlobalTypeAndValue(Prefix)) ||
(EatIfPresent(lltok::kw_prologue) &&
ParseGlobalTypeAndValue(Prologue)))
ParseGlobalTypeAndValue(Prologue)) ||
(EatIfPresent(lltok::kw_personality) &&
ParseGlobalTypeAndValue(PersonalityFn)))
return true;

if (FuncAttrs.contains(Attribute::Builtin))
Expand Down Expand Up @@ -4254,6 +4257,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
Fn->setAlignment(Alignment);
Fn->setSection(Section);
Fn->setComdat(C);
Fn->setPersonalityFn(PersonalityFn);
if (!GC.empty()) Fn->setGC(GC.c_str());
Fn->setPrefixData(Prefix);
Fn->setPrologueData(Prologue);
Expand Down Expand Up @@ -5105,14 +5109,11 @@ int LLParser::ParsePHI(Instruction *&Inst, PerFunctionState &PFS) {
/// ::= 'filter' TypeAndValue ( ',' TypeAndValue )*
bool LLParser::ParseLandingPad(Instruction *&Inst, PerFunctionState &PFS) {
Type *Ty = nullptr; LocTy TyLoc;
Value *PersFn; LocTy PersFnLoc;

if (ParseType(Ty, TyLoc) ||
ParseToken(lltok::kw_personality, "expected 'personality'") ||
ParseTypeAndValue(PersFn, PersFnLoc, PFS))
if (ParseType(Ty, TyLoc))
return true;

std::unique_ptr<LandingPadInst> LP(LandingPadInst::Create(Ty, PersFn, 0));
std::unique_ptr<LandingPadInst> LP(LandingPadInst::Create(Ty, 0));
LP->setCleanup(EatIfPresent(lltok::kw_cleanup));

while (Lex.getKind() == lltok::kw_catch || Lex.getKind() == lltok::kw_filter){
Expand Down

0 comments on commit 7fddecc

Please sign in to comment.