Fix PR1146: parameter attributes are longer part of

the function type, instead they belong to functions
and function calls.  This is an updated and slightly
corrected version of Reid Spencer's original patch.
The only known problem is that auto-upgrading of
bitcode files doesn't seem to work properly (see
test/Bitcode/AutoUpgradeIntrinsics.ll).  Hopefully
a bitcode guru (who might that be? :) ) will fix it.

llvm-svn: 44359
This commit is contained in:
Duncan Sands 2007-11-27 13:23:08 +00:00
parent db3467f8d4
commit ad0ea2d430
51 changed files with 6340 additions and 5206 deletions

View File

@ -764,9 +764,9 @@ a power of 2.</p>
<p>The return type and each parameter of a function type may have a set of
<i>parameter attributes</i> associated with them. Parameter attributes are
used to communicate additional information about the result or parameters of
a function. Parameter attributes are considered to be part of the function
type so two functions types that differ only by the parameter attributes
are different function types.</p>
a function. Parameter attributes are considered to be part of the function,
not of the function type, so functions with different parameter attributes
can have the same function type.</p>
<p>Parameter attributes are simple keywords that follow the type specified. If
multiple parameter attributes are needed, they are space separated. For
@ -774,15 +774,13 @@ a power of 2.</p>
<div class="doc_code">
<pre>
%someFunc = i16 (i8 signext %someParam) zeroext
%someFunc = i16 (i8 zeroext %someParam) zeroext
declare i32 @printf(i8* noalias , ...) nounwind
declare i32 @atoi(i8*) nounwind readonly
</pre>
</div>
<p>Note that the two function types above are unique because the parameter has
a different attribute (<tt>signext</tt> in the first one, <tt>zeroext</tt> in
the second). Also note that the attribute for the function result
(<tt>zeroext</tt>) comes immediately after the argument list.</p>
<p>Note that any attributes for the function result (<tt>nounwind</tt>,
<tt>readonly</tt>) come immediately after the argument list.</p>
<p>Currently, only the following parameter attributes are defined:</p>
<dl>

View File

