Change the syntax for parameter attributes:

1. The @ sign is no longer necessary.
2. We now support "function attributes" as parameter attribute 0.
3. Instead of locating the return type attributes after the type of a
   function result, they are now located after the function header's
   closing paranthesis and before any alignment or section options.
4. The way has been prepared for a new "noreturn" function attribute but
   there is no support for recognizing it in the lexer nor doing anything
   with it if it does get set.
5. The FunctionType::getParamAttrsText method now has support for
   returning multiple attributes. This required a change in its interface.

I'm unhappy that this change leads to 6 new shift/reduce conflicts, but
in each case bison's decision to choose the shift is correct so there
shouldn't be any damage from these conflicts.

llvm-svn: 32904
This commit is contained in:
Reid Spencer 2007-01-05 17:06:19 +00:00
parent edd3ad549a
commit 136a91c4e7
4 changed files with 84 additions and 76 deletions

View File

@ -81,9 +81,10 @@ public:
/// set of possible attributes. /// set of possible attributes.
/// @brief Function parameter attributes enumeration. /// @brief Function parameter attributes enumeration.
enum ParameterAttributes { enum ParameterAttributes {
NoAttributeSet = 0, ///< No attribute value has been set on the parameter NoAttributeSet = 0, ///< No attribute value has been set
ZExtAttribute = 1, ///< The parameter should be zero extended before call ZExtAttribute = 1, ///< zero extended before/after call
SExtAttribute = 2 ///< The parameter should be sign extended before call SExtAttribute = 1 << 1, ///< sign extended before/after call
NoReturnAttribute = 1 << 2 ///< mark the function as not returning
}; };
typedef std::vector<ParameterAttributes> ParamAttrsList; typedef std::vector<ParameterAttributes> ParamAttrsList;
private: private:
@ -142,7 +143,7 @@ public:
} }
/// @brief Convert a ParameterAttribute into its assembly text /// @brief Convert a ParameterAttribute into its assembly text
static const char * getParamAttrsText(ParameterAttributes Attr); static std::string getParamAttrsText(ParameterAttributes Attr);
// Implement the AbstractTypeUser interface. // Implement the AbstractTypeUser interface.
virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);

View File

