X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;ds=inline;f=lib%2FVMCore%2FAsmWriter.cpp;h=aba66c85a7654645311f65e6921e64bbe4c838eb;hb=4f4c28f75f74fe557efb63feaf5f4f8bf639dcd5;hp=f13a140b63846f37c3b0e9e7a6606abe61b81b93;hpb=ebe57e36dff2dc3a7ceea99202bdb9eb6fe938bc;p=oota-llvm.git diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index f13a140b638..aba66c85a76 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -2,8 +2,8 @@ // // The LLVM Compiler Infrastructure // -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // @@ -24,7 +24,7 @@ #include "llvm/Instruction.h" #include "llvm/Instructions.h" #include "llvm/Module.h" -#include "llvm/SymbolTable.h" +#include "llvm/ValueSymbolTable.h" #include "llvm/TypeSymbolTable.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/STLExtras.h" @@ -32,6 +32,7 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/Streams.h" #include +#include using namespace llvm; namespace llvm { @@ -48,27 +49,17 @@ class SlotMachine { public: /// @brief A mapping of Values to slot numbers - typedef std::map ValueMap; - - /// @brief A plane with next slot number and ValueMap - struct ValuePlane { - unsigned next_slot; ///< The next slot number to use - ValueMap map; ///< The map of Value* -> unsigned - ValuePlane() { next_slot = 0; } ///< Make sure we start at 0 - }; - - /// @brief The map of planes by Type - typedef std::map TypedPlanes; + typedef std::map ValueMap; /// @} /// @name Constructors /// @{ public: /// @brief Construct from a module - SlotMachine(const Module *M); + explicit SlotMachine(const Module *M); /// @brief Construct from a function, starting out in incorp state. - SlotMachine(const Function *F); + explicit SlotMachine(const Function *F); /// @} /// @name Accessors @@ -131,10 +122,12 @@ public: bool FunctionProcessed; /// @brief The TypePlanes map for the module level data - TypedPlanes mMap; + ValueMap mMap; + unsigned mNext; /// @brief The TypePlanes map for the function level data - TypedPlanes fMap; + ValueMap fMap; + unsigned fNext; /// @} @@ -142,8 +135,10 @@ public: } // end namespace llvm +char PrintModulePass::ID = 0; static RegisterPass X("printm", "Print module to stderr"); +char PrintFunctionPass::ID = 0; static RegisterPass Y("print","Print function to stderr"); @@ -173,6 +168,8 @@ static SlotMachine *createSlotMachine(const Value *V) { return new SlotMachine(BB->getParent()); } else if (const GlobalVariable *GV = dyn_cast(V)){ return new SlotMachine(GV->getParent()); + } else if (const GlobalAlias *GA = dyn_cast(V)){ + return new SlotMachine(GA->getParent()); } else if (const Function *Func = dyn_cast(V)) { return new SlotMachine(Func); } @@ -181,17 +178,42 @@ static SlotMachine *createSlotMachine(const Value *V) { /// NameNeedsQuotes - Return true if the specified llvm name should be wrapped /// with ""'s. -static bool NameNeedsQuotes(const std::string &Name) { - if (Name[0] >= '0' && Name[0] <= '9') return true; - // Scan to see if we have any characters that are not on the "white list" +static std::string QuoteNameIfNeeded(const std::string &Name) { + std::string result; + bool needsQuotes = Name[0] >= '0' && Name[0] <= '9'; + // Scan the name to see if it needs quotes and to replace funky chars with + // their octal equivalent. for (unsigned i = 0, e = Name.size(); i != e; ++i) { char C = Name[i]; assert(C != '"' && "Illegal character in LLVM value name!"); - if ((C < 'a' || C > 'z') && (C < 'A' || C > 'Z') && (C < '0' || C > '9') && - C != '-' && C != '.' && C != '_') - return true; + if (isalnum(C) || C == '-' || C == '.' || C == '_') + result += C; + else if (C == '\\') { + needsQuotes = true; + result += "\\\\"; + } else if (isprint(C)) { + needsQuotes = true; + result += C; + } else { + needsQuotes = true; + result += "\\"; + char hex1 = (C >> 4) & 0x0F; + if (hex1 < 10) + result += hex1 + '0'; + else + result += hex1 - 10 + 'A'; + char hex2 = C & 0x0F; + if (hex2 < 10) + result += hex2 + '0'; + else + result += hex2 - 10 + 'A'; + } } - return false; + if (needsQuotes) { + result.insert(0,"\""); + result += '"'; + } + return result; } enum PrefixType { @@ -205,20 +227,11 @@ enum PrefixType { /// surrounded with ""'s (if it has special chars in it). static std::string getLLVMName(const std::string &Name, PrefixType Prefix) { assert(!Name.empty() && "Cannot get empty name!"); - - // First character cannot start with a number... - if (NameNeedsQuotes(Name)) { - if (Prefix == GlobalPrefix) - return "@\"" + Name + "\""; - return "\"" + Name + "\""; - } - - // If we get here, then the identifier is legal to use as a "VarID". switch (Prefix) { default: assert(0 && "Bad prefix!"); - case GlobalPrefix: return '@' + Name; - case LabelPrefix: return Name; - case LocalPrefix: return '%' + Name; + case GlobalPrefix: return '@' + QuoteNameIfNeeded(Name); + case LabelPrefix: return QuoteNameIfNeeded(Name); + case LocalPrefix: return '%' + QuoteNameIfNeeded(Name); } } @@ -291,27 +304,17 @@ static void calcTypeName(const Type *Ty, const FunctionType *FTy = cast(Ty); calcTypeName(FTy->getReturnType(), TypeStack, TypeNames, Result); Result += " ("; - unsigned Idx = 1; 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 (FTy->getParamAttrs(Idx)) { - Result += + " "; - Result += FunctionType::getParamAttrsText(FTy->getParamAttrs(Idx)); - } - Idx++; } if (FTy->isVarArg()) { if (FTy->getNumParams()) Result += ", "; Result += "..."; } Result += ")"; - if (FTy->getParamAttrs(0)) { - Result += " "; - Result += FunctionType::getParamAttrsText(FTy->getParamAttrs(0)); - } break; } case Type::StructTyID: { @@ -330,11 +333,15 @@ static void calcTypeName(const Type *Ty, Result += '>'; break; } - case Type::PointerTyID: - calcTypeName(cast(Ty)->getElementType(), + case Type::PointerTyID: { + const PointerType *PTy = cast(Ty); + calcTypeName(PTy->getElementType(), TypeStack, TypeNames, Result); + if (unsigned AddressSpace = PTy->getAddressSpace()) + Result += " addrspace(" + utostr(AddressSpace) + ")"; Result += "*"; break; + } case Type::ArrayTyID: { const ArrayType *ATy = cast(Ty); Result += "[" + utostr(ATy->getNumElements()) + " x "; @@ -342,8 +349,8 @@ static void calcTypeName(const Type *Ty, Result += "]"; break; } - case Type::PackedTyID: { - const PackedType *PTy = cast(Ty); + case Type::VectorTyID: { + const VectorType *PTy = cast(Ty); Result += "<" + utostr(PTy->getNumElements()) + " x "; calcTypeName(PTy->getElementType(), TypeStack, TypeNames, Result); Result += ">"; @@ -464,34 +471,70 @@ static void WriteConstantInt(std::ostream &Out, const Constant *CV, if (CI->getType() == Type::Int1Ty) Out << (CI->getZExtValue() ? "true" : "false"); else - Out << CI->getSExtValue(); + Out << CI->getValue().toStringSigned(10); } else if (const ConstantFP *CFP = dyn_cast(CV)) { - // We would like to output the FP constant value in exponential notation, - // but we cannot do this if doing so will lose precision. Check here to - // make sure that we only output it in exponential format if we can parse - // the value back and get the same value. - // - std::string StrVal = ftostr(CFP->getValue()); - - // Check to make sure that the stringized number is not some string like - // "Inf" or NaN, that atof will accept, but the lexer will not. Check that - // the string matches the "[-+]?[0-9]" regex. - // - if ((StrVal[0] >= '0' && StrVal[0] <= '9') || - ((StrVal[0] == '-' || StrVal[0] == '+') && - (StrVal[1] >= '0' && StrVal[1] <= '9'))) - // Reparse stringized version! - if (atof(StrVal.c_str()) == CFP->getValue()) { - Out << StrVal; - return; + if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEdouble || + &CFP->getValueAPF().getSemantics() == &APFloat::IEEEsingle) { + // We would like to output the FP constant value in exponential notation, + // but we cannot do this if doing so will lose precision. Check here to + // make sure that we only output it in exponential format if we can parse + // the value back and get the same value. + // + bool isDouble = &CFP->getValueAPF().getSemantics()==&APFloat::IEEEdouble; + double Val = (isDouble) ? CFP->getValueAPF().convertToDouble() : + CFP->getValueAPF().convertToFloat(); + std::string StrVal = ftostr(CFP->getValueAPF()); + + // Check to make sure that the stringized number is not some string like + // "Inf" or NaN, that atof will accept, but the lexer will not. Check + // that the string matches the "[-+]?[0-9]" regex. + // + if ((StrVal[0] >= '0' && StrVal[0] <= '9') || + ((StrVal[0] == '-' || StrVal[0] == '+') && + (StrVal[1] >= '0' && StrVal[1] <= '9'))) { + // Reparse stringized version! + if (atof(StrVal.c_str()) == Val) { + Out << StrVal; + return; + } } - - // Otherwise we could not reparse it to exactly the same value, so we must - // output the string in hexadecimal format! - assert(sizeof(double) == sizeof(uint64_t) && - "assuming that double is 64 bits!"); - Out << "0x" << utohexstr(DoubleToBits(CFP->getValue())); - + // Otherwise we could not reparse it to exactly the same value, so we must + // output the string in hexadecimal format! + assert(sizeof(double) == sizeof(uint64_t) && + "assuming that double is 64 bits!"); + Out << "0x" << utohexstr(DoubleToBits(Val)); + } else { + // Some form of long double. These appear as a magic letter identifying + // the type, then a fixed number of hex digits. + Out << "0x"; + if (&CFP->getValueAPF().getSemantics() == &APFloat::x87DoubleExtended) + Out << 'K'; + else if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEquad) + Out << 'L'; + else if (&CFP->getValueAPF().getSemantics() == &APFloat::PPCDoubleDouble) + Out << 'M'; + else + assert(0 && "Unsupported floating point type"); + // api needed to prevent premature destruction + APInt api = CFP->getValueAPF().convertToAPInt(); + const uint64_t* p = api.getRawData(); + uint64_t word = *p; + int shiftcount=60; + int width = api.getBitWidth(); + for (int j=0; j>shiftcount) & 15; + if (nibble < 10) + Out << (unsigned char)(nibble + '0'); + else + Out << (unsigned char)(nibble - 10 + 'A'); + if (shiftcount == 0) { + word = *(++p); + shiftcount = 64; + if (width-j-4 < 64) + shiftcount = width-j-4; + } + } + } } else if (isa(CV)) { Out << "zeroinitializer"; } else if (const ConstantArray *CA = dyn_cast(CV)) { @@ -548,7 +591,7 @@ static void WriteConstantInt(std::ostream &Out, const Constant *CV, Out << " }"; if (CS->getType()->isPacked()) Out << '>'; - } else if (const ConstantPacked *CP = dyn_cast(CV)) { + } else if (const ConstantVector *CP = dyn_cast(CV)) { const Type *ETy = CP->getType()->getElementType(); assert(CP->getNumOperands() > 0 && "Number of operands for a PackedConst must be > 0"); @@ -689,14 +732,16 @@ public: fillTypeNameTable(M, TypeNames); } - inline void write(const Module *M) { printModule(M); } - inline void write(const GlobalVariable *G) { printGlobal(G); } - inline void write(const Function *F) { printFunction(F); } - inline void write(const BasicBlock *BB) { printBasicBlock(BB); } + inline void write(const Module *M) { printModule(M); } + inline void write(const GlobalVariable *G) { printGlobal(G); } + inline void write(const GlobalAlias *G) { printAlias(G); } + inline void write(const Function *F) { printFunction(F); } + inline void write(const BasicBlock *BB) { printBasicBlock(BB); } inline void write(const Instruction *I) { printInstruction(*I); } - inline void write(const Type *Ty) { printType(Ty); } + inline void write(const Type *Ty) { printType(Ty); } void writeOperand(const Value *Op, bool PrintType); + void writeParamOperand(const Value *Operand, ParameterAttributes Attrs); const Module* getModule() { return TheModule; } @@ -704,8 +749,9 @@ private: void printModule(const Module *M); void printTypeSymbolTable(const TypeSymbolTable &ST); void printGlobal(const GlobalVariable *GV); + void printAlias(const GlobalAlias *GV); void printFunction(const Function *F); - void printArgument(const Argument *FA, FunctionType::ParameterAttributes A); + void printArgument(const Argument *FA, ParameterAttributes Attrs); void printBasicBlock(const BasicBlock *BB); void printInstruction(const Instruction &I); @@ -736,24 +782,17 @@ std::ostream &AssemblyWriter::printTypeAtLeastOneLevel(const Type *Ty) { else if (const FunctionType *FTy = dyn_cast(Ty)) { printType(FTy->getReturnType()); Out << " ("; - unsigned Idx = 1; for (FunctionType::param_iterator I = FTy->param_begin(), E = FTy->param_end(); I != E; ++I) { if (I != FTy->param_begin()) Out << ", "; printType(*I); - if (FTy->getParamAttrs(Idx)) { - Out << " " << FunctionType::getParamAttrsText(FTy->getParamAttrs(Idx)); - } - Idx++; } if (FTy->isVarArg()) { if (FTy->getNumParams()) Out << ", "; Out << "..."; } Out << ')'; - if (FTy->getParamAttrs(0)) - Out << ' ' << FunctionType::getParamAttrsText(FTy->getParamAttrs(0)); } else if (const StructType *STy = dyn_cast(Ty)) { if (STy->isPacked()) Out << '<'; @@ -768,11 +807,14 @@ std::ostream &AssemblyWriter::printTypeAtLeastOneLevel(const Type *Ty) { if (STy->isPacked()) Out << '>'; } else if (const PointerType *PTy = dyn_cast(Ty)) { - printType(PTy->getElementType()) << '*'; + printType(PTy->getElementType()); + if (unsigned AddressSpace = PTy->getAddressSpace()) + Out << " addrspace(" << AddressSpace << ")"; + Out << '*'; } else if (const ArrayType *ATy = dyn_cast(Ty)) { Out << '[' << ATy->getNumElements() << " x "; printType(ATy->getElementType()) << ']'; - } else if (const PackedType *PTy = dyn_cast(Ty)) { + } else if (const VectorType *PTy = dyn_cast(Ty)) { Out << '<' << PTy->getNumElements() << " x "; printType(PTy->getElementType()) << '>'; } @@ -796,6 +838,21 @@ void AssemblyWriter::writeOperand(const Value *Operand, bool PrintType) { } } +void AssemblyWriter::writeParamOperand(const Value *Operand, + ParameterAttributes Attrs) { + if (Operand == 0) { + Out << ""; + } else { + Out << ' '; + // Print the type + printType(Operand->getType()); + // Print parameter attributes list + if (Attrs != ParamAttr::None) + Out << ' ' << ParamAttr::getAsString(Attrs); + // Print the operand + WriteAsOperandInternal(Out, Operand, TypeNames, &Machine); + } +} void AssemblyWriter::printModule(const Module *M) { if (!M->getModuleIdentifier().empty() && @@ -849,8 +906,12 @@ void AssemblyWriter::printModule(const Module *M) { for (Module::const_global_iterator I = M->global_begin(), E = M->global_end(); I != E; ++I) printGlobal(I); - - Out << "\nimplementation ; Functions:\n"; + + // Output all aliases. + if (!M->alias_empty()) Out << "\n"; + for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end(); + I != E; ++I) + printAlias(I); // Output all of the functions. for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) @@ -860,12 +921,13 @@ void AssemblyWriter::printModule(const Module *M) { void AssemblyWriter::printGlobal(const GlobalVariable *GV) { if (GV->hasName()) Out << getLLVMName(GV->getName(), GlobalPrefix) << " = "; - if (!GV->hasInitializer()) + if (!GV->hasInitializer()) { switch (GV->getLinkage()) { case GlobalValue::DLLImportLinkage: Out << "dllimport "; break; case GlobalValue::ExternalWeakLinkage: Out << "extern_weak "; break; default: Out << "external "; break; - } else { + } + } else { switch (GV->getLinkage()) { case GlobalValue::InternalLinkage: Out << "internal "; break; case GlobalValue::LinkOnceLinkage: Out << "linkonce "; break; @@ -883,9 +945,11 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) { default: assert(0 && "Invalid visibility style!"); case GlobalValue::DefaultVisibility: break; case GlobalValue::HiddenVisibility: Out << "hidden "; break; + case GlobalValue::ProtectedVisibility: Out << "protected "; break; } } - + + if (GV->isThreadLocal()) Out << "thread_local "; Out << (GV->isConstant() ? "constant " : "global "); printType(GV->getType()->getElementType()); @@ -894,16 +958,64 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) { assert(C && "GlobalVar initializer isn't constant?"); writeOperand(GV->getInitializer(), false); } - + + if (unsigned AddressSpace = GV->getType()->getAddressSpace()) + Out << " addrspace(" << AddressSpace << ") "; + if (GV->hasSection()) Out << ", section \"" << GV->getSection() << '"'; if (GV->getAlignment()) Out << ", align " << GV->getAlignment(); - + printInfoComment(*GV); Out << "\n"; } +void AssemblyWriter::printAlias(const GlobalAlias *GA) { + Out << getLLVMName(GA->getName(), GlobalPrefix) << " = "; + switch (GA->getVisibility()) { + default: assert(0 && "Invalid visibility style!"); + case GlobalValue::DefaultVisibility: break; + case GlobalValue::HiddenVisibility: Out << "hidden "; break; + case GlobalValue::ProtectedVisibility: Out << "protected "; break; + } + + Out << "alias "; + + switch (GA->getLinkage()) { + case GlobalValue::WeakLinkage: Out << "weak "; break; + case GlobalValue::InternalLinkage: Out << "internal "; break; + case GlobalValue::ExternalLinkage: break; + default: + assert(0 && "Invalid alias linkage"); + } + + const Constant *Aliasee = GA->getAliasee(); + + if (const GlobalVariable *GV = dyn_cast(Aliasee)) { + printType(GV->getType()); + Out << " " << getLLVMName(GV->getName(), GlobalPrefix); + } else if (const Function *F = dyn_cast(Aliasee)) { + printType(F->getFunctionType()); + Out << "* "; + + if (!F->getName().empty()) + Out << getLLVMName(F->getName(), GlobalPrefix); + else + Out << "@\"\""; + } else { + const ConstantExpr *CE = 0; + if ((CE = dyn_cast(Aliasee)) && + (CE->getOpcode() == Instruction::BitCast)) { + writeOperand(CE, false); + } else + assert(0 && "Unsupported aliasee"); + } + + printInfoComment(*GA); + Out << "\n"; +} + void AssemblyWriter::printTypeSymbolTable(const TypeSymbolTable &ST) { // Print the types. for (TypeSymbolTable::const_iterator TI = ST.begin(), TE = ST.end(); @@ -926,31 +1038,28 @@ void AssemblyWriter::printFunction(const Function *F) { if (AnnotationWriter) AnnotationWriter->emitFunctionAnnot(F, Out); if (F->isDeclaration()) - switch (F->getLinkage()) { - case GlobalValue::DLLImportLinkage: Out << "declare dllimport "; break; - case GlobalValue::ExternalWeakLinkage: Out << "declare extern_weak "; break; - default: Out << "declare "; - } - else { + Out << "declare "; + else Out << "define "; - switch (F->getLinkage()) { - case GlobalValue::InternalLinkage: Out << "internal "; break; - case GlobalValue::LinkOnceLinkage: Out << "linkonce "; break; - case GlobalValue::WeakLinkage: Out << "weak "; break; - case GlobalValue::AppendingLinkage: Out << "appending "; break; - case GlobalValue::DLLImportLinkage: Out << "dllimport "; break; - case GlobalValue::DLLExportLinkage: Out << "dllexport "; break; - case GlobalValue::ExternalWeakLinkage: Out << "extern_weak "; break; - case GlobalValue::ExternalLinkage: break; - case GlobalValue::GhostLinkage: - cerr << "GhostLinkage not allowed in AsmWriter!\n"; - abort(); - } - switch (F->getVisibility()) { - default: assert(0 && "Invalid visibility style!"); - case GlobalValue::DefaultVisibility: break; - case GlobalValue::HiddenVisibility: Out << "hidden "; break; - } + + switch (F->getLinkage()) { + case GlobalValue::InternalLinkage: Out << "internal "; break; + case GlobalValue::LinkOnceLinkage: Out << "linkonce "; break; + case GlobalValue::WeakLinkage: Out << "weak "; break; + case GlobalValue::AppendingLinkage: Out << "appending "; break; + case GlobalValue::DLLImportLinkage: Out << "dllimport "; break; + case GlobalValue::DLLExportLinkage: Out << "dllexport "; break; + case GlobalValue::ExternalWeakLinkage: Out << "extern_weak "; break; + case GlobalValue::ExternalLinkage: break; + case GlobalValue::GhostLinkage: + cerr << "GhostLinkage not allowed in AsmWriter!\n"; + abort(); + } + switch (F->getVisibility()) { + default: assert(0 && "Invalid visibility style!"); + case GlobalValue::DefaultVisibility: break; + case GlobalValue::HiddenVisibility: Out << "hidden "; break; + case GlobalValue::ProtectedVisibility: Out << "protected "; break; } // Print the calling convention. @@ -964,6 +1073,7 @@ void AssemblyWriter::printFunction(const Function *F) { } const FunctionType *FT = F->getFunctionType(); + const PAListPtr &Attrs = F->getParamAttrs(); printType(F->getReturnType()) << ' '; if (!F->getName().empty()) Out << getLLVMName(F->getName(), GlobalPrefix); @@ -975,12 +1085,28 @@ void AssemblyWriter::printFunction(const Function *F) { // Loop over the arguments, printing them... unsigned Idx = 1; - for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); - I != E; ++I) { - // Insert commas as we go... the first arg doesn't get a comma - if (I != F->arg_begin()) Out << ", "; - printArgument(I, FT->getParamAttrs(Idx)); - Idx++; + if (!F->isDeclaration()) { + // If this isn't a declaration, print the argument names as well. + for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); + I != E; ++I) { + // Insert commas as we go... the first arg doesn't get a comma + if (I != F->arg_begin()) Out << ", "; + printArgument(I, Attrs.getParamAttrs(Idx)); + Idx++; + } + } else { + // Otherwise, print the types from the function type. + for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) { + // Insert commas as we go... the first arg doesn't get a comma + if (i) Out << ", "; + + // Output type... + printType(FT->getParamType(i)); + + ParameterAttributes ArgAttrs = Attrs.getParamAttrs(i+1); + if (ArgAttrs != ParamAttr::None) + Out << ' ' << ParamAttr::getAsString(ArgAttrs); + } } // Finish printing arguments... @@ -989,17 +1115,20 @@ void AssemblyWriter::printFunction(const Function *F) { Out << "..."; // Output varargs portion of signature! } Out << ')'; - if (FT->getParamAttrs(0)) - Out << ' ' << FunctionType::getParamAttrsText(FT->getParamAttrs(0)); + ParameterAttributes RetAttrs = Attrs.getParamAttrs(0); + if (RetAttrs != ParamAttr::None) + Out << ' ' << ParamAttr::getAsString(Attrs.getParamAttrs(0)); if (F->hasSection()) Out << " section \"" << F->getSection() << '"'; if (F->getAlignment()) Out << " align " << F->getAlignment(); + if (F->hasCollector()) + Out << " gc \"" << F->getCollector() << '"'; if (F->isDeclaration()) { Out << "\n"; } else { - Out << " {"; + Out << " {\n"; // Output all of its basic blocks... for the function for (Function::const_iterator I = F->begin(), E = F->end(); I != E; ++I) @@ -1015,12 +1144,13 @@ void AssemblyWriter::printFunction(const Function *F) { /// the function. Simply print it out /// void AssemblyWriter::printArgument(const Argument *Arg, - FunctionType::ParameterAttributes attrs) { + ParameterAttributes Attrs) { // Output type... printType(Arg->getType()); - if (attrs != FunctionType::NoAttributeSet) - Out << ' ' << FunctionType::getParamAttrsText(attrs); + // Output parameter attributes list + if (Attrs != ParamAttr::None) + Out << ' ' << ParamAttr::getAsString(Attrs); // Output name, if available... if (Arg->hasName()) @@ -1030,10 +1160,19 @@ void AssemblyWriter::printArgument(const Argument *Arg, /// printBasicBlock - This member is called for each basic block in a method. /// void AssemblyWriter::printBasicBlock(const BasicBlock *BB) { - if (BB->hasName()) { // Print out the label if it exists... - Out << "\n" << getLLVMName(BB->getName(), LabelPrefix) << ':'; - } else if (!BB->use_empty()) { // Don't print block # of no uses... - Out << "\n;