@ -31,7 +31,6 @@ class PointerValType;
class VectorValType;
class IntegerValType;
class APInt;
class ParamAttrsList;
class DerivedType : public Type {
friend class Type;
@ -140,12 +139,11 @@ public:
class FunctionType : public DerivedType {
friend class TypeMap<FunctionValType, FunctionType>;
bool isVarArgs;
const ParamAttrsList *ParamAttrs;
FunctionType(const FunctionType &); // Do not implement
const FunctionType &operator=(const FunctionType &); // Do not implement
FunctionType(const Type *Result, const std::vector<const Type*> &Params,
bool IsVarArgs, const ParamAttrsList *Attrs = 0);
bool IsVarArgs);
public:
/// FunctionType::get - This static method is the primary way of constructing
@ -154,12 +152,7 @@ public:
static FunctionType *get(
const Type *Result, ///< The result type
const std::vector<const Type*> &Params, ///< The types of the parameters
bool isVarArg, ///< Whether this is a variable argument length function
const ParamAttrsList *Attrs = 0
///< Indicates the parameter attributes to use, if any. The 0th entry
///< in the list refers to the return type. Parameters are numbered
///< starting at 1. This argument must be on the heap and FunctionType
///< owns it after its passed here.
bool isVarArg ///< Whether this is a variable argument length function
);
inline bool isVarArg() const { return isVarArgs; }
@ -177,14 +170,6 @@ public:
///
unsigned getNumParams() const { return NumContainedTys - 1; }
bool isStructReturn() const;
/// The parameter attributes for the \p ith parameter are returned. The 0th
/// parameter refers to the return type of the function.
/// @returns The ParameterAttributes for the \p ith parameter.
/// @brief Get the attributes for a parameter
const ParamAttrsList *getParamAttrs() const { return ParamAttrs; }
// Implement the AbstractTypeUser interface.
virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
virtual void typeBecameConcrete(const DerivedType *AbsTy);

View File

@ -68,7 +68,7 @@ private:
BasicBlockListType BasicBlocks; ///< The basic blocks
mutable ArgumentListType ArgumentList; ///< The formal arguments
ValueSymbolTable *SymTab; ///< Symbol table of args/instructions
ParamAttrsList *ParamAttrs; ///< Parameter attributes
const ParamAttrsList *ParamAttrs; ///< Parameter attributes
// The Calling Convention is stored in Value::SubclassData.
/*unsigned CallingConvention;*/
@ -150,7 +150,10 @@ public:
/// Sets the parameter attributes for this Function. To construct a
/// ParamAttrsList, see ParameterAttributes.h
/// @brief Set the parameter attributes.
void setParamAttrs(ParamAttrsList *attrs);
void setParamAttrs(const ParamAttrsList *attrs);
/// @brief Determine if the function returns a structure.
bool isStructReturn() const;
/// deleteBody - This method deletes the body of the function, and converts
/// the linkage to external.

View File

@ -836,7 +836,7 @@ public:
///
class CallInst : public Instruction {
ParamAttrsList *ParamAttrs; ///< parameter attributes for call
const ParamAttrsList *ParamAttrs; ///< parameter attributes for call
CallInst(const CallInst &CI);
void init(Value *Func, Value* const *Params, unsigned NumParams);
void init(Value *Func, Value *Actual1, Value *Actual2);
@ -916,12 +916,15 @@ public:
/// parameter attributes information, if any.
/// @returns 0 if no attributes have been set.
/// @brief Get the parameter attributes.
ParamAttrsList *getParamAttrs() const { return ParamAttrs; }
const ParamAttrsList *getParamAttrs() const { return ParamAttrs; }
/// Sets the parameter attributes for this CallInst. To construct a
/// ParamAttrsList, see ParameterAttributes.h
/// @brief Set the parameter attributes.
void setParamAttrs(ParamAttrsList *attrs);
void setParamAttrs(const ParamAttrsList *attrs);
/// @brief Determine if the call returns a structure.
bool isStructReturn() const;
/// getCalledFunction - Return the function being called by this instruction
/// if it is a direct call. If it is a call through a function pointer,
@ -1620,7 +1623,7 @@ private:
/// calling convention of the call.
///
class InvokeInst : public TerminatorInst {
ParamAttrsList *ParamAttrs;
const ParamAttrsList *ParamAttrs;
InvokeInst(const InvokeInst &BI);
void init(Value *Fn, BasicBlock *IfNormal, BasicBlock *IfException,
Value* const *Args, unsigned NumArgs);
@ -1691,12 +1694,15 @@ public:
/// parameter attributes information, if any.
/// @returns 0 if no attributes have been set.
/// @brief Get the parameter attributes.
ParamAttrsList *getParamAttrs() const { return ParamAttrs; }
const ParamAttrsList *getParamAttrs() const { return ParamAttrs; }
/// Sets the parameter attributes for this InvokeInst. To construct a
/// ParamAttrsList, see ParameterAttributes.h
/// @brief Set the parameter attributes.
void setParamAttrs(ParamAttrsList *attrs);
void setParamAttrs(const ParamAttrsList *attrs);
/// @brief Determine if the call returns a structure.
bool isStructReturn() const;
/// getCalledFunction - Return the function called, or null if this is an
/// indirect function invocation.

View File

@ -77,7 +77,7 @@ const uint16_t MutuallyIncompatible[3] = {
/// with a parameter index.
/// @brief ParameterAttributes with a parameter index.
struct ParamAttrsWithIndex {
uint16_t attrs; ///< The attributes that are set, |'d together
uint16_t attrs; ///< The attributes that are set, or'd together
uint16_t index; ///< Index of the parameter for which the attributes apply
static ParamAttrsWithIndex get(uint16_t idx, uint16_t attrs) {
@ -219,6 +219,13 @@ class ParamAttrsList : public FoldingSetNode {
/// @brief Return the number of parameter attributes this type has.
unsigned size() const { return attrs.size(); }
/// @brief Return the number of references to this ParamAttrsList.
unsigned numRefs() const { return refCount; }
/// @}
/// @name Mutators
/// @{
public:
/// Classes retaining references to ParamAttrsList objects should call this
/// method to increment the reference count. This ensures that the
/// ParamAttrsList object will not disappear until the class drops it.

View File

@ -27,6 +27,7 @@ namespace llvm {
class CallInst;
class InvokeInst;
class ParamAttrsList;
class CallSite {
Instruction *I;
@ -57,6 +58,11 @@ public:
unsigned getCallingConv() const;
void setCallingConv(unsigned CC);
/// getParamAttrs/setParamAttrs - get or set the parameter attributes of
/// the call.
const ParamAttrsList *getParamAttrs() const;
void setParamAttrs(const ParamAttrsList *PAL);
/// getType - Return the type of the instruction that generated this call site
///
const Type *getType() const { return I->getType(); }

View File

@ -268,7 +268,7 @@ BasicAliasAnalysis::getModRefInfo(CallSite CS, Value *P, unsigned Size) {
static bool isNoAliasArgument(const Argument *Arg) {
const Function *Func = Arg->getParent();
const ParamAttrsList *Attr = Func->getFunctionType()->getParamAttrs();
const ParamAttrsList *Attr = Func->getParamAttrs();
if (Attr) {
unsigned Idx = 1;
for (Function::const_arg_iterator I = Func->arg_begin(),
@ -839,7 +839,7 @@ BasicAliasAnalysis::getModRefBehavior(Function *F, CallSite CS,
return UnknownModRefBehavior;
}
const ParamAttrsList *Attrs = F->getFunctionType()->getParamAttrs();
const ParamAttrsList *Attrs = F->getParamAttrs();
if (Attrs && Attrs->paramHasAttr(0, ParamAttr::ReadNone))
return DoesNotAccessMemory;
if (Attrs && Attrs->paramHasAttr(0, ParamAttr::ReadOnly))

File diff suppressed because it is too large Load Diff

View File

@ -179,8 +179,8 @@
NOALIAS = 395,
BYVAL = 396,
NEST = 397,
CONST = 398,
PURE = 399,
READNONE = 398,
READONLY = 399,
DEFAULT = 400,
HIDDEN = 401,
PROTECTED = 402
@ -327,8 +327,8 @@
#define NOALIAS 395
#define BYVAL 396
#define NEST 397
#define CONST 398
#define PURE 399
#define READNONE 398
#define READONLY 399
#define DEFAULT 400
#define HIDDEN 401
#define PROTECTED 402
@ -338,7 +338,7 @@
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
#line 968 "/llvm/lib/AsmParser/llvmAsmParser.y"
#line 945 "/home/duncan/LLVM/llvm.top/llvm/lib/AsmParser/llvmAsmParser.y"
{
llvm::Module *ModuleVal;
llvm::Function *FunctionVal;
@ -385,7 +385,7 @@ typedef union YYSTYPE
llvm::ICmpInst::Predicate IPredicate;
llvm::FCmpInst::Predicate FPredicate;
}
/* Line 1529 of yacc.c. */
/* Line 1489 of yacc.c. */
#line 390 "llvmAsmParser.tab.h"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */

View File

@ -1328,61 +1328,36 @@ Types
CHECK_FOR_ERROR
}
| Types '(' ArgTypeListI ')' OptFuncAttrs {
// Allow but ignore attributes on function types; this permits auto-upgrade.
// FIXME: remove in LLVM 3.0.
std::vector<const Type*> Params;
ParamAttrsVector Attrs;
if ($5 != ParamAttr::None) {
ParamAttrsWithIndex X; X.index = 0; X.attrs = $5;
Attrs.push_back(X);
}
unsigned index = 1;
TypeWithAttrsList::iterator I = $3->begin(), E = $3->end();
for (; I != E; ++I, ++index) {
for (; I != E; ++I ) {
const Type *Ty = I->Ty->get();
Params.push_back(Ty);
if (Ty != Type::VoidTy)
if (I->Attrs != ParamAttr::None) {
ParamAttrsWithIndex X; X.index = index; X.attrs = I->Attrs;
Attrs.push_back(X);
}
}
bool isVarArg = Params.size() && Params.back() == Type::VoidTy;
if (isVarArg) Params.pop_back();
ParamAttrsList *ActualAttrs = 0;
if (!Attrs.empty())
ActualAttrs = ParamAttrsList::get(Attrs);
FunctionType *FT = FunctionType::get(*$1, Params, isVarArg, ActualAttrs);
FunctionType *FT = FunctionType::get(*$1, Params, isVarArg);
delete $3; // Delete the argument list
delete $1; // Delete the return type handle
$$ = new PATypeHolder(HandleUpRefs(FT));
CHECK_FOR_ERROR
}
| VOID '(' ArgTypeListI ')' OptFuncAttrs {
// Allow but ignore attributes on function types; this permits auto-upgrade.
// FIXME: remove in LLVM 3.0.
std::vector<const Type*> Params;
ParamAttrsVector Attrs;
if ($5 != ParamAttr::None) {
ParamAttrsWithIndex X; X.index = 0; X.attrs = $5;
Attrs.push_back(X);
}
TypeWithAttrsList::iterator I = $3->begin(), E = $3->end();
unsigned index = 1;
for ( ; I != E; ++I, ++index) {
for ( ; I != E; ++I ) {
const Type* Ty = I->Ty->get();
Params.push_back(Ty);
if (Ty != Type::VoidTy)
if (I->Attrs != ParamAttr::None) {
ParamAttrsWithIndex X; X.index = index; X.attrs = I->Attrs;
Attrs.push_back(X);
}
}
bool isVarArg = Params.size() && Params.back() == Type::VoidTy;
if (isVarArg) Params.pop_back();
ParamAttrsList *ActualAttrs = 0;
if (!Attrs.empty())
ActualAttrs = ParamAttrsList::get(Attrs);
FunctionType *FT = FunctionType::get($1, Params, isVarArg, ActualAttrs);
FunctionType *FT = FunctionType::get($1, Params, isVarArg);
delete $3; // Delete the argument list
$$ = new PATypeHolder(HandleUpRefs(FT));
CHECK_FOR_ERROR
@ -1434,9 +1409,11 @@ Types
;
ArgType
: Types OptParamAttrs {
: Types OptParamAttrs {
// Allow but ignore attributes on function types; this permits auto-upgrade.
// FIXME: remove in LLVM 3.0.
$$.Ty = $1;
$$.Attrs = $2;
$$.Attrs = ParamAttr::None;
}
;
@ -2241,7 +2218,9 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
std::vector<const Type*> ParamTypeList;
ParamAttrsVector Attrs;
if ($7 != ParamAttr::None) {
ParamAttrsWithIndex PAWI; PAWI.index = 0; PAWI.attrs = $7;
ParamAttrsWithIndex PAWI;
PAWI.index = 0;
PAWI.attrs = $7;
Attrs.push_back(PAWI);
}
if ($5) { // If there are arguments...
@ -2253,7 +2232,9 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
ParamTypeList.push_back(Ty);
if (Ty != Type::VoidTy)
if (I->Attrs != ParamAttr::None) {
ParamAttrsWithIndex PAWI; PAWI.index = index; PAWI.attrs = I->Attrs;
ParamAttrsWithIndex PAWI;
PAWI.index = index;
PAWI.attrs = I->Attrs;
Attrs.push_back(PAWI);
}
}
@ -2266,7 +2247,7 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
if (!Attrs.empty())
PAL = ParamAttrsList::get(Attrs);
FunctionType *FT = FunctionType::get(*$2, ParamTypeList, isVarArg, PAL);
FunctionType *FT = FunctionType::get(*$2, ParamTypeList, isVarArg);
const PointerType *PFT = PointerType::get(FT);
delete $2;
@ -2283,19 +2264,24 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
// Move the function to the end of the list, from whereever it was
// previously inserted.
Fn = cast<Function>(FWRef);
assert(!Fn->getParamAttrs() && "Forward reference has parameter attributes!");
CurModule.CurrentModule->getFunctionList().remove(Fn);
CurModule.CurrentModule->getFunctionList().push_back(Fn);
} else if (!FunctionName.empty() && // Merge with an earlier prototype?
(Fn = CurModule.CurrentModule->getFunction(FunctionName))) {
if (Fn->getFunctionType() != FT) {
if (Fn->getFunctionType() != FT ) {
// The existing function doesn't have the same type. This is an overload
// error.
GEN_ERROR("Overload of function '" + FunctionName + "' not permitted.");
} else if (Fn->getParamAttrs() != PAL) {
// The existing function doesn't have the same parameter attributes.
// This is an overload error.
GEN_ERROR("Overload of function '" + FunctionName + "' not permitted.");
} else if (!CurFun.isDeclare && !Fn->isDeclaration()) {
// Neither the existing or the current function is a declaration and they
// have the same name and same type. Clearly this is a redefinition.
GEN_ERROR("Redefinition of function '" + FunctionName + "'");
} if (Fn->isDeclaration()) {
} else if (Fn->isDeclaration()) {
// Make sure to strip off any argument names so we can't get conflicts.
for (Function::arg_iterator AI = Fn->arg_begin(), AE = Fn->arg_end();
AI != AE; ++AI)
@ -2304,7 +2290,6 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
} else { // Not already defined?
Fn = new Function(FT, GlobalValue::ExternalWeakLinkage, FunctionName,
CurModule.CurrentModule);
InsertValue(Fn, CurModule.Values);
}
@ -2318,6 +2303,7 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
Fn->setVisibility(CurFun.Visibility);
}
Fn->setCallingConv($1);
Fn->setParamAttrs(PAL);
Fn->setAlignment($9);
if ($8) {
Fn->setSection(*$8);
@ -2597,28 +2583,14 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result...
!(Ty = dyn_cast<FunctionType>(PFTy->getElementType()))) {
// Pull out the types of all of the arguments...
std::vector<const Type*> ParamTypes;
ParamAttrsVector Attrs;
if ($8 != ParamAttr::None) {
ParamAttrsWithIndex PAWI; PAWI.index = 0; PAWI.attrs = $8;
Attrs.push_back(PAWI);
}
ParamList::iterator I = $6->begin(), E = $6->end();
unsigned index = 1;
for (; I != E; ++I, ++index) {
for (; I != E; ++I) {
const Type *Ty = I->Val->getType();
if (Ty == Type::VoidTy)
GEN_ERROR("Short call syntax cannot be used with varargs");
ParamTypes.push_back(Ty);
if (I->Attrs != ParamAttr::None) {
ParamAttrsWithIndex PAWI; PAWI.index = index; PAWI.attrs = I->Attrs;
Attrs.push_back(PAWI);
}
}
ParamAttrsList *PAL = 0;
if (!Attrs.empty())
PAL = ParamAttrsList::get(Attrs);
Ty = FunctionType::get($3->get(), ParamTypes, false, PAL);
Ty = FunctionType::get($3->get(), ParamTypes, false);
PFTy = PointerType::get(Ty);
}
@ -2631,6 +2603,12 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result...
BasicBlock *Except = getBBVal($14);
CHECK_FOR_ERROR
ParamAttrsVector Attrs;
if ($8 != ParamAttr::None) {
ParamAttrsWithIndex PAWI; PAWI.index = 0; PAWI.attrs = $8;
Attrs.push_back(PAWI);
}
// Check the arguments
ValueList Args;
if ($6->empty()) { // Has no arguments?
@ -2644,12 +2622,19 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result...
FunctionType::param_iterator I = Ty->param_begin();
FunctionType::param_iterator E = Ty->param_end();
ParamList::iterator ArgI = $6->begin(), ArgE = $6->end();
unsigned index = 1;
for (; ArgI != ArgE && I != E; ++ArgI, ++I) {
for (; ArgI != ArgE && I != E; ++ArgI, ++I, ++index) {
if (ArgI->Val->getType() != *I)
GEN_ERROR("Parameter " + ArgI->Val->getName()+ " is not of type '" +
(*I)->getDescription() + "'");
Args.push_back(ArgI->Val);
if (ArgI->Attrs != ParamAttr::None) {
ParamAttrsWithIndex PAWI;
PAWI.index = index;
PAWI.attrs = ArgI->Attrs;
Attrs.push_back(PAWI);
}
}
if (Ty->isVarArg()) {
@ -2660,9 +2645,14 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result...
GEN_ERROR("Invalid number of parameters detected");
}
ParamAttrsList *PAL = 0;
if (!Attrs.empty())
PAL = ParamAttrsList::get(Attrs);
// Create the InvokeInst
InvokeInst *II = new InvokeInst(V, Normal, Except, Args.begin(), Args.end());
II->setCallingConv($2);
II->setParamAttrs(PAL);
$$ = II;
delete $6;
CHECK_FOR_ERROR
@ -2733,33 +2723,39 @@ PHIList : Types '[' ValueRef ',' ValueRef ']' { // Used for PHI nodes
};
ParamList : Types ValueRef OptParamAttrs {
ParamList : Types OptParamAttrs ValueRef OptParamAttrs {
// FIXME: Remove trailing OptParamAttrs in LLVM 3.0, it was a mistake in 2.0
if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription());
// Used for call and invoke instructions
$$ = new ParamList();
ParamListEntry E; E.Attrs = $3; E.Val = getVal($1->get(), $2);
ParamListEntry E; E.Attrs = $2 | $4; E.Val = getVal($1->get(), $3);
$$->push_back(E);
delete $1;
CHECK_FOR_ERROR
}
| LABEL ValueRef OptParamAttrs {
| LABEL OptParamAttrs ValueRef OptParamAttrs {
// FIXME: Remove trailing OptParamAttrs in LLVM 3.0, it was a mistake in 2.0
// Labels are only valid in ASMs
$$ = new ParamList();
ParamListEntry E; E.Attrs = $3; E.Val = getBBVal($2);
ParamListEntry E; E.Attrs = $2 | $4; E.Val = getBBVal($3);
$$->push_back(E);
CHECK_FOR_ERROR
}
| ParamList ',' Types ValueRef OptParamAttrs {
| ParamList ',' Types OptParamAttrs ValueRef OptParamAttrs {
// FIXME: Remove trailing OptParamAttrs in LLVM 3.0, it was a mistake in 2.0
if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$3)->getDescription());
$$ = $1;
ParamListEntry E; E.Attrs = $5; E.Val = getVal($3->get(), $4);
ParamListEntry E; E.Attrs = $4 | $6; E.Val = getVal($3->get(), $5);
$$->push_back(E);
delete $3;
CHECK_FOR_ERROR
}
| ParamList ',' LABEL ValueRef OptParamAttrs {
| ParamList ',' LABEL OptParamAttrs ValueRef OptParamAttrs {
// FIXME: Remove trailing OptParamAttrs in LLVM 3.0, it was a mistake in 2.0
$$ = $1;
ParamListEntry E; E.Attrs = $5; E.Val = getBBVal($4);
ParamListEntry E; E.Attrs = $4 | $6; E.Val = getBBVal($5);
$$->push_back(E);
CHECK_FOR_ERROR
}
@ -2914,29 +2910,14 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
!(Ty = dyn_cast<FunctionType>(PFTy->getElementType()))) {
// Pull out the types of all of the arguments...
std::vector<const Type*> ParamTypes;
ParamAttrsVector Attrs;
if ($8 != ParamAttr::None) {
ParamAttrsWithIndex PAWI; PAWI.index = 0; PAWI.attrs = $8;
Attrs.push_back(PAWI);
}
unsigned index = 1;
ParamList::iterator I = $6->begin(), E = $6->end();
for (; I != E; ++I, ++index) {
for (; I != E; ++I) {
const Type *Ty = I->Val->getType();
if (Ty == Type::VoidTy)
GEN_ERROR("Short call syntax cannot be used with varargs");
ParamTypes.push_back(Ty);
if (I->Attrs != ParamAttr::None) {
ParamAttrsWithIndex PAWI; PAWI.index = index; PAWI.attrs = I->Attrs;
Attrs.push_back(PAWI);
}
}
ParamAttrsList *PAL = 0;
if (!Attrs.empty())
PAL = ParamAttrsList::get(Attrs);
Ty = FunctionType::get($3->get(), ParamTypes, false, PAL);
Ty = FunctionType::get($3->get(), ParamTypes, false);
PFTy = PointerType::get(Ty);
}
@ -2952,6 +2933,14 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
theF->getName() + "'");
}
// Set up the ParamAttrs for the function
ParamAttrsVector Attrs;
if ($8 != ParamAttr::None) {
ParamAttrsWithIndex PAWI;
PAWI.index = 0;
PAWI.attrs = $8;
Attrs.push_back(PAWI);
}
// Check the arguments
ValueList Args;
if ($6->empty()) { // Has no arguments?
@ -2961,17 +2950,23 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
"expects arguments");
} else { // Has arguments?
// Loop through FunctionType's arguments and ensure they are specified
// correctly!
//
// correctly. Also, gather any parameter attributes.
FunctionType::param_iterator I = Ty->param_begin();
FunctionType::param_iterator E = Ty->param_end();
ParamList::iterator ArgI = $6->begin(), ArgE = $6->end();
unsigned index = 1;
for (; ArgI != ArgE && I != E; ++ArgI, ++I) {
for (; ArgI != ArgE && I != E; ++ArgI, ++I, ++index) {
if (ArgI->Val->getType() != *I)
GEN_ERROR("Parameter " + ArgI->Val->getName()+ " is not of type '" +
(*I)->getDescription() + "'");
Args.push_back(ArgI->Val);
if (ArgI->Attrs != ParamAttr::None) {
ParamAttrsWithIndex PAWI;
PAWI.index = index;
PAWI.attrs = ArgI->Attrs;
Attrs.push_back(PAWI);
}
}
if (Ty->isVarArg()) {
if (I == E)
@ -2980,10 +2975,17 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
} else if (I != E || ArgI != ArgE)
GEN_ERROR("Invalid number of parameters detected");
}
// Finish off the ParamAttrs and check them
ParamAttrsList *PAL = 0;
if (!Attrs.empty())
PAL = ParamAttrsList::get(Attrs);
// Create the call node
CallInst *CI = new CallInst(V, Args.begin(), Args.end());
CI->setTailCall($1);
CI->setCallingConv($2);
CI->setParamAttrs(PAL);
$$ = CI;
delete $6;
delete $3;

View File

@ -29,9 +29,6 @@
#include <list>
#include <map>
#include <utility>
#ifndef NDEBUG
#define YYDEBUG 1
#endif
// The following is a gross hack. In order to rid the libAsmParser library of
// exceptions, we have to have a way of getting the yyparse function to go into
@ -51,15 +48,6 @@ static bool TriggerError = false;
int yyerror(const char *ErrorMsg); // Forward declarations to prevent "implicit
int yylex(); // declaration" of xxx warnings.
int yyparse();
namespace llvm {
std::string CurFilename;
#if YYDEBUG
static cl::opt<bool>
Debug("debug-yacc", cl::desc("Print yacc debug state changes"),
cl::Hidden, cl::init(false));
#endif
}
using namespace llvm;
static Module *ParserResult;
@ -513,7 +501,7 @@ static Value *getVal(const Type *Ty, const ValID &ID) {
// Remember where this forward reference came from. FIXME, shouldn't we try
// to recycle these things??
CurModule.PlaceHolderInfo.insert(std::make_pair(V, std::make_pair(ID,
llvmAsmlineno)));
LLLgetLineNo())));
if (inFunctionScope())
InsertValue(V, CurFun.LateResolveValues);
@ -945,22 +933,11 @@ static PATypeHolder HandleUpRefs(const Type *ty) {
//
static Module* RunParser(Module * M);
Module *llvm::RunVMAsmParser(const std::string &Filename, FILE *F) {
set_scan_file(F);
CurFilename = Filename;
return RunParser(new Module(CurFilename));
}
Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
set_scan_string(AsmString);
CurFilename = "from_memory";
if (M == NULL) {
return RunParser(new Module (CurFilename));
} else {
return RunParser(M);
}
Module *llvm::RunVMAsmParser(llvm::MemoryBuffer *MB) {
InitLLLexer(MB);
Module *M = RunParser(new Module(LLLgetFilename()));
FreeLexer();
return M;
}
%}
@ -1113,7 +1090,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
// Function Attributes
%token SIGNEXT ZEROEXT NORETURN INREG SRET NOUNWIND NOALIAS BYVAL NEST
%token CONST PURE
%token READNONE READONLY
// Visibility Styles
%token DEFAULT HIDDEN PROTECTED
@ -1257,8 +1234,8 @@ FuncAttr : NORETURN { $$ = ParamAttr::NoReturn; }
| NOUNWIND { $$ = ParamAttr::NoUnwind; }
| ZEROEXT { $$ = ParamAttr::ZExt; }
| SIGNEXT { $$ = ParamAttr::SExt; }
| PURE { $$ = ParamAttr::Pure; }
| CONST { $$ = ParamAttr::Const; }
| READNONE { $$ = ParamAttr::ReadNone; }
| READONLY { $$ = ParamAttr::ReadOnly; }
;
OptFuncAttrs : /* empty */ { $$ = ParamAttr::None; }
@ -1351,61 +1328,36 @@ Types
CHECK_FOR_ERROR
}
| Types '(' ArgTypeListI ')' OptFuncAttrs {
// Allow but ignore attributes on function types; this permits auto-upgrade.
// FIXME: remove in LLVM 3.0.
std::vector<const Type*> Params;
ParamAttrsVector Attrs;
if ($5 != ParamAttr::None) {
ParamAttrsWithIndex X; X.index = 0; X.attrs = $5;
Attrs.push_back(X);
}
unsigned index = 1;
TypeWithAttrsList::iterator I = $3->begin(), E = $3->end();
for (; I != E; ++I, ++index) {
for (; I != E; ++I ) {
const Type *Ty = I->Ty->get();
Params.push_back(Ty);
if (Ty != Type::VoidTy)
if (I->Attrs != ParamAttr::None) {
ParamAttrsWithIndex X; X.index = index; X.attrs = I->Attrs;
Attrs.push_back(X);
}
}
bool isVarArg = Params.size() && Params.back() == Type::VoidTy;
if (isVarArg) Params.pop_back();
ParamAttrsList *ActualAttrs = 0;
if (!Attrs.empty())
ActualAttrs = ParamAttrsList::get(Attrs);
FunctionType *FT = FunctionType::get(*$1, Params, isVarArg, ActualAttrs);
FunctionType *FT = FunctionType::get(*$1, Params, isVarArg);
delete $3; // Delete the argument list
delete $1; // Delete the return type handle
$$ = new PATypeHolder(HandleUpRefs(FT));
CHECK_FOR_ERROR
}
| VOID '(' ArgTypeListI ')' OptFuncAttrs {
// Allow but ignore attributes on function types; this permits auto-upgrade.
// FIXME: remove in LLVM 3.0.
std::vector<const Type*> Params;
ParamAttrsVector Attrs;
if ($5 != ParamAttr::None) {
ParamAttrsWithIndex X; X.index = 0; X.attrs = $5;
Attrs.push_back(X);
}
TypeWithAttrsList::iterator I = $3->begin(), E = $3->end();
unsigned index = 1;
for ( ; I != E; ++I, ++index) {
for ( ; I != E; ++I ) {
const Type* Ty = I->Ty->get();
Params.push_back(Ty);
if (Ty != Type::VoidTy)
if (I->Attrs != ParamAttr::None) {
ParamAttrsWithIndex X; X.index = index; X.attrs = I->Attrs;
Attrs.push_back(X);
}
}
bool isVarArg = Params.size() && Params.back() == Type::VoidTy;
if (isVarArg) Params.pop_back();
ParamAttrsList *ActualAttrs = 0;
if (!Attrs.empty())
ActualAttrs = ParamAttrsList::get(Attrs);
FunctionType *FT = FunctionType::get($1, Params, isVarArg, ActualAttrs);
FunctionType *FT = FunctionType::get($1, Params, isVarArg);
delete $3; // Delete the argument list
$$ = new PATypeHolder(HandleUpRefs(FT));
CHECK_FOR_ERROR
@ -1457,9 +1409,11 @@ Types
;
ArgType
: Types OptParamAttrs {
: Types OptParamAttrs {
// Allow but ignore attributes on function types; this permits auto-upgrade.
// FIXME: remove in LLVM 3.0.
$$.Ty = $1;
$$.Attrs = $2;
$$.Attrs = ParamAttr::None;
}
;
@ -2264,7 +2218,9 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
std::vector<const Type*> ParamTypeList;
ParamAttrsVector Attrs;
if ($7 != ParamAttr::None) {
ParamAttrsWithIndex PAWI; PAWI.index = 0; PAWI.attrs = $7;
ParamAttrsWithIndex PAWI;
PAWI.index = 0;
PAWI.attrs = $7;
Attrs.push_back(PAWI);
}
if ($5) { // If there are arguments...
@ -2276,7 +2232,9 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
ParamTypeList.push_back(Ty);
if (Ty != Type::VoidTy)
if (I->Attrs != ParamAttr::None) {
ParamAttrsWithIndex PAWI; PAWI.index = index; PAWI.attrs = I->Attrs;
ParamAttrsWithIndex PAWI;
PAWI.index = index;
PAWI.attrs = I->Attrs;
Attrs.push_back(PAWI);
}
}
@ -2289,7 +2247,7 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
if (!Attrs.empty())
PAL = ParamAttrsList::get(Attrs);
FunctionType *FT = FunctionType::get(*$2, ParamTypeList, isVarArg, PAL);
FunctionType *FT = FunctionType::get(*$2, ParamTypeList, isVarArg);
const PointerType *PFT = PointerType::get(FT);
delete $2;
@ -2306,19 +2264,24 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
// Move the function to the end of the list, from whereever it was
// previously inserted.
Fn = cast<Function>(FWRef);
assert(!Fn->getParamAttrs() && "Forward reference has parameter attributes!");
CurModule.CurrentModule->getFunctionList().remove(Fn);
CurModule.CurrentModule->getFunctionList().push_back(Fn);
} else if (!FunctionName.empty() && // Merge with an earlier prototype?
(Fn = CurModule.CurrentModule->getFunction(FunctionName))) {
if (Fn->getFunctionType() != FT) {
if (Fn->getFunctionType() != FT ) {
// The existing function doesn't have the same type. This is an overload
// error.
GEN_ERROR("Overload of function '" + FunctionName + "' not permitted.");
} else if (Fn->getParamAttrs() != PAL) {
// The existing function doesn't have the same parameter attributes.
// This is an overload error.
GEN_ERROR("Overload of function '" + FunctionName + "' not permitted.");
} else if (!CurFun.isDeclare && !Fn->isDeclaration()) {
// Neither the existing or the current function is a declaration and they
// have the same name and same type. Clearly this is a redefinition.
GEN_ERROR("Redefinition of function '" + FunctionName + "'");
} if (Fn->isDeclaration()) {
} else if (Fn->isDeclaration()) {
// Make sure to strip off any argument names so we can't get conflicts.
for (Function::arg_iterator AI = Fn->arg_begin(), AE = Fn->arg_end();
AI != AE; ++AI)
@ -2327,7 +2290,6 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
} else { // Not already defined?
Fn = new Function(FT, GlobalValue::ExternalWeakLinkage, FunctionName,
CurModule.CurrentModule);
InsertValue(Fn, CurModule.Values);
}
@ -2341,6 +2303,7 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
Fn->setVisibility(CurFun.Visibility);
}
Fn->setCallingConv($1);
Fn->setParamAttrs(PAL);
Fn->setAlignment($9);
if ($8) {
Fn->setSection(*$8);
@ -2620,28 +2583,14 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result...
!(Ty = dyn_cast<FunctionType>(PFTy->getElementType()))) {
// Pull out the types of all of the arguments...
std::vector<const Type*> ParamTypes;
ParamAttrsVector Attrs;
if ($8 != ParamAttr::None) {
ParamAttrsWithIndex PAWI; PAWI.index = 0; PAWI.attrs = $8;
Attrs.push_back(PAWI);
}
ParamList::iterator I = $6->begin(), E = $6->end();
unsigned index = 1;
for (; I != E; ++I, ++index) {
for (; I != E; ++I) {
const Type *Ty = I->Val->getType();
if (Ty == Type::VoidTy)
GEN_ERROR("Short call syntax cannot be used with varargs");
ParamTypes.push_back(Ty);
if (I->Attrs != ParamAttr::None) {
ParamAttrsWithIndex PAWI; PAWI.index = index; PAWI.attrs = I->Attrs;
Attrs.push_back(PAWI);
}
}
ParamAttrsList *PAL = 0;
if (!Attrs.empty())
PAL = ParamAttrsList::get(Attrs);
Ty = FunctionType::get($3->get(), ParamTypes, false, PAL);
Ty = FunctionType::get($3->get(), ParamTypes, false);
PFTy = PointerType::get(Ty);
}
@ -2654,6 +2603,12 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result...
BasicBlock *Except = getBBVal($14);
CHECK_FOR_ERROR
ParamAttrsVector Attrs;
if ($8 != ParamAttr::None) {
ParamAttrsWithIndex PAWI; PAWI.index = 0; PAWI.attrs = $8;
Attrs.push_back(PAWI);
}
// Check the arguments
ValueList Args;
if ($6->empty()) { // Has no arguments?
@ -2667,12 +2622,19 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result...
FunctionType::param_iterator I = Ty->param_begin();
FunctionType::param_iterator E = Ty->param_end();
ParamList::iterator ArgI = $6->begin(), ArgE = $6->end();
unsigned index = 1;
for (; ArgI != ArgE && I != E; ++ArgI, ++I) {
for (; ArgI != ArgE && I != E; ++ArgI, ++I, ++index) {
if (ArgI->Val->getType() != *I)
GEN_ERROR("Parameter " + ArgI->Val->getName()+ " is not of type '" +
(*I)->getDescription() + "'");
Args.push_back(ArgI->Val);
if (ArgI->Attrs != ParamAttr::None) {
ParamAttrsWithIndex PAWI;
PAWI.index = index;
PAWI.attrs = ArgI->Attrs;
Attrs.push_back(PAWI);
}
}
if (Ty->isVarArg()) {
@ -2683,9 +2645,14 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result...
GEN_ERROR("Invalid number of parameters detected");
}
ParamAttrsList *PAL = 0;
if (!Attrs.empty())
PAL = ParamAttrsList::get(Attrs);
// Create the InvokeInst
InvokeInst *II = new InvokeInst(V, Normal, Except, Args.begin(), Args.end());
II->setCallingConv($2);
II->setParamAttrs(PAL);
$$ = II;
delete $6;
CHECK_FOR_ERROR
@ -2756,33 +2723,39 @@ PHIList : Types '[' ValueRef ',' ValueRef ']' { // Used for PHI nodes
};
ParamList : Types ValueRef OptParamAttrs {
ParamList : Types OptParamAttrs ValueRef OptParamAttrs {
// FIXME: Remove trailing OptParamAttrs in LLVM 3.0, it was a mistake in 2.0
if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription());
// Used for call and invoke instructions
$$ = new ParamList();
ParamListEntry E; E.Attrs = $3; E.Val = getVal($1->get(), $2);
ParamListEntry E; E.Attrs = $2 | $4; E.Val = getVal($1->get(), $3);
$$->push_back(E);
delete $1;
CHECK_FOR_ERROR
}
| LABEL ValueRef OptParamAttrs {
| LABEL OptParamAttrs ValueRef OptParamAttrs {
// FIXME: Remove trailing OptParamAttrs in LLVM 3.0, it was a mistake in 2.0
// Labels are only valid in ASMs
$$ = new ParamList();
ParamListEntry E; E.Attrs = $3; E.Val = getBBVal($2);
ParamListEntry E; E.Attrs = $2 | $4; E.Val = getBBVal($3);
$$->push_back(E);
CHECK_FOR_ERROR
}
| ParamList ',' Types ValueRef OptParamAttrs {
| ParamList ',' Types OptParamAttrs ValueRef OptParamAttrs {
// FIXME: Remove trailing OptParamAttrs in LLVM 3.0, it was a mistake in 2.0
if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$3)->getDescription());
$$ = $1;
ParamListEntry E; E.Attrs = $5; E.Val = getVal($3->get(), $4);
ParamListEntry E; E.Attrs = $4 | $6; E.Val = getVal($3->get(), $5);
$$->push_back(E);
delete $3;
CHECK_FOR_ERROR
}
| ParamList ',' LABEL ValueRef OptParamAttrs {
| ParamList ',' LABEL OptParamAttrs ValueRef OptParamAttrs {
// FIXME: Remove trailing OptParamAttrs in LLVM 3.0, it was a mistake in 2.0
$$ = $1;
ParamListEntry E; E.Attrs = $5; E.Val = getBBVal($4);
ParamListEntry E; E.Attrs = $4 | $6; E.Val = getBBVal($5);
$$->push_back(E);
CHECK_FOR_ERROR
}
@ -2937,29 +2910,14 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
!(Ty = dyn_cast<FunctionType>(PFTy->getElementType()))) {
// Pull out the types of all of the arguments...
std::vector<const Type*> ParamTypes;
ParamAttrsVector Attrs;
if ($8 != ParamAttr::None) {
ParamAttrsWithIndex PAWI; PAWI.index = 0; PAWI.attrs = $8;
Attrs.push_back(PAWI);
}
unsigned index = 1;
ParamList::iterator I = $6->begin(), E = $6->end();
for (; I != E; ++I, ++index) {
for (; I != E; ++I) {
const Type *Ty = I->Val->getType();
if (Ty == Type::VoidTy)
GEN_ERROR("Short call syntax cannot be used with varargs");
ParamTypes.push_back(Ty);
if (I->Attrs != ParamAttr::None) {
ParamAttrsWithIndex PAWI; PAWI.index = index; PAWI.attrs = I->Attrs;
Attrs.push_back(PAWI);
}
}
ParamAttrsList *PAL = 0;
if (!Attrs.empty())
PAL = ParamAttrsList::get(Attrs);
Ty = FunctionType::get($3->get(), ParamTypes, false, PAL);
Ty = FunctionType::get($3->get(), ParamTypes, false);
PFTy = PointerType::get(Ty);
}
@ -2975,6 +2933,14 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
theF->getName() + "'");
}
// Set up the ParamAttrs for the function
ParamAttrsVector Attrs;
if ($8 != ParamAttr::None) {
ParamAttrsWithIndex PAWI;
PAWI.index = 0;
PAWI.attrs = $8;
Attrs.push_back(PAWI);
}
// Check the arguments
ValueList Args;
if ($6->empty()) { // Has no arguments?
@ -2984,17 +2950,23 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
"expects arguments");
} else { // Has arguments?
// Loop through FunctionType's arguments and ensure they are specified
// correctly!
//
// correctly. Also, gather any parameter attributes.
FunctionType::param_iterator I = Ty->param_begin();
FunctionType::param_iterator E = Ty->param_end();
ParamList::iterator ArgI = $6->begin(), ArgE = $6->end();
unsigned index = 1;
for (; ArgI != ArgE && I != E; ++ArgI, ++I) {
for (; ArgI != ArgE && I != E; ++ArgI, ++I, ++index) {
if (ArgI->Val->getType() != *I)
GEN_ERROR("Parameter " + ArgI->Val->getName()+ " is not of type '" +
(*I)->getDescription() + "'");
Args.push_back(ArgI->Val);
if (ArgI->Attrs != ParamAttr::None) {
ParamAttrsWithIndex PAWI;
PAWI.index = index;
PAWI.attrs = ArgI->Attrs;
Attrs.push_back(PAWI);
}
}
if (Ty->isVarArg()) {
if (I == E)
@ -3003,10 +2975,17 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
} else if (I != E || ArgI != ArgE)
GEN_ERROR("Invalid number of parameters detected");
}
// Finish off the ParamAttrs and check them
ParamAttrsList *PAL = 0;
if (!Attrs.empty())
PAL = ParamAttrsList::get(Attrs);
// Create the call node
CallInst *CI = new CallInst(V, Args.begin(), Args.end());
CI->setTailCall($1);
CI->setCallingConv($2);
CI->setParamAttrs(PAL);
$$ = CI;
delete $6;
delete $3;
@ -3118,13 +3097,7 @@ MemoryInst : MALLOC Types OptCAlign {
// common code from the two 'RunVMAsmParser' functions
static Module* RunParser(Module * M) {
llvmAsmlineno = 1; // Reset the current line number...
CurModule.CurrentModule = M;
#if YYDEBUG
yydebug = Debug;
#endif
// Check to make sure the parser succeeded
if (yyparse()) {
if (ParserResult)
@ -3176,21 +3149,21 @@ static Module* RunParser(Module * M) {
}
void llvm::GenerateError(const std::string &message, int LineNo) {
if (LineNo == -1) LineNo = llvmAsmlineno;
if (LineNo == -1) LineNo = LLLgetLineNo();
// TODO: column number in exception
if (TheParseError)
TheParseError->setError(CurFilename, message, LineNo);
TheParseError->setError(LLLgetFilename(), message, LineNo);
TriggerError = 1;
}
int yyerror(const char *ErrorMsg) {
std::string where
= std::string((CurFilename == "-") ? std::string("<stdin>") : CurFilename)
+ ":" + utostr((unsigned) llvmAsmlineno) + ": ";
std::string where = LLLgetFilename() + ":" + utostr(LLLgetLineNo()) + ": ";
std::string errMsg = where + "error: " + std::string(ErrorMsg);
if (yychar != YYEMPTY && yychar != 0)
errMsg += " while reading token: '" + std::string(llvmAsmtext, llvmAsmleng)+
"'";
if (yychar != YYEMPTY && yychar != 0) {
errMsg += " while reading token: '";
errMsg += std::string(LLLgetTokenStart(),
LLLgetTokenStart()+LLLgetTokenLength()) + "'";
}
GenerateError(errMsg);
return 0;
}

View File

@ -329,15 +329,15 @@ bool BitcodeReader::ParseTypeTable() {
ResultTy = PointerType::get(getTypeByID(Record[0], true));
break;
case bitc::TYPE_CODE_FUNCTION: {
// FUNCTION: [vararg, attrid, retty, paramty x N]
if (Record.size() < 3)
// FUNCTION: [vararg, retty, paramty x N]
if (Record.size() < 2)
return Error("Invalid FUNCTION type record");
std::vector<const Type*> ArgTys;
for (unsigned i = 3, e = Record.size(); i != e; ++i)
for (unsigned i = 2, e = Record.size(); i != e; ++i)
ArgTys.push_back(getTypeByID(Record[i], true));
ResultTy = FunctionType::get(getTypeByID(Record[2], true), ArgTys,
Record[0], getParamAttrs(Record[1]));
ResultTy = FunctionType::get(getTypeByID(Record[1], true), ArgTys,
Record[0]);
break;
}
case bitc::TYPE_CODE_STRUCT: { // STRUCT: [ispacked, eltty x N]
@ -1033,9 +1033,8 @@ bool BitcodeReader::ParseModule(const std::string &ModuleID) {
Func->setCallingConv(Record[1]);
bool isProto = Record[2];
Func->setLinkage(GetDecodedLinkage(Record[3]));
assert(Func->getFunctionType()->getParamAttrs() ==
getParamAttrs(Record[4]));
const ParamAttrsList *PAL = getParamAttrs(Record[4]);
Func->setParamAttrs(PAL);
Func->setAlignment((1 << Record[5]) >> 1);
if (Record[6]) {
@ -1360,8 +1359,10 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
break;
}
case bitc::FUNC_CODE_INST_INVOKE: { // INVOKE: [cc,fnty, op0,op1,op2, ...]
case bitc::FUNC_CODE_INST_INVOKE: {
// INVOKE: [attrs, cc, normBB, unwindBB, fnty, op0,op1,op2, ...]
if (Record.size() < 4) return Error("Invalid INVOKE record");
const ParamAttrsList *PAL = getParamAttrs(Record[0]);
unsigned CCInfo = Record[1];
BasicBlock *NormalBB = getBasicBlock(Record[2]);
BasicBlock *UnwindBB = getBasicBlock(Record[3]);
@ -1380,8 +1381,6 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
Record.size() < OpNum+FTy->getNumParams())
return Error("Invalid INVOKE record");
assert(FTy->getParamAttrs() == getParamAttrs(Record[0]));
SmallVector<Value*, 16> Ops;
for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) {
Ops.push_back(getFnValueByID(Record[OpNum], FTy->getParamType(i)));
@ -1403,6 +1402,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
I = new InvokeInst(Callee, NormalBB, UnwindBB, Ops.begin(), Ops.end());
cast<InvokeInst>(I)->setCallingConv(CCInfo);
cast<InvokeInst>(I)->setParamAttrs(PAL);
break;
}
case bitc::FUNC_CODE_INST_UNWIND: // UNWIND
@ -1482,10 +1482,12 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
I = new StoreInst(Val, Ptr, Record[OpNum+1], (1 << Record[OpNum]) >> 1);
break;
}
case bitc::FUNC_CODE_INST_CALL: { // CALL: [cc, fnty, fnid, arg0, arg1...]
if (Record.size() < 2)
case bitc::FUNC_CODE_INST_CALL: {
// CALL: [paramattrs, cc, fnty, fnid, arg0, arg1...]
if (Record.size() < 3)
return Error("Invalid CALL record");
const ParamAttrsList *PAL = getParamAttrs(Record[0]);
unsigned CCInfo = Record[1];
unsigned OpNum = 2;
@ -1499,8 +1501,6 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
if (!FTy || Record.size() < FTy->getNumParams()+OpNum)
return Error("Invalid CALL record");
assert(FTy->getParamAttrs() == getParamAttrs(Record[0]));
SmallVector<Value*, 16> Args;
// Read the fixed params.
for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) {
@ -1527,6 +1527,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
I = new CallInst(Callee, Args.begin(), Args.end());
cast<CallInst>(I)->setCallingConv(CCInfo>>1);
cast<CallInst>(I)->setTailCall(CCInfo & 1);
cast<CallInst>(I)->setParamAttrs(PAL);
break;
}
case bitc::FUNC_CODE_INST_VAARG: { // VAARG: [valistty, valist, instty]

View File

@ -147,8 +147,6 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) {
Abbv = new BitCodeAbbrev();
Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_FUNCTION));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isvararg
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
Log2_32_Ceil(VE.getParamAttrs().size()+1)));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
Log2_32_Ceil(VE.getTypes().size()+1)));
@ -206,10 +204,9 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) {
case Type::FunctionTyID: {
const FunctionType *FT = cast<FunctionType>(T);
// FUNCTION: [isvararg, attrid, retty, paramty x N]
// FUNCTION: [isvararg, retty, paramty x N]
Code = bitc::TYPE_CODE_FUNCTION;
TypeVals.push_back(FT->isVarArg());
TypeVals.push_back(VE.getParamAttrID(FT->getParamAttrs()));
TypeVals.push_back(VE.getTypeID(FT->getReturnType()));
for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i)
TypeVals.push_back(VE.getTypeID(FT->getParamType(i)));
@ -383,18 +380,13 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE,
// Emit the function proto information.
for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) {
// FUNCTION: [type, callingconv, isproto, linkage, alignment, section,
// visibility]
// FUNCTION: [type, callingconv, isproto, paramattr,
// linkage, alignment, section, visibility]
Vals.push_back(VE.getTypeID(F->getType()));
Vals.push_back(F->getCallingConv());
Vals.push_back(F->isDeclaration());
Vals.push_back(getEncodedLinkage(F));
// Note: we emit the param attr ID number for the function type of this
// function. In the future, we intend for attrs to be properties of
// functions, instead of on the type. This is to support this future work.
Vals.push_back(VE.getParamAttrID(F->getFunctionType()->getParamAttrs()));
Vals.push_back(VE.getParamAttrID(F->getParamAttrs()));
Vals.push_back(Log2_32(F->getAlignment())+1);
Vals.push_back(F->hasSection() ? SectionMap[F->getSection()] : 0);
Vals.push_back(getEncodedVisibility(F));
@ -760,12 +752,9 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
Code = bitc::FUNC_CODE_INST_INVOKE;
// Note: we emit the param attr ID number for the function type of this
// function. In the future, we intend for attrs to be properties of
// functions, instead of on the type. This is to support this future work.
Vals.push_back(VE.getParamAttrID(FTy->getParamAttrs()));
Vals.push_back(cast<InvokeInst>(I).getCallingConv());
const InvokeInst *II = cast<InvokeInst>(&I);
Vals.push_back(VE.getParamAttrID(II->getParamAttrs()));
Vals.push_back(II->getCallingConv());
Vals.push_back(VE.getValueID(I.getOperand(1))); // normal dest
Vals.push_back(VE.getValueID(I.getOperand(2))); // unwind dest
PushValueAndType(I.getOperand(0), InstID, Vals, VE); // callee
@ -837,14 +826,10 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
Code = bitc::FUNC_CODE_INST_CALL;
// Note: we emit the param attr ID number for the function type of this
// function. In the future, we intend for attrs to be properties of
// functions, instead of on the type. This is to support this future work.
Vals.push_back(VE.getParamAttrID(FTy->getParamAttrs()));
Vals.push_back((cast<CallInst>(I).getCallingConv() << 1) |
unsigned(cast<CallInst>(I).isTailCall()));
PushValueAndType(I.getOperand(0), InstID, Vals, VE); // Callee
const CallInst *CI = cast<CallInst>(&I);
Vals.push_back(VE.getParamAttrID(CI->getParamAttrs()));
Vals.push_back((CI->getCallingConv() << 1) | unsigned(CI->isTailCall()));
PushValueAndType(CI->getOperand(0), InstID, Vals, VE); // Callee
// Emit value #'s for the fixed parameters.
for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i)

View File

@ -17,6 +17,7 @@
#include "llvm/Module.h"
#include "llvm/TypeSymbolTable.h"
#include "llvm/ValueSymbolTable.h"
#include "llvm/Instructions.h"
#include <algorithm>
using namespace llvm;
@ -44,8 +45,10 @@ ValueEnumerator::ValueEnumerator(const Module *M) {
EnumerateValue(I);
// Enumerate the functions.
for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) {
EnumerateValue(I);
EnumerateParamAttrs(cast<Function>(I)->getParamAttrs());
}
// Enumerate the aliases.
for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end();
@ -86,6 +89,10 @@ ValueEnumerator::ValueEnumerator(const Module *M) {
OI != E; ++OI)
EnumerateOperandType(*OI);
EnumerateType(I->getType());
if (const CallInst *CI = dyn_cast<CallInst>(I))
EnumerateParamAttrs(CI->getParamAttrs());
else if (const InvokeInst *II = dyn_cast<InvokeInst>(I))
EnumerateParamAttrs(II->getParamAttrs());
}
}
@ -220,10 +227,6 @@ void ValueEnumerator::EnumerateType(const Type *Ty) {
for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end();
I != E; ++I)
EnumerateType(*I);
// If this is a function type, enumerate the param attrs.
if (const FunctionType *FTy = dyn_cast<FunctionType>(Ty))
EnumerateParamAttrs(FTy->getParamAttrs());
}
// Enumerate the types for the specified value. If the value is a constant,
@ -296,6 +299,10 @@ void ValueEnumerator::incorporateFunction(const Function &F) {
// Optimize the constant layout.
OptimizeConstants(FirstFuncConstantID, Values.size());
// Add the function's parameter attributes so they are available for use in
// the function's instruction.
EnumerateParamAttrs(F.getParamAttrs());
FirstInstID = Values.size();
// Add all of the instructions.

View File

@ -499,11 +499,11 @@ public:
unsigned Opc);
bool isExportableFromCurrentBlock(Value *V, const BasicBlock *FromBB);
void ExportFromCurrentBlock(Value *V);
void LowerCallTo(Instruction &I,
const Type *CalledValueTy, unsigned CallingConv,
void LowerCallTo(Instruction &I, const Type *CalledValueTy,
const ParamAttrsList *PAL, unsigned CallingConv,
bool IsTailCall, SDOperand Callee, unsigned OpIdx,
MachineBasicBlock *LandingPad = NULL);
// Terminator instructions.
void visitRet(ReturnInst &I);
void visitBr(BranchInst &I);
@ -934,12 +934,11 @@ void SelectionDAGLowering::visitRet(ReturnInst &I) {
TmpVT = TLI.getTypeToTransformTo(MVT::i32);
else
TmpVT = MVT::i32;
const FunctionType *FTy = I.getParent()->getParent()->getFunctionType();
const ParamAttrsList *Attrs = FTy->getParamAttrs();
const ParamAttrsList *PAL = I.getParent()->getParent()->getParamAttrs();
ISD::NodeType ExtendKind = ISD::ANY_EXTEND;
if (Attrs && Attrs->paramHasAttr(0, ParamAttr::SExt))
if (PAL && PAL->paramHasAttr(0, ParamAttr::SExt))
ExtendKind = ISD::SIGN_EXTEND;
if (Attrs && Attrs->paramHasAttr(0, ParamAttr::ZExt))
if (PAL && PAL->paramHasAttr(0, ParamAttr::ZExt))
ExtendKind = ISD::ZERO_EXTEND;
RetOp = DAG.getNode(ExtendKind, TmpVT, RetOp);
NewValues.push_back(RetOp);
@ -1450,7 +1449,7 @@ void SelectionDAGLowering::visitInvoke(InvokeInst &I) {
MachineBasicBlock *Return = FuncInfo.MBBMap[I.getSuccessor(0)];
MachineBasicBlock *LandingPad = FuncInfo.MBBMap[I.getSuccessor(1)];
LowerCallTo(I, I.getCalledValue()->getType(),
LowerCallTo(I, I.getCalledValue()->getType(), I.getParamAttrs(),
I.getCallingConv(),
false,
getValue(I.getOperand(0)),
@ -2940,13 +2939,13 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
void SelectionDAGLowering::LowerCallTo(Instruction &I,
const Type *CalledValueTy,
const ParamAttrsList *Attrs,
unsigned CallingConv,
bool IsTailCall,
SDOperand Callee, unsigned OpIdx,
MachineBasicBlock *LandingPad) {
const PointerType *PT = cast<PointerType>(CalledValueTy);
const FunctionType *FTy = cast<FunctionType>(PT->getElementType());
const ParamAttrsList *Attrs = FTy->getParamAttrs();
MachineModuleInfo *MMI = DAG.getMachineModuleInfo();
unsigned BeginLabel = 0, EndLabel = 0;
@ -3073,7 +3072,7 @@ void SelectionDAGLowering::visitCall(CallInst &I) {
else
Callee = DAG.getExternalSymbol(RenameFn, TLI.getPointerTy());
LowerCallTo(I, I.getCalledValue()->getType(),
LowerCallTo(I, I.getCalledValue()->getType(), I.getParamAttrs(),
I.getCallingConv(),
I.isTailCall(),
Callee,
@ -3893,8 +3892,7 @@ void SelectionDAGLowering::visitVACopy(CallInst &I) {
/// integrated into SDISel.
std::vector<SDOperand>
TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
const FunctionType *FTy = F.getFunctionType();
const ParamAttrsList *Attrs = FTy->getParamAttrs();
const ParamAttrsList *Attrs = F.getParamAttrs();
// Add CC# and isVararg as operands to the FORMAL_ARGUMENTS node.
std::vector<SDOperand> Ops;
Ops.push_back(DAG.getRoot());

View File

@ -358,6 +358,7 @@ static void CopyGVAttributes(GlobalValue *DestGV, const GlobalValue *SrcGV) {
if (const Function *SrcF = dyn_cast<Function>(SrcGV)) {
Function *DestF = cast<Function>(DestGV);
DestF->setCallingConv(SrcF->getCallingConv());
DestF->setParamAttrs(SrcF->getParamAttrs());
}
}

View File

@ -126,12 +126,14 @@ namespace {
std::ostream &printType(std::ostream &Out, const Type *Ty,
bool isSigned = false,
const std::string &VariableName = "",
bool IgnoreName = false);
bool IgnoreName = false,
const ParamAttrsList *PAL = 0);
std::ostream &printSimpleType(std::ostream &Out, const Type *Ty,
bool isSigned,
const std::string &NameSoFar = "");
void printStructReturnPointerFunctionType(std::ostream &Out,
const ParamAttrsList *PAL,
const PointerType *Ty);
void writeOperand(Value *Operand);
@ -353,6 +355,7 @@ bool CBackendNameAllUsedStructsAndMergeFunctions::runOnModule(Module &M) {
/// return type, except, instead of printing the type as void (*)(Struct*, ...)
/// print it as "Struct (*)(...)", for struct return functions.
void CWriter::printStructReturnPointerFunctionType(std::ostream &Out,
const ParamAttrsList *PAL,
const PointerType *TheTy) {
const FunctionType *FTy = cast<FunctionType>(TheTy->getElementType());
std::stringstream FunctionInnards;
@ -362,12 +365,11 @@ void CWriter::printStructReturnPointerFunctionType(std::ostream &Out,
FunctionType::param_iterator I = FTy->param_begin(), E = FTy->param_end();
const Type *RetTy = cast<PointerType>(I->get())->getElementType();
unsigned Idx = 1;
const ParamAttrsList *Attrs = FTy->getParamAttrs();
for (++I; I != E; ++I) {
if (PrintedType)
FunctionInnards << ", ";
printType(FunctionInnards, *I,
/*isSigned=*/Attrs && Attrs->paramHasAttr(Idx, ParamAttr::SExt), "");
/*isSigned=*/PAL && PAL->paramHasAttr(Idx, ParamAttr::SExt), "");
PrintedType = true;
}
if (FTy->isVarArg()) {
@ -379,7 +381,7 @@ void CWriter::printStructReturnPointerFunctionType(std::ostream &Out,
FunctionInnards << ')';
std::string tstr = FunctionInnards.str();
printType(Out, RetTy,
/*isSigned=*/Attrs && Attrs->paramHasAttr(0, ParamAttr::SExt), tstr);
/*isSigned=*/PAL && PAL->paramHasAttr(0, ParamAttr::SExt), tstr);
}
std::ostream &
@ -422,7 +424,7 @@ CWriter::printSimpleType(std::ostream &Out, const Type *Ty, bool isSigned,
//
std::ostream &CWriter::printType(std::ostream &Out, const Type *Ty,
bool isSigned, const std::string &NameSoFar,
bool IgnoreName) {
bool IgnoreName, const ParamAttrsList* PAL) {
if (Ty->isPrimitiveType() || Ty->isInteger()) {
printSimpleType(Out, Ty, isSigned, NameSoFar);
return Out;
@ -439,14 +441,13 @@ std::ostream &CWriter::printType(std::ostream &Out, const Type *Ty,
const FunctionType *FTy = cast<FunctionType>(Ty);
std::stringstream FunctionInnards;
FunctionInnards << " (" << NameSoFar << ") (";
const ParamAttrsList *Attrs = FTy->getParamAttrs();
unsigned Idx = 1;
for (FunctionType::param_iterator I = FTy->param_begin(),
E = FTy->param_end(); I != E; ++I) {
if (I != FTy->param_begin())
FunctionInnards << ", ";
printType(FunctionInnards, *I,
/*isSigned=*/Attrs && Attrs->paramHasAttr(Idx, ParamAttr::SExt), "");
printType(FunctionInnards, *I,
/*isSigned=*/PAL && PAL->paramHasAttr(Idx, ParamAttr::SExt), "");
++Idx;
}
if (FTy->isVarArg()) {
@ -458,7 +459,7 @@ std::ostream &CWriter::printType(std::ostream &Out, const Type *Ty,
FunctionInnards << ')';
std::string tstr = FunctionInnards.str();
printType(Out, FTy->getReturnType(),
/*isSigned=*/Attrs && Attrs->paramHasAttr(0, ParamAttr::SExt), tstr);
/*isSigned=*/PAL && PAL->paramHasAttr(0, ParamAttr::SExt), tstr);
return Out;
}
case Type::StructTyID: {
@ -1836,7 +1837,7 @@ void CWriter::printContainedStructs(const Type *Ty,
void CWriter::printFunctionSignature(const Function *F, bool Prototype) {
/// isStructReturn - Should this function actually return a struct by-value?
bool isStructReturn = F->getFunctionType()->isStructReturn();
bool isStructReturn = F->isStructReturn();
if (F->hasInternalLinkage()) Out << "static ";
if (F->hasDLLImportLinkage()) Out << "__declspec(dllimport) ";
@ -1852,7 +1853,7 @@ void CWriter::printFunctionSignature(const Function *F, bool Prototype) {
// Loop over the arguments, printing them...
const FunctionType *FT = cast<FunctionType>(F->getFunctionType());
const ParamAttrsList *Attrs = FT->getParamAttrs();
const ParamAttrsList *PAL = F->getParamAttrs();
std::stringstream FunctionInnards;
@ -1880,7 +1881,7 @@ void CWriter::printFunctionSignature(const Function *F, bool Prototype) {
else
ArgName = "";
printType(FunctionInnards, I->getType(),
/*isSigned=*/Attrs && Attrs->paramHasAttr(Idx, ParamAttr::SExt),
/*isSigned=*/PAL && PAL->paramHasAttr(Idx, ParamAttr::SExt),
ArgName);
PrintedArg = true;
++Idx;
@ -1901,7 +1902,7 @@ void CWriter::printFunctionSignature(const Function *F, bool Prototype) {
for (; I != E; ++I) {
if (PrintedArg) FunctionInnards << ", ";
printType(FunctionInnards, *I,
/*isSigned=*/Attrs && Attrs->paramHasAttr(Idx, ParamAttr::SExt));
/*isSigned=*/PAL && PAL->paramHasAttr(Idx, ParamAttr::SExt));
PrintedArg = true;
++Idx;
}
@ -1929,7 +1930,7 @@ void CWriter::printFunctionSignature(const Function *F, bool Prototype) {
// Print out the return type and the signature built above.
printType(Out, RetTy,
/*isSigned=*/ Attrs && Attrs->paramHasAttr(0, ParamAttr::SExt),
/*isSigned=*/ PAL && PAL->paramHasAttr(0, ParamAttr::SExt),
FunctionInnards.str());
}
@ -1944,7 +1945,7 @@ static inline bool isFPIntBitCast(const Instruction &I) {
void CWriter::printFunction(Function &F) {
/// isStructReturn - Should this function actually return a struct by-value?
bool isStructReturn = F.getFunctionType()->isStructReturn();
bool isStructReturn = F.isStructReturn();
printFunctionSignature(&F, false);
Out << " {\n";
@ -2068,8 +2069,7 @@ void CWriter::printBasicBlock(BasicBlock *BB) {
//
void CWriter::visitReturnInst(ReturnInst &I) {
// If this is a struct return function, return the temporary struct.
bool isStructReturn = I.getParent()->getParent()->
getFunctionType()->isStructReturn();
bool isStructReturn = I.getParent()->getParent()->isStructReturn();
if (isStructReturn) {
Out << " return StructReturn;\n";
@ -2594,7 +2594,8 @@ void CWriter::visitCallInst(CallInst &I) {
// If this is a call to a struct-return function, assign to the first
// parameter instead of passing it to the call.
bool isStructRet = FTy->isStructReturn();
const ParamAttrsList *PAL = I.getParamAttrs();
bool isStructRet = I.isStructReturn();
if (isStructRet) {
Out << "*(";
writeOperand(I.getOperand(1));
@ -2633,7 +2634,7 @@ void CWriter::visitCallInst(CallInst &I) {
if (!isStructRet)
printType(Out, I.getCalledValue()->getType());
else
printStructReturnPointerFunctionType(Out,
printStructReturnPointerFunctionType(Out, PAL,
cast<PointerType>(I.getCalledValue()->getType()));
Out << ")(void*)";
}
@ -2652,7 +2653,6 @@ void CWriter::visitCallInst(CallInst &I) {
++ArgNo;
}
const ParamAttrsList *Attrs = FTy->getParamAttrs();
bool PrintedArg = false;
unsigned Idx = 1;
for (; AI != AE; ++AI, ++ArgNo, ++Idx) {
@ -2661,7 +2661,7 @@ void CWriter::visitCallInst(CallInst &I) {
(*AI)->getType() != FTy->getParamType(ArgNo)) {
Out << '(';
printType(Out, FTy->getParamType(ArgNo),
/*isSigned=*/Attrs && Attrs->paramHasAttr(Idx, ParamAttr::SExt));
/*isSigned=*/PAL && PAL->paramHasAttr(Idx, ParamAttr::SExt));
Out << ')';
}
writeOperand(*AI);

View File

@ -1387,8 +1387,7 @@ void MSILWriter::printStaticInitializerList() {
void MSILWriter::printFunction(const Function& F) {
const FunctionType* FTy = F.getFunctionType();
const ParamAttrsList *Attrs = FTy->getParamAttrs();
const ParamAttrsList *Attrs = F.getParamAttrs();
bool isSigned = Attrs && Attrs->paramHasAttr(0, ParamAttr::SExt);
Out << "\n.method static ";
Out << (F.hasInternalLinkage() ? "private " : "public ");

View File

@ -93,13 +93,13 @@ void X86SharedAsmPrinter::decorateName(std::string &Name,
case StdCall:
// "Pure" variadic functions do not receive @0 suffix.
if (!FT->isVarArg() || (FT->getNumParams() == 0) ||
(FT->getNumParams() == 1 && FT->isStructReturn()))
(FT->getNumParams() == 1 && F->isStructReturn()))
Name += '@' + utostr_32(Info->getBytesToPopOnReturn());
break;
case FastCall:
// "Pure" variadic functions do not receive @0 suffix.
if (!FT->isVarArg() || (FT->getNumParams() == 0) ||
(FT->getNumParams() == 1 && FT->isStructReturn()))
(FT->getNumParams() == 1 && F->isStructReturn()))
Name += '@' + utostr_32(Info->getBytesToPopOnReturn());
if (Name[0] == '_') {

View File

@ -4927,7 +4927,7 @@ SDOperand X86TargetLowering::LowerTRAMPOLINE(SDOperand Op,
// Check that ECX wasn't needed by an 'inreg' parameter.
const FunctionType *FTy = Func->getFunctionType();
const ParamAttrsList *Attrs = FTy->getParamAttrs();
const ParamAttrsList *Attrs = Func->getParamAttrs();
if (Attrs && !Func->isVarArg()) {
unsigned InRegCount = 0;

View File

@ -35,6 +35,7 @@
#include "llvm/Module.h"
#include "llvm/CallGraphSCCPass.h"
#include "llvm/Instructions.h"
#include "llvm/ParameterAttributes.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Target/TargetData.h"
@ -139,10 +140,10 @@ bool ArgPromotion::PromoteArguments(CallGraphNode *CGN) {
// No promotable pointer arguments.
if (PointerArgs.empty()) return false;
// Okay, promote all of the arguments are rewrite the callees!
// Okay, promote all of the arguments and rewrite the callees!
Function *NewF = DoPromotion(F, PointerArgs);
// Update the call graph to know that the old function is gone.
// Update the call graph to know that the function has been transformed.
getAnalysis<CallGraph>().changeFunction(F, NewF);
return true;
}
@ -349,9 +350,23 @@ Function *ArgPromotion::DoPromotion(Function *F,
// what the new GEP/Load instructions we are inserting look like.
std::map<std::vector<Value*>, LoadInst*> OriginalLoads;
for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I)
// ParamAttrs - Keep track of the parameter attributes for the arguments
// that we are *not* promoting. For the ones that we do promote, the parameter
// attributes are lost
ParamAttrsVector ParamAttrsVec;
const ParamAttrsList *PAL = F->getParamAttrs();
unsigned index = 1;
for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E;
++I, ++index)
if (!ArgsToPromote.count(I)) {
Params.push_back(I->getType());
if (PAL) {
unsigned attrs = PAL->getParamAttrs(index);
if (attrs)
ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Params.size(),
attrs));
}
} else if (I->use_empty()) {
++NumArgumentsDead;
} else {
@ -387,6 +402,13 @@ Function *ArgPromotion::DoPromotion(Function *F,
const Type *RetTy = FTy->getReturnType();
// Recompute the parameter attributes list based on the new arguments for
// the function.
if (ParamAttrsVec.empty())
PAL = 0;
else
PAL = ParamAttrsList::get(ParamAttrsVec);
// Work around LLVM bug PR56: the CWriter cannot emit varargs functions which
// have zero fixed arguments.
bool ExtraArgHack = false;
@ -394,11 +416,14 @@ Function *ArgPromotion::DoPromotion(Function *F,
ExtraArgHack = true;
Params.push_back(Type::Int32Ty);
}
// Construct the new function type using the new arguments.
FunctionType *NFTy = FunctionType::get(RetTy, Params, FTy->isVarArg());
// Create the new function body and insert it into the module...
// Create the new function body and insert it into the module...
Function *NF = new Function(NFTy, F->getLinkage(), F->getName());
NF->setCallingConv(F->getCallingConv());
NF->setParamAttrs(PAL);
F->getParent()->getFunctionList().insert(F, NF);
// Get the alias analysis information that we need to update to reflect our
@ -449,9 +474,11 @@ Function *ArgPromotion::DoPromotion(Function *F,
New = new InvokeInst(NF, II->getNormalDest(), II->getUnwindDest(),
Args.begin(), Args.end(), "", Call);
cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv());
cast<InvokeInst>(New)->setParamAttrs(PAL);
} else {
New = new CallInst(NF, Args.begin(), Args.end(), "", Call);
cast<CallInst>(New)->setCallingConv(CS.getCallingConv());
cast<CallInst>(New)->setParamAttrs(PAL);
if (cast<CallInst>(Call)->isTailCall())
cast<CallInst>(New)->setTailCall();
}

View File

@ -26,6 +26,7 @@
#include "llvm/IntrinsicInst.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/ParameterAttributes.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Support/Debug.h"
#include "llvm/ADT/Statistic.h"
@ -157,6 +158,7 @@ bool DAE::DeleteDeadVarargs(Function &Fn) {
// Create the new function body and insert it into the module...
Function *NF = new Function(NFTy, Fn.getLinkage());
NF->setCallingConv(Fn.getCallingConv());
NF->setParamAttrs(Fn.getParamAttrs());
Fn.getParent()->getFunctionList().insert(&Fn, NF);
NF->takeName(&Fn);
@ -176,9 +178,11 @@ bool DAE::DeleteDeadVarargs(Function &Fn) {
New = new InvokeInst(NF, II->getNormalDest(), II->getUnwindDest(),
Args.begin(), Args.end(), "", Call);
cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv());
cast<InvokeInst>(New)->setParamAttrs(NF->getParamAttrs());
} else {
New = new CallInst(NF, Args.begin(), Args.end(), "", Call);
cast<CallInst>(New)->setCallingConv(CS.getCallingConv());
cast<CallInst>(New)->setParamAttrs(NF->getParamAttrs());
if (cast<CallInst>(Call)->isTailCall())
cast<CallInst>(New)->setTailCall();
}
@ -233,10 +237,10 @@ static inline bool CallPassesValueThoughVararg(Instruction *Call,
// (used in a computation), MaybeLive (only passed as an argument to a call), or
// Dead (not used).
DAE::Liveness DAE::getArgumentLiveness(const Argument &A) {
const FunctionType *FTy = A.getParent()->getFunctionType();
const Function *F = A.getParent();
// If this is the return value of a struct function, it's not really dead.
if (FTy->isStructReturn() && &*A.getParent()->arg_begin() == &A)
if (F->isStructReturn() && &*(F->arg_begin()) == &A)
return Live;
if (A.use_empty()) // First check, directly dead?
@ -488,10 +492,32 @@ void DAE::RemoveDeadArgumentsFromFunction(Function *F) {
const FunctionType *FTy = F->getFunctionType();
std::vector<const Type*> Params;
for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I)
if (!DeadArguments.count(I))
Params.push_back(I->getType());
// Set up to build a new list of parameter attributes
ParamAttrsVector ParamAttrsVec;
const ParamAttrsList *PAL = F->getParamAttrs();
// Construct the new parameter list from non-dead arguments. Also construct
// a new set of parameter attributes to correspond.
unsigned index = 1;
for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E;
++I, ++index)
if (!DeadArguments.count(I)) {
Params.push_back(I->getType());
if (PAL) {
uint16_t Attrs = PAL->getParamAttrs(index);
if (Attrs != ParamAttr::None)
ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Params.size(),
Attrs));
}
}
// Reconstruct the ParamAttrsList based on the vector we constructed.
if (ParamAttrsVec.empty())
PAL = 0;
else
PAL = ParamAttrsList::get(ParamAttrsVec);
// Make the function return void if the return value is dead.
const Type *RetTy = FTy->getReturnType();
if (DeadRetVal.count(F)) {
RetTy = Type::VoidTy;
@ -507,11 +533,13 @@ void DAE::RemoveDeadArgumentsFromFunction(Function *F) {
Params.push_back(Type::Int32Ty);
}
// Create the new function type based on the recomputed parameters.
FunctionType *NFTy = FunctionType::get(RetTy, Params, FTy->isVarArg());
// Create the new function body and insert it into the module...
Function *NF = new Function(NFTy, F->getLinkage());
NF->setCallingConv(F->getCallingConv());
NF->setParamAttrs(PAL);
F->getParent()->getFunctionList().insert(F, NF);
NF->takeName(F);
@ -542,9 +570,11 @@ void DAE::RemoveDeadArgumentsFromFunction(Function *F) {
New = new InvokeInst(NF, II->getNormalDest(), II->getUnwindDest(),
Args.begin(), Args.end(), "", Call);
cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv());
cast<InvokeInst>(New)->setParamAttrs(PAL);
} else {
New = new CallInst(NF, Args.begin(), Args.end(), "", Call);
cast<CallInst>(New)->setCallingConv(CS.getCallingConv());
cast<CallInst>(New)->setParamAttrs(PAL);
if (cast<CallInst>(Call)->isTailCall())
cast<CallInst>(New)->setTailCall();
}

View File

@ -95,6 +95,7 @@ namespace {
Function *New = new Function(I->getFunctionType(),
GlobalValue::ExternalLinkage);
New->setCallingConv(I->getCallingConv());
New->setParamAttrs(I->getParamAttrs());
// If it's not the named function, delete the body of the function
I->dropAllReferences();

View File

@ -476,6 +476,8 @@ void LowerSetJmp::visitCallInst(CallInst& CI)
InvokeInst* II = new
InvokeInst(CI.getCalledValue(), NewBB, PrelimBBMap[Func],
Params.begin(), Params.end(), CI.getName(), Term);
II->setCallingConv(CI.getCallingConv());
II->setParamAttrs(CI.getParamAttrs());
// Replace the old call inst with the invoke inst and remove the call.
CI.replaceAllUsesWith(II);

View File

@ -156,6 +156,7 @@ bool PruneEH::SimplifyFunction(Function *F) {
Args.begin(), Args.end(), "", II);
Call->takeName(II);
Call->setCallingConv(II->getCallingConv());
Call->setParamAttrs(II->getParamAttrs());
// Anything that used the value produced by the invoke instruction
// now uses the value produced by the call instruction.

View File

@ -7994,13 +7994,15 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) {
const FunctionType *FT = Callee->getFunctionType();
const Type *OldRetTy = Caller->getType();
const FunctionType *ActualFT =
cast<FunctionType>(cast<PointerType>(CE->getType())->getElementType());
const ParamAttrsList* CallerPAL = 0;
if (CallInst *CallerCI = dyn_cast<CallInst>(Caller))
CallerPAL = CallerCI->getParamAttrs();
else if (InvokeInst *CallerII = dyn_cast<InvokeInst>(Caller))
CallerPAL = CallerII->getParamAttrs();
// If the parameter attributes are not compatible, don't do the xform. We
// don't want to lose an sret attribute or something.
if (!ParamAttrsList::areCompatible(FT->getParamAttrs(),
ActualFT->getParamAttrs()))
if (!ParamAttrsList::areCompatible(CallerPAL, Callee->getParamAttrs()))
return false;
// Check to see if we are changing the return type...
@ -8135,12 +8137,15 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) {
NC = new InvokeInst(Callee, II->getNormalDest(), II->getUnwindDest(),
Args.begin(), Args.end(), Caller->getName(), Caller);
cast<InvokeInst>(NC)->setCallingConv(II->getCallingConv());
cast<InvokeInst>(NC)->setParamAttrs(CallerPAL);
} else {
NC = new CallInst(Callee, Args.begin(), Args.end(),
Caller->getName(), Caller);
if (cast<CallInst>(Caller)->isTailCall())
CallInst *CI = cast<CallInst>(Caller);
if (CI->isTailCall())
cast<CallInst>(NC)->setTailCall();
cast<CallInst>(NC)->setCallingConv(cast<CallInst>(Caller)->getCallingConv());
cast<CallInst>(NC)->setCallingConv(CI->getCallingConv());
cast<CallInst>(NC)->setParamAttrs(CallerPAL);
}
// Insert a cast of the return type as necessary.
@ -8191,7 +8196,7 @@ Instruction *InstCombiner::transformCallThroughTrampoline(CallSite CS) {
const PointerType *NestFPTy = cast<PointerType>(NestF->getType());
const FunctionType *NestFTy = cast<FunctionType>(NestFPTy->getElementType());
if (const ParamAttrsList *NestAttrs = NestFTy->getParamAttrs()) {
if (const ParamAttrsList *NestAttrs = NestF->getParamAttrs()) {
unsigned NestIdx = 1;
const Type *NestTy = 0;
uint16_t NestAttr = 0;
@ -8239,7 +8244,7 @@ Instruction *InstCombiner::transformCallThroughTrampoline(CallSite CS) {
// Handle this by synthesizing a new function type, equal to FTy
// with the chain parameter inserted. Likewise for attributes.
const ParamAttrsList *Attrs = FTy->getParamAttrs();
const ParamAttrsList *Attrs = CS.getParamAttrs();
std::vector<const Type*> NewTypes;
ParamAttrsVector NewAttrs;
NewTypes.reserve(FTy->getNumParams()+1);
@ -8280,10 +8285,10 @@ Instruction *InstCombiner::transformCallThroughTrampoline(CallSite CS) {
// Replace the trampoline call with a direct call. Let the generic
// code sort out any function type mismatches.
FunctionType *NewFTy =
FunctionType::get(FTy->getReturnType(), NewTypes, FTy->isVarArg(),
ParamAttrsList::get(NewAttrs));
FunctionType::get(FTy->getReturnType(), NewTypes, FTy->isVarArg());
Constant *NewCallee = NestF->getType() == PointerType::get(NewFTy) ?
NestF : ConstantExpr::getBitCast(NestF, PointerType::get(NewFTy));
const ParamAttrsList *NewPAL = ParamAttrsList::get(NewAttrs);
Instruction *NewCaller;
if (InvokeInst *II = dyn_cast<InvokeInst>(Caller)) {
@ -8292,6 +8297,7 @@ Instruction *InstCombiner::transformCallThroughTrampoline(CallSite CS) {
NewArgs.begin(), NewArgs.end(),
Caller->getName(), Caller);
cast<InvokeInst>(NewCaller)->setCallingConv(II->getCallingConv());
cast<InvokeInst>(NewCaller)->setParamAttrs(NewPAL);
} else {
NewCaller = new CallInst(NewCallee, NewArgs.begin(), NewArgs.end(),
Caller->getName(), Caller);
@ -8299,6 +8305,7 @@ Instruction *InstCombiner::transformCallThroughTrampoline(CallSite CS) {
cast<CallInst>(NewCaller)->setTailCall();
cast<CallInst>(NewCaller)->
setCallingConv(cast<CallInst>(Caller)->getCallingConv());
cast<CallInst>(NewCaller)->setParamAttrs(NewPAL);
}
if (Caller->getType() != Type::VoidTy && !Caller->use_empty())
Caller->replaceAllUsesWith(NewCaller);

View File

@ -339,6 +339,8 @@ bool LowerGC::runOnFunction(Function &F) {
Value *II = new InvokeInst(CI->getCalledValue(), NewBB, Cleanup,
Args.begin(), Args.end(), CI->getName(), CBB);
cast<InvokeInst>(II)->setCallingConv(CI->getCallingConv());
cast<InvokeInst>(II)->setParamAttrs(CI->getParamAttrs());
CI->replaceAllUsesWith(II);
delete CI;
}

View File

@ -96,16 +96,11 @@ static bool IsNoReturn(const CallInst *CI) {
if (Attrs->paramHasAttr(0, ParamAttr::NoReturn))
return true;
if (const Function *Callee = CI->getCalledFunction()) {
if (const Function *Callee = CI->getCalledFunction())
if (const ParamAttrsList *Attrs = Callee->getParamAttrs())
if (Attrs->paramHasAttr(0, ParamAttr::NoReturn))
return true;
const FunctionType *FT = Callee->getFunctionType();
if (const ParamAttrsList *Attrs = FT->getParamAttrs())
if (Attrs->paramHasAttr(0, ParamAttr::NoReturn))
return true;
}
return false;
}
@ -115,16 +110,11 @@ static bool IsNoUnwind(const InvokeInst *II) {
if (Attrs->paramHasAttr(0, ParamAttr::NoUnwind))
return true;
if (const Function *Callee = II->getCalledFunction()) {
if (const Function *Callee = II->getCalledFunction())
if (const ParamAttrsList *Attrs = Callee->getParamAttrs())
if (Attrs->paramHasAttr(0, ParamAttr::NoUnwind))
return true;
const FunctionType *FT = Callee->getFunctionType();
if (const ParamAttrsList *Attrs = FT->getParamAttrs())
if (Attrs->paramHasAttr(0, ParamAttr::NoUnwind))
return true;
}
return false;
}

View File

@ -79,6 +79,9 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
assert(ValueMap.count(I) && "No mapping from source argument specified!");
#endif
// Clone the parameter attributes
NewFunc->setParamAttrs(OldFunc->getParamAttrs());
// Loop over all of the basic blocks in the function, cloning them as
// appropriate. Note that we save BE this way in order to handle cloning of
// recursive functions into themselves.
@ -304,7 +307,7 @@ ConstantFoldMappedInstruction(const Instruction *I) {
/// effect of this is to copy significantly less code in cases where (for
/// example) a function call with constant arguments is inlined, and those
/// constant arguments cause a significant amount of code in the callee to be
/// dead. Since this doesn't produce an exactly copy of the input, it can't be
/// dead. Since this doesn't produce an exact copy of the input, it can't be
/// used for things like CloneFunction or CloneModule.
void llvm::CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc,
DenseMap<const Value*, Value*> &ValueMap,

View File

@ -66,6 +66,7 @@ Module *llvm::CloneModule(const Module *M,
new Function(cast<FunctionType>(I->getType()->getElementType()),
GlobalValue::ExternalLinkage, I->getName(), New);
NF->setCallingConv(I->getCallingConv());
NF->setParamAttrs(I->getParamAttrs());
ValueMap[I]= NF;
}
@ -120,5 +121,3 @@ Module *llvm::CloneModule(const Module *M,
return New;
}
// vim: sw=2

View File

@ -88,6 +88,7 @@ static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock,
InvokeArgs.begin(), InvokeArgs.end(),
CI->getName(), BB->getTerminator());
II->setCallingConv(CI->getCallingConv());
II->setParamAttrs(CI->getParamAttrs());
// Make sure that anything using the call now uses the invoke!
CI->replaceAllUsesWith(II);

View File

@ -212,9 +212,10 @@ bool LowerInvoke::insertCheapEHSupport(Function &F) {
std::vector<Value*> CallArgs(II->op_begin()+3, II->op_end());
// Insert a normal call instruction...
CallInst *NewCall = new CallInst(II->getCalledValue(),
CallArgs.begin(), CallArgs.end(), "", II);
CallArgs.begin(), CallArgs.end(), "",II);
NewCall->takeName(II);
NewCall->setCallingConv(II->getCallingConv());
NewCall->setParamAttrs(II->getParamAttrs());
II->replaceAllUsesWith(NewCall);
// Insert an unconditional branch to the normal destination.
@ -273,6 +274,7 @@ void LowerInvoke::rewriteExpensiveInvoke(InvokeInst *II, unsigned InvokeNo,
II);
NewCall->takeName(II);
NewCall->setCallingConv(II->getCallingConv());
NewCall->setParamAttrs(II->getParamAttrs());
II->replaceAllUsesWith(NewCall);
// Replace the invoke with an uncond branch.

View File

@ -1376,6 +1376,7 @@ bool llvm::SimplifyCFG(BasicBlock *BB) {
CallInst *CI = new CallInst(II->getCalledValue(),
Args.begin(), Args.end(), II->getName(), BI);
CI->setCallingConv(II->getCallingConv());
CI->setParamAttrs(II->getParamAttrs());
// If the invoke produced a value, the Call now does instead
II->replaceAllUsesWith(CI);
delete II;
@ -1751,6 +1752,7 @@ bool llvm::SimplifyCFG(BasicBlock *BB) {
Args.begin(), Args.end(),
II->getName(), BI);
CI->setCallingConv(II->getCallingConv());
CI->setParamAttrs(II->getParamAttrs());
// If the invoke produced a value, the Call does now instead.
II->replaceAllUsesWith(CI);
delete II;

View File

@ -305,28 +305,17 @@ static void calcTypeName(const Type *Ty,
const FunctionType *FTy = cast<FunctionType>(Ty);
calcTypeName(FTy->getReturnType(), TypeStack, TypeNames, Result);
Result += " (";
unsigned Idx = 1;
const ParamAttrsList *Attrs = FTy->getParamAttrs();
for (FunctionType::param_iterator I = FTy->param_begin(),
E = FTy->param_end(); I != E; ++I) {
E = FTy->param_end(); I != E; ++I) {
if (I != FTy->param_begin())
Result += ", ";
calcTypeName(*I, TypeStack, TypeNames, Result);
if (Attrs && Attrs->getParamAttrs(Idx) != ParamAttr::None) {
Result += + " ";
Result += Attrs->getParamAttrsTextByIndex(Idx);
}
Idx++;
}
if (FTy->isVarArg()) {
if (FTy->getNumParams()) Result += ", ";
Result += "...";
}
Result += ")";
if (Attrs && Attrs->getParamAttrs(0) != ParamAttr::None) {
Result += " ";
Result += Attrs->getParamAttrsTextByIndex(0);
}
break;
}
case Type::StructTyID: {
@ -749,6 +738,7 @@ public:
inline void write(const Type *Ty) { printType(Ty); }
void writeOperand(const Value *Op, bool PrintType);
void writeParamOperand(const Value *Operand, uint16_t Attrs);
const Module* getModule() { return TheModule; }
@ -789,25 +779,17 @@ std::ostream &AssemblyWriter::printTypeAtLeastOneLevel(const Type *Ty) {
else if (const FunctionType *FTy = dyn_cast<FunctionType>(Ty)) {
printType(FTy->getReturnType());
Out << " (";
unsigned Idx = 1;
const ParamAttrsList *Attrs = FTy->getParamAttrs();
for (FunctionType::param_iterator I = FTy->param_begin(),
E = FTy->param_end(); I != E; ++I) {
if (I != FTy->param_begin())
Out << ", ";
printType(*I);
if (Attrs && Attrs->getParamAttrs(Idx) != ParamAttr::None) {
Out << " " << Attrs->getParamAttrsTextByIndex(Idx);
}
Idx++;
}
if (FTy->isVarArg()) {
if (FTy->getNumParams()) Out << ", ";
Out << "...";
}
Out << ')';
if (Attrs && Attrs->getParamAttrs(0) != ParamAttr::None)
Out << ' ' << Attrs->getParamAttrsTextByIndex(0);
} else if (const StructType *STy = dyn_cast<StructType>(Ty)) {
if (STy->isPacked())
Out << '<';
@ -850,6 +832,20 @@ void AssemblyWriter::writeOperand(const Value *Operand, bool PrintType) {
}
}
void AssemblyWriter::writeParamOperand(const Value *Operand, uint16_t Attrs) {
if (Operand == 0) {
Out << "<null operand!>";
} else {
Out << ' ';
// Print the type
printType(Operand->getType());
// Print parameter attributes list
if (Attrs != ParamAttr::None)
Out << ' ' << ParamAttrsList::getParamAttrsText(Attrs);
// Print the operand
WriteAsOperandInternal(Out, Operand, TypeNames, &Machine);
}
}
void AssemblyWriter::printModule(const Module *M) {
if (!M->getModuleIdentifier().empty() &&
@ -1066,7 +1062,7 @@ void AssemblyWriter::printFunction(const Function *F) {
}
const FunctionType *FT = F->getFunctionType();
const ParamAttrsList *Attrs = FT->getParamAttrs();
const ParamAttrsList *Attrs = F->getParamAttrs();
printType(F->getReturnType()) << ' ';
if (!F->getName().empty())
Out << getLLVMName(F->getName(), GlobalPrefix);
@ -1139,6 +1135,7 @@ void AssemblyWriter::printArgument(const Argument *Arg, uint16_t Attrs) {
// Output type...
printType(Arg->getType());
// Output parameter attributes list
if (Attrs != ParamAttr::None)
Out << ' ' << ParamAttrsList::getParamAttrsText(Attrs);
@ -1295,7 +1292,7 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
const PointerType *PTy = cast<PointerType>(Operand->getType());
const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
const Type *RetTy = FTy->getReturnType();
const ParamAttrsList *PAL = FTy->getParamAttrs();
const ParamAttrsList *PAL = CI->getParamAttrs();
// If possible, print out the short form of the call instruction. We can
// only do this if the first argument is a pointer to a nonvararg function,
@ -1313,9 +1310,7 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
for (unsigned op = 1, Eop = I.getNumOperands(); op < Eop; ++op) {
if (op > 1)
Out << ',';
writeOperand(I.getOperand(op), true);
if (PAL && PAL->getParamAttrs(op) != ParamAttr::None)
Out << " " << PAL->getParamAttrsTextByIndex(op);
writeParamOperand(I.getOperand(op), PAL ? PAL->getParamAttrs(op) : 0);
}
Out << " )";
if (PAL && PAL->getParamAttrs(0) != ParamAttr::None)
@ -1324,7 +1319,7 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
const PointerType *PTy = cast<PointerType>(Operand->getType());
const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
const Type *RetTy = FTy->getReturnType();
const ParamAttrsList *PAL = FTy->getParamAttrs();
const ParamAttrsList *PAL = II->getParamAttrs();
// Print the calling convention being used.
switch (II->getCallingConv()) {
@ -1353,9 +1348,7 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
for (unsigned op = 3, Eop = I.getNumOperands(); op < Eop; ++op) {
if (op > 3)
Out << ',';
writeOperand(I.getOperand(op), true);
if (PAL && PAL->getParamAttrs(op-2) != ParamAttr::None)
Out << " " << PAL->getParamAttrsTextByIndex(op-2);
writeParamOperand(I.getOperand(op), PAL ? PAL->getParamAttrs(op-2) : 0);
}
Out << " )";

View File

@ -127,9 +127,6 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
Function *F = CI->getCalledFunction();
assert(F && "CallInst has no function associated with it.");
const FunctionType *FTy = F->getFunctionType();
const FunctionType *NewFnTy = NewFn->getFunctionType();
switch(NewFn->getIntrinsicID()) {
default: assert(0 && "Unknown function for CallInst upgrade.");
@ -149,10 +146,10 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
// Handle any uses of the old CallInst.
if (!CI->use_empty()) {
// Check for sign extend parameter attributes on the return values.
bool SrcSExt = NewFnTy->getParamAttrs() &&
NewFnTy->getParamAttrs()->paramHasAttr(0,ParamAttr::SExt);
bool DestSExt = FTy->getParamAttrs() &&
FTy->getParamAttrs()->paramHasAttr(0,ParamAttr::SExt);
bool SrcSExt = NewFn->getParamAttrs() &&
NewFn->getParamAttrs()->paramHasAttr(0,ParamAttr::SExt);
bool DestSExt = F->getParamAttrs() &&
F->getParamAttrs()->paramHasAttr(0,ParamAttr::SExt);
// Construct an appropriate cast from the new return type to the old.
CastInst *RetCast = CastInst::create(

View File

@ -161,7 +161,7 @@ ParamAttrsList::areCompatible(const ParamAttrsList *A, const ParamAttrsList *B){
void
ParamAttrsList::Profile(FoldingSetNodeID &ID) const {
for (unsigned i = 0; i < attrs.size(); ++i) {
unsigned val = attrs[i].attrs << 16 | attrs[i].index;
uint32_t val = uint32_t(attrs[i].attrs) << 16 | attrs[i].index;
ID.AddInteger(val);
}
}
@ -170,7 +170,10 @@ static ManagedStatic<FoldingSet<ParamAttrsList> > ParamAttrsLists;
ParamAttrsList *
ParamAttrsList::get(const ParamAttrsVector &attrVec) {
assert(!attrVec.empty() && "Illegal to create empty ParamAttrsList");
// If there are no attributes then return a null ParamAttrsList pointer.
if (attrVec.empty())
return 0;
#ifndef NDEBUG
for (unsigned i = 0, e = attrVec.size(); i < e; ++i) {
assert(attrVec[i].attrs != ParamAttr::None
@ -179,15 +182,22 @@ ParamAttrsList::get(const ParamAttrsVector &attrVec) {
&& "Misordered ParamAttrsList!");
}
#endif
// Otherwise, build a key to look up the existing attributes.
ParamAttrsList key(attrVec);
FoldingSetNodeID ID;
key.Profile(ID);
void *InsertPos;
ParamAttrsList* PAL = ParamAttrsLists->FindNodeOrInsertPos(ID, InsertPos);
// If we didn't find any existing attributes of the same shape then
// create a new one and insert it.
if (!PAL) {
PAL = new ParamAttrsList(attrVec);
ParamAttrsLists->InsertNode(PAL, InsertPos);
}
// Return the ParamAttrsList that we found or created.
return PAL;
}
@ -201,8 +211,8 @@ ParamAttrsList::~ParamAttrsList() {
Function::Function(const FunctionType *Ty, LinkageTypes Linkage,
const std::string &name, Module *ParentModule)
: GlobalValue(PointerType::get(Ty), Value::FunctionVal, 0, 0, Linkage, name) {
ParamAttrs = 0;
: GlobalValue(PointerType::get(Ty), Value::FunctionVal, 0, 0, Linkage, name),
ParamAttrs(0) {
SymTab = new ValueSymbolTable();
assert((getReturnType()->isFirstClassType() ||getReturnType() == Type::VoidTy)
@ -259,16 +269,30 @@ void Function::setParent(Module *parent) {
LeakDetector::removeGarbageObject(this);
}
void Function::setParamAttrs(ParamAttrsList *attrs) {
void Function::setParamAttrs(const ParamAttrsList *attrs) {
// Avoid deleting the ParamAttrsList if they are setting the
// attributes to the same list.
if (ParamAttrs == attrs)
return;
// Drop reference on the old ParamAttrsList
if (ParamAttrs)
ParamAttrs->dropRef();
// Add reference to the new ParamAttrsList
if (attrs)
attrs->addRef();
// Set the new ParamAttrsList.
ParamAttrs = attrs;
}
bool Function::isStructReturn() const {
if (ParamAttrs)
return ParamAttrs->paramHasAttr(1, ParamAttr::StructRet);
return false;
}
const FunctionType *Function::getFunctionType() const {
return cast<FunctionType>(getType()->getElementType());
}

View File

@ -35,6 +35,18 @@ void CallSite::setCallingConv(unsigned CC) {
else
cast<InvokeInst>(I)->setCallingConv(CC);
}
const ParamAttrsList* CallSite::getParamAttrs() const {
if (CallInst *CI = dyn_cast<CallInst>(I))
return CI->getParamAttrs();
else
return cast<InvokeInst>(I)->getParamAttrs();
}
void CallSite::setParamAttrs(const ParamAttrsList *PAL) {
if (CallInst *CI = dyn_cast<CallInst>(I))
CI->setParamAttrs(PAL);
else
cast<InvokeInst>(I)->setParamAttrs(PAL);
}
@ -341,8 +353,9 @@ CallInst::CallInst(Value *Func, const std::string &Name,
CallInst::CallInst(const CallInst &CI)
: Instruction(CI.getType(), Instruction::Call, new Use[CI.getNumOperands()],
CI.getNumOperands()) {
ParamAttrs = 0;
CI.getNumOperands()),
ParamAttrs(0) {
setParamAttrs(CI.getParamAttrs());
SubclassData = CI.SubclassData;
Use *OL = OperandList;
Use *InOL = CI.OperandList;
@ -350,7 +363,10 @@ CallInst::CallInst(const CallInst &CI)
OL[i].init(InOL[i], this);
}
void CallInst::setParamAttrs(ParamAttrsList *newAttrs) {
void CallInst::setParamAttrs(const ParamAttrsList *newAttrs) {
if (ParamAttrs == newAttrs)
return;
if (ParamAttrs)
ParamAttrs->dropRef();
@ -360,6 +376,12 @@ void CallInst::setParamAttrs(ParamAttrsList *newAttrs) {
ParamAttrs = newAttrs;
}
bool CallInst::isStructReturn() const {
if (ParamAttrs)
return ParamAttrs->paramHasAttr(1, ParamAttr::StructRet);
return false;
}
//===----------------------------------------------------------------------===//
// InvokeInst Implementation
//===----------------------------------------------------------------------===//
@ -397,8 +419,9 @@ void InvokeInst::init(Value *Fn, BasicBlock *IfNormal, BasicBlock *IfException,
InvokeInst::InvokeInst(const InvokeInst &II)
: TerminatorInst(II.getType(), Instruction::Invoke,
new Use[II.getNumOperands()], II.getNumOperands()) {
ParamAttrs = 0;
new Use[II.getNumOperands()], II.getNumOperands()),
ParamAttrs(0) {
setParamAttrs(II.getParamAttrs());
SubclassData = II.SubclassData;
Use *OL = OperandList, *InOL = II.OperandList;
for (unsigned i = 0, e = II.getNumOperands(); i != e; ++i)
@ -415,7 +438,10 @@ void InvokeInst::setSuccessorV(unsigned idx, BasicBlock *B) {
return setSuccessor(idx, B);
}
void InvokeInst::setParamAttrs(ParamAttrsList *newAttrs) {
void InvokeInst::setParamAttrs(const ParamAttrsList *newAttrs) {
if (ParamAttrs == newAttrs)
return;
if (ParamAttrs)
ParamAttrs->dropRef();
@ -425,6 +451,12 @@ void InvokeInst::setParamAttrs(ParamAttrsList *newAttrs) {
ParamAttrs = newAttrs;
}
bool InvokeInst::isStructReturn() const {
if (ParamAttrs)
return ParamAttrs->paramHasAttr(1, ParamAttr::StructRet);
return false;
}
//===----------------------------------------------------------------------===//
// ReturnInst Implementation
//===----------------------------------------------------------------------===//

View File

@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//
#include "llvm/DerivedTypes.h"
#include "llvm/ParameterAttributes.h"
#include "llvm/Constants.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/StringExtras.h"
@ -307,15 +306,10 @@ static std::string getTypeDescription(const Type *Ty,
if (!Result.empty())
Result += " ";
Result += getTypeDescription(FTy->getReturnType(), TypeStack) + " (";
unsigned Idx = 1;
const ParamAttrsList *Attrs = FTy->getParamAttrs();
for (FunctionType::param_iterator I = FTy->param_begin(),
E = FTy->param_end(); I != E; ++I) {
E = FTy->param_end(); I != E; ++I) {
if (I != FTy->param_begin())
Result += ", ";
if (Attrs && Attrs->getParamAttrs(Idx) != ParamAttr::None)
Result += Attrs->getParamAttrsTextByIndex(Idx);
Idx++;
Result += getTypeDescription(*I, TypeStack);
}
if (FTy->isVarArg()) {
@ -323,9 +317,6 @@ static std::string getTypeDescription(const Type *Ty,
Result += "...";
}
Result += ")";
if (Attrs && Attrs->getParamAttrs(0) != ParamAttr::None) {
Result += " " + Attrs->getParamAttrsTextByIndex(0);
}
break;
}
case Type::StructTyID: {
@ -444,8 +435,8 @@ const IntegerType *Type::Int64Ty = new BuiltinIntegerType(64);
FunctionType::FunctionType(const Type *Result,
const std::vector<const Type*> &Params,
bool IsVarArgs, const ParamAttrsList *Attrs)
: DerivedType(FunctionTyID), isVarArgs(IsVarArgs), ParamAttrs(Attrs) {
bool IsVarArgs)
: DerivedType(FunctionTyID), isVarArgs(IsVarArgs) {
ContainedTys = reinterpret_cast<PATypeHandle*>(this+1);
NumContainedTys = Params.size() + 1; // + 1 for result type
assert((Result->isFirstClassType() || Result == Type::VoidTy ||
@ -667,16 +658,7 @@ static bool TypesEqual(const Type *Ty, const Type *Ty2,
FTy->getNumParams() != FTy2->getNumParams() ||
!TypesEqual(FTy->getReturnType(), FTy2->getReturnType(), EqTypes))
return false;
const ParamAttrsList *Attrs1 = FTy->getParamAttrs();
const ParamAttrsList *Attrs2 = FTy2->getParamAttrs();
if ((!Attrs1 && Attrs2) || (!Attrs2 && Attrs1) ||
(Attrs1 && Attrs2 && (Attrs1->size() != Attrs2->size() ||
(Attrs1->getParamAttrs(0) != Attrs2->getParamAttrs(0)))))
return false;
for (unsigned i = 0, e = FTy2->getNumParams(); i != e; ++i) {
if (Attrs1 && Attrs1->getParamAttrs(i+1) != Attrs2->getParamAttrs(i+1))
return false;
if (!TypesEqual(FTy->getParamType(i), FTy2->getParamType(i), EqTypes))
return false;
}
@ -1055,12 +1037,10 @@ namespace llvm {
class FunctionValType {
const Type *RetTy;
std::vector<const Type*> ArgTypes;
const ParamAttrsList *ParamAttrs;
bool isVarArg;
public:
FunctionValType(const Type *ret, const std::vector<const Type*> &args,
bool IVA, const ParamAttrsList *attrs)
: RetTy(ret), ParamAttrs(attrs), isVarArg(IVA) {
bool isVA) : RetTy(ret), isVarArg(isVA) {
for (unsigned i = 0; i < args.size(); ++i)
ArgTypes.push_back(args[i]);
}
@ -1068,9 +1048,7 @@ public:
static FunctionValType get(const FunctionType *FT);
static unsigned hashTypeStructure(const FunctionType *FT) {
unsigned Result = FT->getNumParams()*64 + FT->isVarArg();
if (FT->getParamAttrs())
Result += FT->getParamAttrs()->size()*2;
unsigned Result = FT->getNumParams()*2 + FT->isVarArg();
return Result;
}
@ -1081,13 +1059,6 @@ public:
if (isVarArg > MTV.isVarArg) return false;
if (ArgTypes < MTV.ArgTypes) return true;
if (ArgTypes > MTV.ArgTypes) return false;
if (ParamAttrs)
if (MTV.ParamAttrs)
return *ParamAttrs < *MTV.ParamAttrs;
else
return false;
else if (MTV.ParamAttrs)
return true;
return false;
}
};
@ -1102,18 +1073,15 @@ FunctionValType FunctionValType::get(const FunctionType *FT) {
ParamTypes.reserve(FT->getNumParams());
for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i)
ParamTypes.push_back(FT->getParamType(i));
return FunctionValType(FT->getReturnType(), ParamTypes, FT->isVarArg(),
FT->getParamAttrs());
return FunctionValType(FT->getReturnType(), ParamTypes, FT->isVarArg());
}
// FunctionType::get - The factory function for the FunctionType class...
FunctionType *FunctionType::get(const Type *ReturnType,
const std::vector<const Type*> &Params,
bool isVarArg,
const ParamAttrsList *Attrs) {
FunctionValType VT(ReturnType, Params, isVarArg, Attrs);
bool isVarArg) {
FunctionValType VT(ReturnType, Params, isVarArg);
FunctionType *FT = FunctionTypes->get(VT);
if (FT) {
return FT;
@ -1121,7 +1089,7 @@ FunctionType *FunctionType::get(const Type *ReturnType,
FT = (FunctionType*) new char[sizeof(FunctionType) +
sizeof(PATypeHandle)*(Params.size()+1)];
new (FT) FunctionType(ReturnType, Params, isVarArg, Attrs);
new (FT) FunctionType(ReturnType, Params, isVarArg);
FunctionTypes->add(VT, FT);
#ifdef DEBUG_MERGE_TYPES
@ -1130,12 +1098,6 @@ FunctionType *FunctionType::get(const Type *ReturnType,
return FT;
}
bool FunctionType::isStructReturn() const {
if (ParamAttrs)
return ParamAttrs->paramHasAttr(1, ParamAttr::StructRet);
return false;
}
//===----------------------------------------------------------------------===//
// Array Type Factory...
//

View File

@ -390,12 +390,12 @@ void Verifier::visitFunction(Function &F) {
F.getReturnType() == Type::VoidTy,
"Functions cannot return aggregate values!", &F);
Assert1(!FT->isStructReturn() || FT->getReturnType() == Type::VoidTy,
Assert1(!F.isStructReturn() || FT->getReturnType() == Type::VoidTy,
"Invalid struct-return function!", &F);
bool SawSRet = false;
if (const ParamAttrsList *Attrs = FT->getParamAttrs()) {
if (const ParamAttrsList *Attrs = F.getParamAttrs()) {
bool SawNest = false;
for (unsigned Idx = 0; Idx <= FT->getNumParams(); ++Idx) {
@ -448,7 +448,7 @@ void Verifier::visitFunction(Function &F) {
}
}
Assert1(SawSRet == FT->isStructReturn(),
Assert1(SawSRet == F.isStructReturn(),
"StructReturn function with no sret attribute!", &F);
// Check that this function meets the restrictions on this calling convention.

View File

@ -1,5 +1,5 @@
; RUN: llvm-upgrade < %s | llvm-as | llvm-dis | \
; RUN: grep {tail call void (\{ \}\\* sret}
; RUN: grep {tail call void.*sret null}
declare csretcc void %foo({}*, ...)

View File

@ -1,7 +1,5 @@
; For PR1187
; RUN: llvm-upgrade < %s > /dev/null
; XFAIL: *
; Un-XFAIL this when PR1146 is fixed.
; PR1187
%mystruct = type { int, double }
%glob = global %mystruct { int 3, double 42.0 }

View File

@ -0,0 +1,4 @@
; RUN: not llvm-as < %s
declare i32 @atoi(i8*) nounwind readonly
declare i32 @atoi(i8*)

View File

@ -0,0 +1,3 @@
; RUN: llvm-as < %s
@FP = weak global i8 (...) signext * null

View File

@ -14,7 +14,7 @@ declare void @exit(i32) noreturn nounwind
define i32 @main(i32 inreg %argc, i8 ** inreg %argv) nounwind {
%val = trunc i32 %argc to i16
%res1 = call i16 (i16 signext) signext *@test(i16 %val)
%res1 = call i16 (i16 signext) signext *@test(i16 signext %val) signext
%two = add i16 %res1, %res1
%res2 = call i8 @test2(i16 %two zeroext) zeroext
%retVal = sext i16 %two to i32

View File

@ -11,7 +11,7 @@ declare i8 @"test2" (i16 zeroext %a2) zeroext
define i33 @main(i33 %argc, i8 **%argv) {
%val = trunc i33 %argc to i16
%res = call i16 (i16 signext) signext *@test(i16 %val)
%res = call i16 (i16 signext) signext *@test(i16 signext %val) signext
%two = add i16 %res, %res
%res2 = call i8 @test2(i16 %two zeroext) zeroext
%retVal = sext i16 %two to i33

View File

@ -1,6 +1,4 @@
; RUN: llvm-upgrade < %s | llvm-as | opt -simplifycfg -disable-output
; XFAIL: *
; Un-XFAIL this when PR1146 is finished.
%struct..4._102 = type { %struct.QVectorData* }
%struct..5._125 = type { %struct.QMapData* }

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,353 @@
typedef union {
/* A Bison parser, made by GNU Bison 2.3. */
/* Skeleton interface for Bison's Yacc-like parsers in C
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
under terms of your choice, so long as that work isn't itself a
parser generator using the skeleton or a modified version thereof
as a parser skeleton. Alternatively, if you modify or redistribute
the parser skeleton itself, you may (at your option) remove this
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
ESINT64VAL = 258,
EUINT64VAL = 259,
SINTVAL = 260,
UINTVAL = 261,
FPVAL = 262,
VOID = 263,
BOOL = 264,
SBYTE = 265,
UBYTE = 266,
SHORT = 267,
USHORT = 268,
INT = 269,
UINT = 270,
LONG = 271,
ULONG = 272,
FLOAT = 273,
DOUBLE = 274,
TYPE = 275,
LABEL = 276,
VAR_ID = 277,
LABELSTR = 278,
STRINGCONSTANT = 279,
IMPLEMENTATION = 280,
ZEROINITIALIZER = 281,
TRUETOK = 282,
FALSETOK = 283,
BEGINTOK = 284,
ENDTOK = 285,
DECLARE = 286,
GLOBAL = 287,
CONSTANT = 288,
SECTION = 289,
VOLATILE = 290,
TO = 291,
DOTDOTDOT = 292,
NULL_TOK = 293,
UNDEF = 294,
CONST = 295,
INTERNAL = 296,
LINKONCE = 297,
WEAK = 298,
APPENDING = 299,
DLLIMPORT = 300,
DLLEXPORT = 301,
EXTERN_WEAK = 302,
OPAQUE = 303,
NOT = 304,
EXTERNAL = 305,
TARGET = 306,
TRIPLE = 307,
ENDIAN = 308,
POINTERSIZE = 309,
LITTLE = 310,
BIG = 311,
ALIGN = 312,
DEPLIBS = 313,
CALL = 314,
TAIL = 315,
ASM_TOK = 316,
MODULE = 317,
SIDEEFFECT = 318,
CC_TOK = 319,
CCC_TOK = 320,
CSRETCC_TOK = 321,
FASTCC_TOK = 322,
COLDCC_TOK = 323,
X86_STDCALLCC_TOK = 324,
X86_FASTCALLCC_TOK = 325,
DATALAYOUT = 326,
RET = 327,
BR = 328,
SWITCH = 329,
INVOKE = 330,
UNREACHABLE = 331,
UNWIND = 332,
EXCEPT = 333,
ADD = 334,
SUB = 335,
MUL = 336,
DIV = 337,
UDIV = 338,
SDIV = 339,
FDIV = 340,
REM = 341,
UREM = 342,
SREM = 343,
FREM = 344,
AND = 345,
OR = 346,
XOR = 347,
SHL = 348,
SHR = 349,
ASHR = 350,
LSHR = 351,
SETLE = 352,
SETGE = 353,
SETLT = 354,
SETGT = 355,
SETEQ = 356,
SETNE = 357,
ICMP = 358,
FCMP = 359,
MALLOC = 360,
ALLOCA = 361,
FREE = 362,
LOAD = 363,
STORE = 364,
GETELEMENTPTR = 365,
PHI_TOK = 366,
SELECT = 367,
VAARG = 368,
EXTRACTELEMENT = 369,
INSERTELEMENT = 370,
SHUFFLEVECTOR = 371,
VAARG_old = 372,
VANEXT_old = 373,
EQ = 374,
NE = 375,
SLT = 376,
SGT = 377,
SLE = 378,
SGE = 379,
ULT = 380,
UGT = 381,
ULE = 382,
UGE = 383,
OEQ = 384,
ONE = 385,
OLT = 386,
OGT = 387,
OLE = 388,
OGE = 389,
ORD = 390,
UNO = 391,
UEQ = 392,
UNE = 393,
CAST = 394,
TRUNC = 395,
ZEXT = 396,
SEXT = 397,
FPTRUNC = 398,
FPEXT = 399,
FPTOUI = 400,
FPTOSI = 401,
UITOFP = 402,
SITOFP = 403,
PTRTOINT = 404,
INTTOPTR = 405,
BITCAST = 406
};
#endif
/* Tokens. */
#define ESINT64VAL 258
#define EUINT64VAL 259
#define SINTVAL 260
#define UINTVAL 261
#define FPVAL 262
#define VOID 263
#define BOOL 264
#define SBYTE 265
#define UBYTE 266
#define SHORT 267
#define USHORT 268
#define INT 269
#define UINT 270
#define LONG 271
#define ULONG 272
#define FLOAT 273
#define DOUBLE 274
#define TYPE 275
#define LABEL 276
#define VAR_ID 277
#define LABELSTR 278
#define STRINGCONSTANT 279
#define IMPLEMENTATION 280
#define ZEROINITIALIZER 281
#define TRUETOK 282
#define FALSETOK 283
#define BEGINTOK 284
#define ENDTOK 285
#define DECLARE 286
#define GLOBAL 287
#define CONSTANT 288
#define SECTION 289
#define VOLATILE 290
#define TO 291
#define DOTDOTDOT 292
#define NULL_TOK 293
#define UNDEF 294
#define CONST 295
#define INTERNAL 296
#define LINKONCE 297
#define WEAK 298
#define APPENDING 299
#define DLLIMPORT 300
#define DLLEXPORT 301
#define EXTERN_WEAK 302
#define OPAQUE 303
#define NOT 304
#define EXTERNAL 305
#define TARGET 306
#define TRIPLE 307
#define ENDIAN 308
#define POINTERSIZE 309
#define LITTLE 310
#define BIG 311
#define ALIGN 312
#define DEPLIBS 313
#define CALL 314
#define TAIL 315
#define ASM_TOK 316
#define MODULE 317
#define SIDEEFFECT 318
#define CC_TOK 319
#define CCC_TOK 320
#define CSRETCC_TOK 321
#define FASTCC_TOK 322
#define COLDCC_TOK 323
#define X86_STDCALLCC_TOK 324
#define X86_FASTCALLCC_TOK 325
#define DATALAYOUT 326
#define RET 327
#define BR 328
#define SWITCH 329
#define INVOKE 330
#define UNREACHABLE 331
#define UNWIND 332
#define EXCEPT 333
#define ADD 334
#define SUB 335
#define MUL 336
#define DIV 337
#define UDIV 338
#define SDIV 339
#define FDIV 340
#define REM 341
#define UREM 342
#define SREM 343
#define FREM 344
#define AND 345
#define OR 346
#define XOR 347
#define SHL 348
#define SHR 349
#define ASHR 350
#define LSHR 351
#define SETLE 352
#define SETGE 353
#define SETLT 354
#define SETGT 355
#define SETEQ 356
#define SETNE 357
#define ICMP 358
#define FCMP 359
#define MALLOC 360
#define ALLOCA 361
#define FREE 362
#define LOAD 363
#define STORE 364
#define GETELEMENTPTR 365
#define PHI_TOK 366
#define SELECT 367
#define VAARG 368
#define EXTRACTELEMENT 369
#define INSERTELEMENT 370
#define SHUFFLEVECTOR 371
#define VAARG_old 372
#define VANEXT_old 373
#define EQ 374
#define NE 375
#define SLT 376
#define SGT 377
#define SLE 378
#define SGE 379
#define ULT 380
#define UGT 381
#define ULE 382
#define UGE 383
#define OEQ 384
#define ONE 385
#define OLT 386
#define OGT 387
#define OLE 388
#define OGE 389
#define ORD 390
#define UNO 391
#define UEQ 392
#define UNE 393
#define CAST 394
#define TRUNC 395
#define ZEXT 396
#define SEXT 397
#define FPTRUNC 398
#define FPEXT 399
#define FPTOUI 400
#define FPTOSI 401
#define UITOFP 402
#define SITOFP 403
#define PTRTOINT 404
#define INTTOPTR 405
#define BITCAST 406
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
#line 1680 "/home/duncan/LLVM/llvm.top/llvm/tools/llvm-upgrade/UpgradeParser.y"
{
llvm::Module *ModuleVal;
llvm::Function *FunctionVal;
std::pair<llvm::PATypeInfo, char*> *ArgVal;
@ -38,156 +387,14 @@ typedef union {
llvm::ICmpInst::Predicate IPred;
llvm::FCmpInst::Predicate FPred;
llvm::Module::Endianness Endianness;
} YYSTYPE;
#define ESINT64VAL 257
#define EUINT64VAL 258
#define SINTVAL 259
#define UINTVAL 260
#define FPVAL 261
#define VOID 262
#define BOOL 263
#define SBYTE 264
#define UBYTE 265
#define SHORT 266
#define USHORT 267
#define INT 268
#define UINT 269
#define LONG 270
#define ULONG 271
#define FLOAT 272
#define DOUBLE 273
#define TYPE 274
#define LABEL 275
#define VAR_ID 276
#define LABELSTR 277
#define STRINGCONSTANT 278
#define IMPLEMENTATION 279
#define ZEROINITIALIZER 280
#define TRUETOK 281
#define FALSETOK 282
#define BEGINTOK 283
#define ENDTOK 284
#define DECLARE 285
#define GLOBAL 286
#define CONSTANT 287
#define SECTION 288
#define VOLATILE 289
#define TO 290
#define DOTDOTDOT 291
#define NULL_TOK 292
#define UNDEF 293
#define CONST 294
#define INTERNAL 295
#define LINKONCE 296
#define WEAK 297
#define APPENDING 298
#define DLLIMPORT 299
#define DLLEXPORT 300
#define EXTERN_WEAK 301
#define OPAQUE 302
#define NOT 303
#define EXTERNAL 304
#define TARGET 305
#define TRIPLE 306
#define ENDIAN 307
#define POINTERSIZE 308
#define LITTLE 309
#define BIG 310
#define ALIGN 311
#define DEPLIBS 312
#define CALL 313
#define TAIL 314
#define ASM_TOK 315
#define MODULE 316
#define SIDEEFFECT 317
#define CC_TOK 318
#define CCC_TOK 319
#define CSRETCC_TOK 320
#define FASTCC_TOK 321
#define COLDCC_TOK 322
#define X86_STDCALLCC_TOK 323
#define X86_FASTCALLCC_TOK 324
#define DATALAYOUT 325
#define RET 326
#define BR 327
#define SWITCH 328
#define INVOKE 329
#define UNREACHABLE 330
#define UNWIND 331
#define EXCEPT 332
#define ADD 333
#define SUB 334
#define MUL 335
#define DIV 336
#define UDIV 337
#define SDIV 338
#define FDIV 339
#define REM 340
#define UREM 341
#define SREM 342
#define FREM 343
#define AND 344
#define OR 345
#define XOR 346
#define SHL 347
#define SHR 348
#define ASHR 349
#define LSHR 350
#define SETLE 351
#define SETGE 352
#define SETLT 353
#define SETGT 354
#define SETEQ 355
#define SETNE 356
#define ICMP 357
#define FCMP 358
#define MALLOC 359
#define ALLOCA 360
#define FREE 361
#define LOAD 362
#define STORE 363
#define GETELEMENTPTR 364
#define PHI_TOK 365
#define SELECT 366
#define VAARG 367
#define EXTRACTELEMENT 368
#define INSERTELEMENT 369
#define SHUFFLEVECTOR 370
#define VAARG_old 371
#define VANEXT_old 372
#define EQ 373
#define NE 374
#define SLT 375
#define SGT 376
#define SLE 377
#define SGE 378
#define ULT 379
#define UGT 380
#define ULE 381
#define UGE 382
#define OEQ 383
#define ONE 384
#define OLT 385
#define OGT 386
#define OLE 387
#define OGE 388
#define ORD 389
#define UNO 390
#define UEQ 391
#define UNE 392
#define CAST 393
#define TRUNC 394
#define ZEXT 395
#define SEXT 396
#define FPTRUNC 397
#define FPEXT 398
#define FPTOUI 399
#define FPTOSI 400
#define UITOFP 401
#define SITOFP 402
#define PTRTOINT 403
#define INTTOPTR 404
#define BITCAST 405
}
/* Line 1489 of yacc.c. */
#line 393 "UpgradeParser.tab.h"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1
#endif
extern YYSTYPE Upgradelval;

View File

@ -373,78 +373,6 @@ static Signedness getElementSign(const ConstInfo& CI,
return result;
}
/// This function determines if two function types differ only in their use of
/// the sret parameter attribute in the first argument. If they are identical
/// in all other respects, it returns true. Otherwise, it returns false.
static bool FuncTysDifferOnlyBySRet(const FunctionType *F1,
const FunctionType *F2) {
if (F1->getReturnType() != F2->getReturnType() ||
F1->getNumParams() != F2->getNumParams())
return false;
const ParamAttrsList *PAL1 = F1->getParamAttrs();
const ParamAttrsList *PAL2 = F2->getParamAttrs();
if (PAL1 && !PAL2 || PAL2 && !PAL1)
return false;
if (PAL1 && PAL2 && ((PAL1->size() != PAL2->size()) ||
(PAL1->getParamAttrs(0) != PAL2->getParamAttrs(0))))
return false;
unsigned SRetMask = ~unsigned(ParamAttr::StructRet);
for (unsigned i = 0; i < F1->getNumParams(); ++i) {
if (F1->getParamType(i) != F2->getParamType(i) || (PAL1 && PAL2 &&
(unsigned(PAL1->getParamAttrs(i+1)) & SRetMask !=
unsigned(PAL2->getParamAttrs(i+1)) & SRetMask)))
return false;
}
return true;
}
/// This function determines if the type of V and Ty differ only by the SRet
/// parameter attribute. This is a more generalized case of
/// FuncTysDIfferOnlyBySRet since it doesn't require FunctionType arguments.
static bool TypesDifferOnlyBySRet(Value *V, const Type* Ty) {
if (V->getType() == Ty)
return true;
const PointerType *PF1 = dyn_cast<PointerType>(Ty);
const PointerType *PF2 = dyn_cast<PointerType>(V->getType());
if (PF1 && PF2) {
const FunctionType* FT1 = dyn_cast<FunctionType>(PF1->getElementType());
const FunctionType* FT2 = dyn_cast<FunctionType>(PF2->getElementType());
if (FT1 && FT2)
return FuncTysDifferOnlyBySRet(FT1, FT2);
}
return false;
}
// The upgrade of csretcc to sret param attribute may have caused a function
// to not be found because the param attribute changed the type of the called
// function. This helper function, used in getExistingValue, detects that
// situation and bitcasts the function to the correct type.
static Value* handleSRetFuncTypeMerge(Value *V, const Type* Ty) {
// Handle degenerate cases
if (!V)
return 0;
if (V->getType() == Ty)
return V;
const PointerType *PF1 = dyn_cast<PointerType>(Ty);
const PointerType *PF2 = dyn_cast<PointerType>(V->getType());
if (PF1 && PF2) {
const FunctionType *FT1 = dyn_cast<FunctionType>(PF1->getElementType());
const FunctionType *FT2 = dyn_cast<FunctionType>(PF2->getElementType());
if (FT1 && FT2 && FuncTysDifferOnlyBySRet(FT1, FT2)) {
const ParamAttrsList *PAL2 = FT2->getParamAttrs();
if (PAL2 && PAL2->paramHasAttr(1, ParamAttr::StructRet))
return V;
else if (Constant *C = dyn_cast<Constant>(V))
return ConstantExpr::getBitCast(C, PF1);
else
return new BitCastInst(V, PF1, "upgrd.cast", CurBB);
}
}
return 0;
}
// getExistingValue - Look up the value specified by the provided type and
// the provided ValID. If the value exists and has already been defined, return
// it. Otherwise return null.
@ -491,8 +419,7 @@ static Value *getExistingValue(const Type *Ty, const ValID &D) {
ValueSymbolTable &SymTab = CurFun.CurrentFunction->getValueSymbolTable();
V = SymTab.lookup(LookupName);
if (V && V->getType() != Ty)
V = handleSRetFuncTypeMerge(V, Ty);
assert((!V || TypesDifferOnlyBySRet(V, Ty)) && "Found wrong type");
V = 0;
}
if (!V) {
RenameMapType::const_iterator I = CurModule.RenameMap.find(Key);
@ -503,8 +430,7 @@ static Value *getExistingValue(const Type *Ty, const ValID &D) {
LookupName = D.Name;
V = CurModule.CurrentModule->getValueSymbolTable().lookup(LookupName);
if (V && V->getType() != Ty)
V = handleSRetFuncTypeMerge(V, Ty);
assert((!V || TypesDifferOnlyBySRet(V, Ty)) && "Found wrong type");
V = 0;
}
if (!V)
return 0;
@ -2139,7 +2065,7 @@ UpRTypes
}
const FunctionType *FTy =
FunctionType::get($1.PAT->get(), Params, isVarArg, PAL);
FunctionType::get($1.PAT->get(), Params, isVarArg);
$$.PAT = new PATypeHolder( HandleUpRefs(FTy, $$.S) );
delete $1.PAT; // Delete the return type handle
@ -2925,19 +2851,7 @@ FunctionHeaderH
if (isVarArg)
ParamTyList.pop_back();
// Convert the CSRet calling convention into the corresponding parameter
// attribute.
ParamAttrsList *PAL = 0;
if ($1 == OldCallingConv::CSRet) {
ParamAttrsVector Attrs;
ParamAttrsWithIndex PAWI;
PAWI.index = 1; PAWI.attrs = ParamAttr::StructRet; // first arg
Attrs.push_back(PAWI);
PAL = ParamAttrsList::get(Attrs);
}
const FunctionType *FT =
FunctionType::get(RetTy, ParamTyList, isVarArg, PAL);
const FunctionType *FT = FunctionType::get(RetTy, ParamTyList, isVarArg);
const PointerType *PFT = PointerType::get(FT);
delete $2.PAT;
@ -3055,6 +2969,16 @@ FunctionHeaderH
free($7);
}
// Convert the CSRet calling convention into the corresponding parameter
// attribute.
if ($1 == OldCallingConv::CSRet) {
ParamAttrsVector Attrs;
ParamAttrsWithIndex PAWI;
PAWI.index = 1; PAWI.attrs = ParamAttr::StructRet; // first arg
Attrs.push_back(PAWI);
Fn->setParamAttrs(ParamAttrsList::get(Attrs));
}
// Add all of the arguments we parsed to the function...
if ($5) { // Is null if empty...
if (isVarArg) { // Nuke the last entry
@ -3324,17 +3248,9 @@ BBTerminatorInst
FTySign.add(I->S);
}
}
ParamAttrsList *PAL = 0;
if ($2 == OldCallingConv::CSRet) {
ParamAttrsVector Attrs;
ParamAttrsWithIndex PAWI;
PAWI.index = 1; PAWI.attrs = ParamAttr::StructRet; // first arg
Attrs.push_back(PAWI);
PAL = ParamAttrsList::get(Attrs);
}
bool isVarArg = ParamTypes.size() && ParamTypes.back() == Type::VoidTy;
if (isVarArg) ParamTypes.pop_back();
Ty = FunctionType::get($3.PAT->get(), ParamTypes, isVarArg, PAL);
Ty = FunctionType::get($3.PAT->get(), ParamTypes, isVarArg);
PFTy = PointerType::get(Ty);
$$.S.copy($3.S);
} else {
@ -3376,6 +3292,13 @@ BBTerminatorInst
$$.TI = new InvokeInst(V, Normal, Except, Args.begin(), Args.end());
}
cast<InvokeInst>($$.TI)->setCallingConv(upgradeCallingConv($2));
if ($2 == OldCallingConv::CSRet) {
ParamAttrsVector Attrs;
ParamAttrsWithIndex PAWI;
PAWI.index = 1; PAWI.attrs = ParamAttr::StructRet; // first arg
Attrs.push_back(PAWI);
cast<InvokeInst>($$.TI)->setParamAttrs(ParamAttrsList::get(Attrs));
}
delete $3.PAT;
delete $6;
lastCallingConv = OldCallingConv::C;
@ -3732,17 +3655,7 @@ InstVal
if (!RetTy->isFirstClassType() && RetTy != Type::VoidTy)
error("Functions cannot return aggregate types");
// Deal with CSRetCC
ParamAttrsList *PAL = 0;
if ($2 == OldCallingConv::CSRet) {
ParamAttrsVector Attrs;
ParamAttrsWithIndex PAWI;
PAWI.index = 1; PAWI.attrs = ParamAttr::StructRet; // first arg
Attrs.push_back(PAWI);
PAL = ParamAttrsList::get(Attrs);
}
FTy = FunctionType::get(RetTy, ParamTypes, isVarArg, PAL);
FTy = FunctionType::get(RetTy, ParamTypes, isVarArg);
PFTy = PointerType::get(FTy);
$$.S.copy($3.S);
} else {
@ -3794,8 +3707,17 @@ InstVal
CallInst *CI = new CallInst(V, Args.begin(), Args.end());
CI->setTailCall($1);
CI->setCallingConv(upgradeCallingConv($2));
$$.I = CI;
}
// Deal with CSRetCC
if ($2 == OldCallingConv::CSRet) {
ParamAttrsVector Attrs;
ParamAttrsWithIndex PAWI;
PAWI.index = 1; PAWI.attrs = ParamAttr::StructRet; // first arg
Attrs.push_back(PAWI);
cast<CallInst>($$.I)->setParamAttrs(ParamAttrsList::get(Attrs));
}
delete $3.PAT;
delete $6;
lastCallingConv = OldCallingConv::C;
@ -3874,17 +3796,11 @@ MemoryInst
Value *StoreVal = $3.V;
Value* tmpVal = getVal(PTy, $6);
if (ElTy != $3.V->getType()) {
StoreVal = handleSRetFuncTypeMerge($3.V, ElTy);
if (!StoreVal)
error("Can't store '" + $3.V->getType()->getDescription() +
"' into space of type '" + ElTy->getDescription() + "'");
else {
PTy = PointerType::get(StoreVal->getType());
if (Constant *C = dyn_cast<Constant>(tmpVal))
tmpVal = ConstantExpr::getBitCast(C, PTy);
else
tmpVal = new BitCastInst(tmpVal, PTy, "upgrd.cast", CurBB);
}
PTy = PointerType::get(StoreVal->getType());
if (Constant *C = dyn_cast<Constant>(tmpVal))
tmpVal = ConstantExpr::getBitCast(C, PTy);
else
tmpVal = new BitCastInst(tmpVal, PTy, "upgrd.cast", CurBB);
}
$$.I = new StoreInst(StoreVal, tmpVal, $1);
$$.S.makeSignless();

View File

@ -373,78 +373,6 @@ static Signedness getElementSign(const ConstInfo& CI,
return result;
}
/// This function determines if two function types differ only in their use of
/// the sret parameter attribute in the first argument. If they are identical
/// in all other respects, it returns true. Otherwise, it returns false.
static bool FuncTysDifferOnlyBySRet(const FunctionType *F1,
const FunctionType *F2) {
if (F1->getReturnType() != F2->getReturnType() ||
F1->getNumParams() != F2->getNumParams())
return false;
const ParamAttrsList *PAL1 = F1->getParamAttrs();
const ParamAttrsList *PAL2 = F2->getParamAttrs();
if (PAL1 && !PAL2 || PAL2 && !PAL1)
return false;
if (PAL1 && PAL2 && ((PAL1->size() != PAL2->size()) ||
(PAL1->getParamAttrs(0) != PAL2->getParamAttrs(0))))
return false;
unsigned SRetMask = ~unsigned(ParamAttr::StructRet);
for (unsigned i = 0; i < F1->getNumParams(); ++i) {
if (F1->getParamType(i) != F2->getParamType(i) || (PAL1 && PAL2 &&
(unsigned(PAL1->getParamAttrs(i+1)) & SRetMask !=
unsigned(PAL2->getParamAttrs(i+1)) & SRetMask)))
return false;
}
return true;
}
/// This function determines if the type of V and Ty differ only by the SRet
/// parameter attribute. This is a more generalized case of
/// FuncTysDIfferOnlyBySRet since it doesn't require FunctionType arguments.
static bool TypesDifferOnlyBySRet(Value *V, const Type* Ty) {
if (V->getType() == Ty)
return true;
const PointerType *PF1 = dyn_cast<PointerType>(Ty);
const PointerType *PF2 = dyn_cast<PointerType>(V->getType());
if (PF1 && PF2) {
const FunctionType* FT1 = dyn_cast<FunctionType>(PF1->getElementType());
const FunctionType* FT2 = dyn_cast<FunctionType>(PF2->getElementType());
if (FT1 && FT2)
return FuncTysDifferOnlyBySRet(FT1, FT2);
}
return false;
}
// The upgrade of csretcc to sret param attribute may have caused a function
// to not be found because the param attribute changed the type of the called
// function. This helper function, used in getExistingValue, detects that
// situation and bitcasts the function to the correct type.
static Value* handleSRetFuncTypeMerge(Value *V, const Type* Ty) {
// Handle degenerate cases
if (!V)
return 0;
if (V->getType() == Ty)
return V;
const PointerType *PF1 = dyn_cast<PointerType>(Ty);
const PointerType *PF2 = dyn_cast<PointerType>(V->getType());
if (PF1 && PF2) {
const FunctionType *FT1 = dyn_cast<FunctionType>(PF1->getElementType());
const FunctionType *FT2 = dyn_cast<FunctionType>(PF2->getElementType());
if (FT1 && FT2 && FuncTysDifferOnlyBySRet(FT1, FT2)) {
const ParamAttrsList *PAL2 = FT2->getParamAttrs();
if (PAL2 && PAL2->paramHasAttr(1, ParamAttr::StructRet))
return V;
else if (Constant *C = dyn_cast<Constant>(V))
return ConstantExpr::getBitCast(C, PF1);
else
return new BitCastInst(V, PF1, "upgrd.cast", CurBB);
}
}
return 0;
}
// getExistingValue - Look up the value specified by the provided type and
// the provided ValID. If the value exists and has already been defined, return
// it. Otherwise return null.
@ -491,8 +419,7 @@ static Value *getExistingValue(const Type *Ty, const ValID &D) {
ValueSymbolTable &SymTab = CurFun.CurrentFunction->getValueSymbolTable();
V = SymTab.lookup(LookupName);
if (V && V->getType() != Ty)
V = handleSRetFuncTypeMerge(V, Ty);
assert((!V || TypesDifferOnlyBySRet(V, Ty)) && "Found wrong type");
V = 0;
}
if (!V) {
RenameMapType::const_iterator I = CurModule.RenameMap.find(Key);
@ -503,8 +430,7 @@ static Value *getExistingValue(const Type *Ty, const ValID &D) {
LookupName = D.Name;
V = CurModule.CurrentModule->getValueSymbolTable().lookup(LookupName);
if (V && V->getType() != Ty)
V = handleSRetFuncTypeMerge(V, Ty);
assert((!V || TypesDifferOnlyBySRet(V, Ty)) && "Found wrong type");
V = 0;
}
if (!V)
return 0;
@ -2139,7 +2065,7 @@ UpRTypes
}
const FunctionType *FTy =
FunctionType::get($1.PAT->get(), Params, isVarArg, PAL);
FunctionType::get($1.PAT->get(), Params, isVarArg);
$$.PAT = new PATypeHolder( HandleUpRefs(FTy, $$.S) );
delete $1.PAT; // Delete the return type handle
@ -2925,19 +2851,7 @@ FunctionHeaderH
if (isVarArg)
ParamTyList.pop_back();
// Convert the CSRet calling convention into the corresponding parameter
// attribute.
ParamAttrsList *PAL = 0;
if ($1 == OldCallingConv::CSRet) {
ParamAttrsVector Attrs;
ParamAttrsWithIndex PAWI;
PAWI.index = 1; PAWI.attrs = ParamAttr::StructRet; // first arg
Attrs.push_back(PAWI);
PAL = ParamAttrsList::get(Attrs);
}
const FunctionType *FT =
FunctionType::get(RetTy, ParamTyList, isVarArg, PAL);
const FunctionType *FT = FunctionType::get(RetTy, ParamTyList, isVarArg);
const PointerType *PFT = PointerType::get(FT);
delete $2.PAT;
@ -3055,6 +2969,16 @@ FunctionHeaderH
free($7);
}
// Convert the CSRet calling convention into the corresponding parameter
// attribute.
if ($1 == OldCallingConv::CSRet) {
ParamAttrsVector Attrs;
ParamAttrsWithIndex PAWI;
PAWI.index = 1; PAWI.attrs = ParamAttr::StructRet; // first arg
Attrs.push_back(PAWI);
Fn->setParamAttrs(ParamAttrsList::get(Attrs));
}
// Add all of the arguments we parsed to the function...
if ($5) { // Is null if empty...
if (isVarArg) { // Nuke the last entry
@ -3324,17 +3248,9 @@ BBTerminatorInst
FTySign.add(I->S);
}
}
ParamAttrsList *PAL = 0;
if ($2 == OldCallingConv::CSRet) {
ParamAttrsVector Attrs;
ParamAttrsWithIndex PAWI;
PAWI.index = 1; PAWI.attrs = ParamAttr::StructRet; // first arg
Attrs.push_back(PAWI);
PAL = ParamAttrsList::get(Attrs);
}
bool isVarArg = ParamTypes.size() && ParamTypes.back() == Type::VoidTy;
if (isVarArg) ParamTypes.pop_back();
Ty = FunctionType::get($3.PAT->get(), ParamTypes, isVarArg, PAL);
Ty = FunctionType::get($3.PAT->get(), ParamTypes, isVarArg);
PFTy = PointerType::get(Ty);
$$.S.copy($3.S);
} else {
@ -3376,6 +3292,13 @@ BBTerminatorInst
$$.TI = new InvokeInst(V, Normal, Except, Args.begin(), Args.end());
}
cast<InvokeInst>($$.TI)->setCallingConv(upgradeCallingConv($2));
if ($2 == OldCallingConv::CSRet) {
ParamAttrsVector Attrs;
ParamAttrsWithIndex PAWI;
PAWI.index = 1; PAWI.attrs = ParamAttr::StructRet; // first arg
Attrs.push_back(PAWI);
cast<InvokeInst>($$.TI)->setParamAttrs(ParamAttrsList::get(Attrs));
}
delete $3.PAT;
delete $6;
lastCallingConv = OldCallingConv::C;
@ -3732,17 +3655,7 @@ InstVal
if (!RetTy->isFirstClassType() && RetTy != Type::VoidTy)
error("Functions cannot return aggregate types");
// Deal with CSRetCC
ParamAttrsList *PAL = 0;
if ($2 == OldCallingConv::CSRet) {
ParamAttrsVector Attrs;
ParamAttrsWithIndex PAWI;
PAWI.index = 1; PAWI.attrs = ParamAttr::StructRet; // first arg
Attrs.push_back(PAWI);
PAL = ParamAttrsList::get(Attrs);
}
FTy = FunctionType::get(RetTy, ParamTypes, isVarArg, PAL);
FTy = FunctionType::get(RetTy, ParamTypes, isVarArg);
PFTy = PointerType::get(FTy);
$$.S.copy($3.S);
} else {
@ -3794,8 +3707,17 @@ InstVal
CallInst *CI = new CallInst(V, Args.begin(), Args.end());
CI->setTailCall($1);
CI->setCallingConv(upgradeCallingConv($2));
$$.I = CI;
}
// Deal with CSRetCC
if ($2 == OldCallingConv::CSRet) {
ParamAttrsVector Attrs;
ParamAttrsWithIndex PAWI;
PAWI.index = 1; PAWI.attrs = ParamAttr::StructRet; // first arg
Attrs.push_back(PAWI);
cast<CallInst>($$.I)->setParamAttrs(ParamAttrsList::get(Attrs));
}
delete $3.PAT;
delete $6;
lastCallingConv = OldCallingConv::C;
@ -3874,17 +3796,11 @@ MemoryInst
Value *StoreVal = $3.V;
Value* tmpVal = getVal(PTy, $6);
if (ElTy != $3.V->getType()) {
StoreVal = handleSRetFuncTypeMerge($3.V, ElTy);
if (!StoreVal)
error("Can't store '" + $3.V->getType()->getDescription() +
"' into space of type '" + ElTy->getDescription() + "'");
else {
PTy = PointerType::get(StoreVal->getType());
if (Constant *C = dyn_cast<Constant>(tmpVal))
tmpVal = ConstantExpr::getBitCast(C, PTy);
else
tmpVal = new BitCastInst(tmpVal, PTy, "upgrd.cast", CurBB);
}
PTy = PointerType::get(StoreVal->getType());
if (Constant *C = dyn_cast<Constant>(tmpVal))
tmpVal = ConstantExpr::getBitCast(C, PTy);
else
tmpVal = new BitCastInst(tmpVal, PTy, "upgrd.cast", CurBB);
}
$$.I = new StoreInst(StoreVal, tmpVal, $1);
$$.S.makeSignless();

View File

@ -114,6 +114,7 @@ public:
private:
void printLinkageType(GlobalValue::LinkageTypes LT);
void printVisibilityType(GlobalValue::VisibilityTypes VisTypes);
void printCallingConv(unsigned cc);
void printEscapedString(const std::string& str);
void printCFP(const ConstantFP* CFP);
@ -124,6 +125,7 @@ private:
std::string getCppName(const Value* val);
inline void printCppName(const Value* val);
void printParamAttrs(const ParamAttrsList* PAL, const std::string &name);
bool printTypeInternal(const Type* Ty);
inline void printType(const Type* Ty);
void printTypes(const Module* M);
@ -302,6 +304,22 @@ CppWriter::printLinkageType(GlobalValue::LinkageTypes LT) {
}
}
void
CppWriter::printVisibilityType(GlobalValue::VisibilityTypes VisType) {
switch (VisType) {
default: assert(0 && "Unknown GVar visibility");
case GlobalValue::DefaultVisibility:
Out << "GlobalValue::DefaultVisibility";
break;
case GlobalValue::HiddenVisibility:
Out << "GlobalValue::HiddenVisibility";
break;
case GlobalValue::ProtectedVisibility:
Out << "GlobalValue::ProtectedVisibility";
break;
}
}
// printEscapedString - Print each character of the specified string, escaping
// it if it is not printable or if it is an escape char.
void
@ -419,6 +437,42 @@ CppWriter::printCppName(const Value* val) {
printEscapedString(getCppName(val));
}
void
CppWriter::printParamAttrs(const ParamAttrsList* PAL, const std::string &name) {
Out << "ParamAttrsList *" << name << "_PAL = 0;";
nl(Out);
if (PAL) {
Out << '{'; in(); nl(Out);
Out << "ParamAttrsVector Attrs;"; nl(Out);
Out << "ParamAttrsWithIndex PAWI;"; nl(Out);
for (unsigned i = 0; i < PAL->size(); ++i) {
uint16_t index = PAL->getParamIndex(i);
uint16_t attrs = PAL->getParamAttrs(index);
Out << "PAWI.index = " << index << "; PAWI.attrs = 0 ";
if (attrs & ParamAttr::SExt)
Out << " | ParamAttr::SExt";
if (attrs & ParamAttr::ZExt)
Out << " | ParamAttr::ZExt";
if (attrs & ParamAttr::StructRet)
Out << " | ParamAttr::StructRet";
if (attrs & ParamAttr::InReg)
Out << " | ParamAttr::InReg";
if (attrs & ParamAttr::NoReturn)
Out << " | ParamAttr::NoReturn";
if (attrs & ParamAttr::NoUnwind)
Out << " | ParamAttr::NoUnwind";
Out << ";";
nl(Out);
Out << "Attrs.push_back(PAWI);";
nl(Out);
}
Out << name << "_PAL = ParamAttrsList::get(Attrs);";
nl(Out);
out(); nl(Out);
Out << '}'; nl(Out);
}
}
bool
CppWriter::printTypeInternal(const Type* Ty) {
// We don't print definitions for primitive types
@ -471,41 +525,6 @@ CppWriter::printTypeInternal(const Type* Ty) {
Out << ");";
nl(Out);
}
const ParamAttrsList *PAL = FT->getParamAttrs();
Out << "ParamAttrsList *" << typeName << "_PAL = 0;";
nl(Out);
if (PAL) {
Out << '{'; in(); nl(Out);
Out << "ParamAttrsVector Attrs;"; nl(Out);
Out << "ParamAttrsWithIndex PAWI;"; nl(Out);
for (unsigned i = 0; i < PAL->size(); ++i) {
uint16_t index = PAL->getParamIndex(i);
uint16_t attrs = PAL->getParamAttrs(index);
Out << "PAWI.index = " << index << "; PAWI.attrs = 0 ";
if (attrs & ParamAttr::SExt)
Out << " | ParamAttr::SExt";
if (attrs & ParamAttr::ZExt)
Out << " | ParamAttr::ZExt";
if (attrs & ParamAttr::NoAlias)
Out << " | ParamAttr::NoAlias";
if (attrs & ParamAttr::StructRet)
Out << " | ParamAttr::StructRet";
if (attrs & ParamAttr::InReg)
Out << " | ParamAttr::InReg";
if (attrs & ParamAttr::NoReturn)
Out << " | ParamAttr::NoReturn";
if (attrs & ParamAttr::NoUnwind)
Out << " | ParamAttr::NoUnwind";
Out << ";";
nl(Out);
Out << "Attrs.push_back(PAWI);";
nl(Out);
}
Out << typeName << "_PAL = ParamAttrsList::get(Attrs);";
nl(Out);
out(); nl(Out);
Out << '}'; nl(Out);
}
bool isForward = printTypeInternal(FT->getReturnType());
std::string retTypeName(getCppName(FT->getReturnType()));
Out << "FunctionType* " << typeName << " = FunctionType::get(";
@ -514,8 +533,7 @@ CppWriter::printTypeInternal(const Type* Ty) {
Out << "_fwd";
Out << ",";
nl(Out) << "/*Params=*/" << typeName << "_args,";
nl(Out) << "/*isVarArg=*/" << (FT->isVarArg() ? "true," : "false,") ;
nl(Out) << "/*ParamAttrs=*/" << typeName << "_PAL" << ");";
nl(Out) << "/*isVarArg=*/" << (FT->isVarArg() ? "true" : "false") << ");";
out();
nl(Out);
break;
@ -992,6 +1010,13 @@ void CppWriter::printVariableHead(const GlobalVariable *GV) {
Out << "->setAlignment(" << utostr(GV->getAlignment()) << ");";
nl(Out);
};
if (GV->getVisibility() != GlobalValue::DefaultVisibility) {
printCppName(GV);
Out << "->setVisibility(";
printVisibilityType(GV->getVisibility());
Out << ");";
nl(Out);
}
if (is_inline) {
out(); Out << "}"; nl(Out);
}
@ -1102,6 +1127,9 @@ CppWriter::printInstruction(const Instruction *I, const std::string& bbname) {
nl(Out) << iName << "->setCallingConv(";
printCallingConv(inv->getCallingConv());
Out << ");";
printParamAttrs(inv->getParamAttrs(), iName);
Out << iName << "->setParamAttrs(" << iName << "_PAL);";
nl(Out);
break;
}
case Instruction::Unwind: {
@ -1362,6 +1390,9 @@ CppWriter::printInstruction(const Instruction *I, const std::string& bbname) {
nl(Out) << iName << "->setTailCall("
<< (call->isTailCall() ? "true":"false");
Out << ");";
printParamAttrs(call->getParamAttrs(), iName);
Out << iName << "->setParamAttrs(" << iName << "_PAL);";
nl(Out);
break;
}
case Instruction::Select: {
@ -1533,10 +1564,21 @@ void CppWriter::printFunctionHead(const Function* F) {
Out << "->setAlignment(" << F->getAlignment() << ");";
nl(Out);
}
if (F->getVisibility() != GlobalValue::DefaultVisibility) {
printCppName(F);
Out << "->setVisibility(";
printVisibilityType(F->getVisibility());
Out << ");";
nl(Out);
}
if (is_inline) {
Out << "}";
nl(Out);
}
printParamAttrs(F->getParamAttrs(), getCppName(F));
printCppName(F);
Out << "->setParamAttrs(" << getCppName(F) << "_PAL);";
nl(Out);
}
void CppWriter::printFunctionBody(const Function *F) {