@ -951,7 +951,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
%type <ValueList> IndexList // For GEP indices %type <ValueList> IndexList // For GEP indices
%type <TypeList> TypeListI %type <TypeList> TypeListI
%type <TypeWithAttrsList> ArgTypeList ArgTypeListI %type <TypeWithAttrsList> ArgTypeList ArgTypeListI
%type <TypeWithAttrs> ArgType ResultType %type <TypeWithAttrs> ArgType
%type <JumpTable> JumpTable %type <JumpTable> JumpTable
%type <BoolVal> GlobalType // GLOBAL or CONSTANT? %type <BoolVal> GlobalType // GLOBAL or CONSTANT?
%type <BoolVal> OptVolatile // 'volatile' or not %type <BoolVal> OptVolatile // 'volatile' or not
@ -978,7 +978,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
%token <FPVal> FPVAL // Float or Double constant %token <FPVal> FPVAL // Float or Double constant
// Built in types... // Built in types...
%type <TypeVal> Types %type <TypeVal> Types ResultTypes
%type <PrimType> IntType FPType PrimType // Classifications %type <PrimType> IntType FPType PrimType // Classifications
%token <PrimType> VOID BOOL INT8 INT16 INT32 INT64 %token <PrimType> VOID BOOL INT8 INT16 INT32 INT64
%token <PrimType> FLOAT DOUBLE LABEL %token <PrimType> FLOAT DOUBLE LABEL
@ -999,7 +999,8 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
%token X86_STDCALLCC_TOK X86_FASTCALLCC_TOK %token X86_STDCALLCC_TOK X86_FASTCALLCC_TOK
%token DATALAYOUT %token DATALAYOUT
%type <UIntVal> OptCallingConv %type <UIntVal> OptCallingConv
%type <ParamAttrs> OptParamAttrs ParamAttrList ParamAttr %type <ParamAttrs> OptParamAttrs ParamAttr
%type <ParamAttrs> OptFuncAttrs FuncAttr
// Basic Block Terminating Operators // Basic Block Terminating Operators
%token <TermOpVal> RET BR SWITCH INVOKE UNWIND UNREACHABLE %token <TermOpVal> RET BR SWITCH INVOKE UNWIND UNREACHABLE
@ -1026,6 +1027,8 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
%token <OtherOpVal> PHI_TOK SELECT SHL LSHR ASHR VAARG %token <OtherOpVal> PHI_TOK SELECT SHL LSHR ASHR VAARG
%token <OtherOpVal> EXTRACTELEMENT INSERTELEMENT SHUFFLEVECTOR %token <OtherOpVal> EXTRACTELEMENT INSERTELEMENT SHUFFLEVECTOR
// Function Attributes
%token NORETURN
%start Module %start Module
%% %%
@ -1129,15 +1132,20 @@ ParamAttr : ZEXT { $$ = FunctionType::ZExtAttribute; }
| SEXT { $$ = FunctionType::SExtAttribute; } | SEXT { $$ = FunctionType::SExtAttribute; }
; ;
ParamAttrList : ParamAttr { $$ = $1; } OptParamAttrs : /* empty */ { $$ = FunctionType::NoAttributeSet; }
| ParamAttrList ',' ParamAttr { | OptParamAttrs ParamAttr {
$$ = FunctionType::ParameterAttributes($1 | $3); $$ = FunctionType::ParameterAttributes($1 | $2);
} }
; ;
OptParamAttrs : /* empty */ { $$ = FunctionType::NoAttributeSet; } FuncAttr : NORETURN { $$ = FunctionType::NoReturnAttribute; }
| '@' ParamAttr { $$ = $2; } | ParamAttr
| '@' '(' ParamAttrList ')' { $$ = $3; } ;
OptFuncAttrs : /* empty */ { $$ = FunctionType::NoAttributeSet; }
| OptFuncAttrs FuncAttr {
$$ = FunctionType::ParameterAttributes($1 | $2);
}
; ;
// OptAlign/OptCAlign - An optional alignment, and an optional alignment with // OptAlign/OptCAlign - An optional alignment, and an optional alignment with
@ -1223,11 +1231,11 @@ Types
UR_OUT("New Upreference!\n"); UR_OUT("New Upreference!\n");
CHECK_FOR_ERROR CHECK_FOR_ERROR
} }
| Types OptParamAttrs '(' ArgTypeListI ')' { | Types '(' ArgTypeListI ')' OptFuncAttrs {
std::vector<const Type*> Params; std::vector<const Type*> Params;
std::vector<FunctionType::ParameterAttributes> Attrs; std::vector<FunctionType::ParameterAttributes> Attrs;
Attrs.push_back($2); Attrs.push_back($5);
for (TypeWithAttrsList::iterator I=$4->begin(), E=$4->end(); I != E; ++I) { for (TypeWithAttrsList::iterator I=$3->begin(), E=$3->end(); I != E; ++I) {
Params.push_back(I->Ty->get()); Params.push_back(I->Ty->get());
if (I->Ty->get() != Type::VoidTy) if (I->Ty->get() != Type::VoidTy)
Attrs.push_back(I->Attrs); Attrs.push_back(I->Attrs);
@ -1236,16 +1244,16 @@ Types
if (isVarArg) Params.pop_back(); if (isVarArg) Params.pop_back();
FunctionType *FT = FunctionType::get(*$1, Params, isVarArg, Attrs); FunctionType *FT = FunctionType::get(*$1, Params, isVarArg, Attrs);
delete $4; // Delete the argument list delete $3; // Delete the argument list
delete $1; // Delete the return type handle delete $1; // Delete the return type handle
$$ = new PATypeHolder(HandleUpRefs(FT)); $$ = new PATypeHolder(HandleUpRefs(FT));
CHECK_FOR_ERROR CHECK_FOR_ERROR
} }
| VOID OptParamAttrs '(' ArgTypeListI ')' { | VOID '(' ArgTypeListI ')' OptFuncAttrs {
std::vector<const Type*> Params; std::vector<const Type*> Params;
std::vector<FunctionType::ParameterAttributes> Attrs; std::vector<FunctionType::ParameterAttributes> Attrs;
Attrs.push_back($2); Attrs.push_back($5);
for (TypeWithAttrsList::iterator I=$4->begin(), E=$4->end(); I != E; ++I) { for (TypeWithAttrsList::iterator I=$3->begin(), E=$3->end(); I != E; ++I) {
Params.push_back(I->Ty->get()); Params.push_back(I->Ty->get());
if (I->Ty->get() != Type::VoidTy) if (I->Ty->get() != Type::VoidTy)
Attrs.push_back(I->Attrs); Attrs.push_back(I->Attrs);
@ -1254,7 +1262,7 @@ Types
if (isVarArg) Params.pop_back(); if (isVarArg) Params.pop_back();
FunctionType *FT = FunctionType::get($1, Params, isVarArg, Attrs); FunctionType *FT = FunctionType::get($1, Params, isVarArg, Attrs);
delete $4; // Delete the argument list delete $3; // Delete the argument list
$$ = new PATypeHolder(HandleUpRefs(FT)); $$ = new PATypeHolder(HandleUpRefs(FT));
CHECK_FOR_ERROR CHECK_FOR_ERROR
} }
@ -1313,18 +1321,16 @@ ArgType
} }
; ;
ResultType ResultTypes
: Types OptParamAttrs { : Types {
if (!UpRefs.empty()) if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription()); GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription());
if (!(*$1)->isFirstClassType()) if (!(*$1)->isFirstClassType())
GEN_ERROR("LLVM functions cannot return aggregate types!"); GEN_ERROR("LLVM functions cannot return aggregate types!");
$$.Ty = $1; $$ = $1;
$$.Attrs = $2;
} }
| VOID OptParamAttrs { | VOID {
$$.Ty = new PATypeHolder(Type::VoidTy); $$ = new PATypeHolder(Type::VoidTy);
$$.Attrs = $2;
} }
; ;
@ -1990,20 +1996,20 @@ ArgList : ArgListH {
CHECK_FOR_ERROR CHECK_FOR_ERROR
}; };
FunctionHeaderH : OptCallingConv ResultType Name '(' ArgList ')' FunctionHeaderH : OptCallingConv ResultTypes Name '(' ArgList ')'
OptSection OptAlign { OptFuncAttrs OptSection OptAlign {
UnEscapeLexed($3); UnEscapeLexed($3);
std::string FunctionName($3); std::string FunctionName($3);
free($3); // Free strdup'd memory! free($3); // Free strdup'd memory!
// Check the function result for abstractness if this is a define. We should // Check the function result for abstractness if this is a define. We should
// have no abstract types at this point // have no abstract types at this point
if (!CurFun.isDeclare && CurModule.TypeIsUnresolved($2.Ty)) if (!CurFun.isDeclare && CurModule.TypeIsUnresolved($2))
GEN_ERROR("Reference to abstract result: "+ $2.Ty->get()->getDescription()); GEN_ERROR("Reference to abstract result: "+ $2->get()->getDescription());
std::vector<const Type*> ParamTypeList; std::vector<const Type*> ParamTypeList;
std::vector<FunctionType::ParameterAttributes> ParamAttrs; std::vector<FunctionType::ParameterAttributes> ParamAttrs;
ParamAttrs.push_back($2.Attrs); ParamAttrs.push_back($7);
if ($5) { // If there are arguments... if ($5) { // If there are arguments...
for (ArgListType::iterator I = $5->begin(); I != $5->end(); ++I) { for (ArgListType::iterator I = $5->begin(); I != $5->end(); ++I) {
const Type* Ty = I->Ty->get(); const Type* Ty = I->Ty->get();
@ -2018,10 +2024,10 @@ FunctionHeaderH : OptCallingConv ResultType Name '(' ArgList ')'
bool isVarArg = ParamTypeList.size() && ParamTypeList.back() == Type::VoidTy; bool isVarArg = ParamTypeList.size() && ParamTypeList.back() == Type::VoidTy;
if (isVarArg) ParamTypeList.pop_back(); if (isVarArg) ParamTypeList.pop_back();
FunctionType *FT = FunctionType::get(*$2.Ty, ParamTypeList, isVarArg, FunctionType *FT = FunctionType::get(*$2, ParamTypeList, isVarArg,
ParamAttrs); ParamAttrs);
const PointerType *PFT = PointerType::get(FT); const PointerType *PFT = PointerType::get(FT);
delete $2.Ty; delete $2;
ValID ID; ValID ID;
if (!FunctionName.empty()) { if (!FunctionName.empty()) {
@ -2066,10 +2072,10 @@ FunctionHeaderH : OptCallingConv ResultType Name '(' ArgList ')'
Fn->setLinkage(CurFun.Linkage); Fn->setLinkage(CurFun.Linkage);
} }
Fn->setCallingConv($1); Fn->setCallingConv($1);
Fn->setAlignment($8); Fn->setAlignment($9);
if ($7) { if ($8) {
Fn->setSection($7); Fn->setSection($8);
free($7); free($8);
} }
// Add all of the arguments we parsed to the function... // Add all of the arguments we parsed to the function...
@ -2340,18 +2346,18 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result...
$$ = S; $$ = S;
CHECK_FOR_ERROR CHECK_FOR_ERROR
} }
| INVOKE OptCallingConv ResultType ValueRef '(' ValueRefList ')' | INVOKE OptCallingConv ResultTypes ValueRef '(' ValueRefList ')' OptFuncAttrs
TO LABEL ValueRef UNWIND LABEL ValueRef { TO LABEL ValueRef UNWIND LABEL ValueRef {
// Handle the short syntax // Handle the short syntax
const PointerType *PFTy = 0; const PointerType *PFTy = 0;
const FunctionType *Ty = 0; const FunctionType *Ty = 0;
if (!(PFTy = dyn_cast<PointerType>($3.Ty->get())) || if (!(PFTy = dyn_cast<PointerType>($3->get())) ||
!(Ty = dyn_cast<FunctionType>(PFTy->getElementType()))) { !(Ty = dyn_cast<FunctionType>(PFTy->getElementType()))) {
// Pull out the types of all of the arguments... // Pull out the types of all of the arguments...
std::vector<const Type*> ParamTypes; std::vector<const Type*> ParamTypes;
FunctionType::ParamAttrsList ParamAttrs; FunctionType::ParamAttrsList ParamAttrs;
ParamAttrs.push_back($3.Attrs); ParamAttrs.push_back($8);
for (ValueRefList::iterator I = $6->begin(), E = $6->end(); I != E; ++I) { for (ValueRefList::iterator I = $6->begin(), E = $6->end(); I != E; ++I) {
const Type *Ty = I->Val->getType(); const Type *Ty = I->Val->getType();
if (Ty == Type::VoidTy) if (Ty == Type::VoidTy)
@ -2360,15 +2366,15 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result...
ParamAttrs.push_back(I->Attrs); ParamAttrs.push_back(I->Attrs);
} }
Ty = FunctionType::get($3.Ty->get(), ParamTypes, false, ParamAttrs); Ty = FunctionType::get($3->get(), ParamTypes, false, ParamAttrs);
PFTy = PointerType::get(Ty); PFTy = PointerType::get(Ty);
} }
Value *V = getVal(PFTy, $4); // Get the function we're calling... Value *V = getVal(PFTy, $4); // Get the function we're calling...
CHECK_FOR_ERROR CHECK_FOR_ERROR
BasicBlock *Normal = getBBVal($10); BasicBlock *Normal = getBBVal($11);
CHECK_FOR_ERROR CHECK_FOR_ERROR
BasicBlock *Except = getBBVal($13); BasicBlock *Except = getBBVal($14);
CHECK_FOR_ERROR CHECK_FOR_ERROR
// Check the arguments // Check the arguments
@ -2655,17 +2661,18 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
delete $2; // Free the list... delete $2; // Free the list...
CHECK_FOR_ERROR CHECK_FOR_ERROR
} }
| OptTailCall OptCallingConv ResultType ValueRef '(' ValueRefList ')' { | OptTailCall OptCallingConv ResultTypes ValueRef '(' ValueRefList ')'
OptFuncAttrs {
// Handle the short syntax // Handle the short syntax
const PointerType *PFTy = 0; const PointerType *PFTy = 0;
const FunctionType *Ty = 0; const FunctionType *Ty = 0;
if (!(PFTy = dyn_cast<PointerType>($3.Ty->get())) || if (!(PFTy = dyn_cast<PointerType>($3->get())) ||
!(Ty = dyn_cast<FunctionType>(PFTy->getElementType()))) { !(Ty = dyn_cast<FunctionType>(PFTy->getElementType()))) {
// Pull out the types of all of the arguments... // Pull out the types of all of the arguments...
std::vector<const Type*> ParamTypes; std::vector<const Type*> ParamTypes;
FunctionType::ParamAttrsList ParamAttrs; FunctionType::ParamAttrsList ParamAttrs;
ParamAttrs.push_back($3.Attrs); ParamAttrs.push_back($8);
for (ValueRefList::iterator I = $6->begin(), E = $6->end(); I != E; ++I) { for (ValueRefList::iterator I = $6->begin(), E = $6->end(); I != E; ++I) {
const Type *Ty = I->Val->getType(); const Type *Ty = I->Val->getType();
if (Ty == Type::VoidTy) if (Ty == Type::VoidTy)
@ -2674,7 +2681,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
ParamAttrs.push_back(I->Attrs); ParamAttrs.push_back(I->Attrs);
} }
Ty = FunctionType::get($3.Ty->get(), ParamTypes, false, ParamAttrs); Ty = FunctionType::get($3->get(), ParamTypes, false, ParamAttrs);
PFTy = PointerType::get(Ty); PFTy = PointerType::get(Ty);
} }

View File

@ -271,10 +271,6 @@ static void calcTypeName(const Type *Ty,
case Type::FunctionTyID: { case Type::FunctionTyID: {
const FunctionType *FTy = cast<FunctionType>(Ty); const FunctionType *FTy = cast<FunctionType>(Ty);
calcTypeName(FTy->getReturnType(), TypeStack, TypeNames, Result); calcTypeName(FTy->getReturnType(), TypeStack, TypeNames, Result);
if (FTy->getParamAttrs(0)) {
Result += " ";
Result += FunctionType::getParamAttrsText(FTy->getParamAttrs(0));
}
Result += " ("; Result += " (";
unsigned Idx = 1; unsigned Idx = 1;
for (FunctionType::param_iterator I = FTy->param_begin(), for (FunctionType::param_iterator I = FTy->param_begin(),
@ -293,6 +289,10 @@ static void calcTypeName(const Type *Ty,
Result += "..."; Result += "...";
} }
Result += ")"; Result += ")";
if (FTy->getParamAttrs(0)) {
Result += " ";
Result += FunctionType::getParamAttrsText(FTy->getParamAttrs(0));
}
break; break;
} }
case Type::StructTyID: { case Type::StructTyID: {
@ -698,8 +698,6 @@ private:
std::ostream &AssemblyWriter::printTypeAtLeastOneLevel(const Type *Ty) { std::ostream &AssemblyWriter::printTypeAtLeastOneLevel(const Type *Ty) {
if (const FunctionType *FTy = dyn_cast<FunctionType>(Ty)) { if (const FunctionType *FTy = dyn_cast<FunctionType>(Ty)) {
printType(FTy->getReturnType()); printType(FTy->getReturnType());
if (FTy->getParamAttrs(0))
Out << ' ' << FunctionType::getParamAttrsText(FTy->getParamAttrs(0));
Out << " ("; Out << " (";
unsigned Idx = 1; unsigned Idx = 1;
for (FunctionType::param_iterator I = FTy->param_begin(), for (FunctionType::param_iterator I = FTy->param_begin(),
@ -717,6 +715,8 @@ std::ostream &AssemblyWriter::printTypeAtLeastOneLevel(const Type *Ty) {
Out << "..."; Out << "...";
} }
Out << ')'; Out << ')';
if (FTy->getParamAttrs(0))
Out << ' ' << FunctionType::getParamAttrsText(FTy->getParamAttrs(0));
} else if (const StructType *STy = dyn_cast<StructType>(Ty)) { } else if (const StructType *STy = dyn_cast<StructType>(Ty)) {
if (STy->isPacked()) if (STy->isPacked())
Out << '<'; Out << '<';
@ -969,8 +969,6 @@ void AssemblyWriter::printFunction(const Function *F) {
const FunctionType *FT = F->getFunctionType(); const FunctionType *FT = F->getFunctionType();
printType(F->getReturnType()) << ' '; printType(F->getReturnType()) << ' ';
if (FT->getParamAttrs(0))
Out << FunctionType::getParamAttrsText(FT->getParamAttrs(0)) << ' ';
if (!F->getName().empty()) if (!F->getName().empty())
Out << getLLVMName(F->getName()); Out << getLLVMName(F->getName());
else else
@ -995,7 +993,8 @@ void AssemblyWriter::printFunction(const Function *F) {
Out << "..."; // Output varargs portion of signature! Out << "..."; // Output varargs portion of signature!
} }
Out << ')'; Out << ')';
if (FT->getParamAttrs(0))
Out << ' ' << FunctionType::getParamAttrsText(FT->getParamAttrs(0));
if (F->hasSection()) if (F->hasSection())
Out << " section \"" << F->getSection() << '"'; Out << " section \"" << F->getSection() << '"';
if (F->getAlignment()) if (F->getAlignment())
@ -1186,8 +1185,6 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
(!isa<PointerType>(RetTy) || (!isa<PointerType>(RetTy) ||
!isa<FunctionType>(cast<PointerType>(RetTy)->getElementType()))) { !isa<FunctionType>(cast<PointerType>(RetTy)->getElementType()))) {
Out << ' '; printType(RetTy); Out << ' '; printType(RetTy);
if (FTy->getParamAttrs(0) != FunctionType::NoAttributeSet)
Out << " " << FTy->getParamAttrsText(FTy->getParamAttrs(0));
writeOperand(Operand, false); writeOperand(Operand, false);
} else { } else {
writeOperand(Operand, true); writeOperand(Operand, true);
@ -1201,6 +1198,8 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
Out << " " << FTy->getParamAttrsText(FTy->getParamAttrs(op)); Out << " " << FTy->getParamAttrsText(FTy->getParamAttrs(op));
} }
Out << " )"; Out << " )";
if (FTy->getParamAttrs(0) != FunctionType::NoAttributeSet)
Out << ' ' << FTy->getParamAttrsText(FTy->getParamAttrs(0));
} else if (const InvokeInst *II = dyn_cast<InvokeInst>(&I)) { } else if (const InvokeInst *II = dyn_cast<InvokeInst>(&I)) {
const PointerType *PTy = cast<PointerType>(Operand->getType()); const PointerType *PTy = cast<PointerType>(Operand->getType());
const FunctionType *FTy = cast<FunctionType>(PTy->getElementType()); const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
@ -1225,8 +1224,6 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
(!isa<PointerType>(RetTy) || (!isa<PointerType>(RetTy) ||
!isa<FunctionType>(cast<PointerType>(RetTy)->getElementType()))) { !isa<FunctionType>(cast<PointerType>(RetTy)->getElementType()))) {
Out << ' '; printType(RetTy); Out << ' '; printType(RetTy);
if (FTy->getParamAttrs(0) != FunctionType::NoAttributeSet)
Out << " " << FTy->getParamAttrsText(FTy->getParamAttrs(0));
writeOperand(Operand, false); writeOperand(Operand, false);
} else { } else {
writeOperand(Operand, true); writeOperand(Operand, true);
@ -1241,7 +1238,10 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
Out << " " << FTy->getParamAttrsText(FTy->getParamAttrs(op-2)); Out << " " << FTy->getParamAttrsText(FTy->getParamAttrs(op-2));
} }
Out << " )\n\t\t\tto"; Out << " )";
if (FTy->getParamAttrs(0) != FunctionType::NoAttributeSet)
Out << " " << FTy->getParamAttrsText(FTy->getParamAttrs(0));
Out << "\n\t\t\tto";
writeOperand(II->getNormalDest(), true); writeOperand(II->getNormalDest(), true);
Out << " unwind"; Out << " unwind";
writeOperand(II->getUnwindDest(), true); writeOperand(II->getUnwindDest(), true);

View File

@ -245,7 +245,6 @@ static std::string getTypeDescription(const Type *Ty,
switch (Ty->getTypeID()) { switch (Ty->getTypeID()) {
case Type::FunctionTyID: { case Type::FunctionTyID: {
const FunctionType *FTy = cast<FunctionType>(Ty); const FunctionType *FTy = cast<FunctionType>(Ty);
Result = FunctionType::getParamAttrsText(FTy->getParamAttrs(0));
if (!Result.empty()) if (!Result.empty())
Result += " "; Result += " ";
Result += getTypeDescription(FTy->getReturnType(), TypeStack) + " ("; Result += getTypeDescription(FTy->getReturnType(), TypeStack) + " (";
@ -254,11 +253,7 @@ static std::string getTypeDescription(const Type *Ty,
E = FTy->param_end(); I != E; ++I) { E = FTy->param_end(); I != E; ++I) {
if (I != FTy->param_begin()) if (I != FTy->param_begin())
Result += ", "; Result += ", ";
const char *PA = FunctionType::getParamAttrsText(FTy->getParamAttrs(Idx)); Result += FunctionType::getParamAttrsText(FTy->getParamAttrs(Idx));
if (PA[0] != 0) {
Result += PA;
Result += " ";
}
Idx++; Idx++;
Result += getTypeDescription(*I, TypeStack); Result += getTypeDescription(*I, TypeStack);
} }
@ -267,6 +262,9 @@ static std::string getTypeDescription(const Type *Ty,
Result += "..."; Result += "...";
} }
Result += ")"; Result += ")";
if (FTy->getParamAttrs(0)) {
Result += " " + FunctionType::getParamAttrsText(FTy->getParamAttrs(0));
}
break; break;
} }
case Type::StructTyID: { case Type::StructTyID: {
@ -1021,13 +1019,15 @@ FunctionType::getParamAttrs(unsigned Idx) const {
return (*ParamAttrs)[Idx]; return (*ParamAttrs)[Idx];
} }
const char *FunctionType::getParamAttrsText(ParameterAttributes Attr) { std::string FunctionType::getParamAttrsText(ParameterAttributes Attr) {
switch (Attr) { std::string Result;
default: assert(0 && "Invalid ParameterAttribute value"); if (Attr & ZExtAttribute)
case 0: return ""; Result += "zext ";
case ZExtAttribute: return "@zext"; if (Attr & SExtAttribute)
case SExtAttribute: return "@sext"; Result += "sext ";
} if (Attr & NoReturnAttribute)
Result += "noreturn ";
return Result;
} }
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//