X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FAsmWriter.cpp;h=55d037db141db02ae4fe7d1d3d0807bd9255afcb;hb=e6be34a53ecbe8c2ff9f0793b13d847e94c0de91;hp=f13a140b63846f37c3b0e9e7a6606abe61b81b93;hpb=ebe57e36dff2dc3a7ceea99202bdb9eb6fe938bc;p=oota-llvm.git diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index f13a140b638..55d037db141 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. // //===----------------------------------------------------------------------===// // @@ -20,11 +20,12 @@ #include "llvm/CallingConv.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" +#include "llvm/ParamAttrsList.h" #include "llvm/InlineAsm.h" #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 +33,7 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/Streams.h" #include +#include using namespace llvm; namespace llvm { @@ -48,27 +50,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 +123,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 +136,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 +169,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 +179,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 +228,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 +305,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 +334,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 +350,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 +472,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 +592,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 +733,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 +750,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 +783,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 +808,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 +839,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 << ' ' << ParamAttrsList::getParamAttrsText(Attrs); + // Print the operand + WriteAsOperandInternal(Out, Operand, TypeNames, &Machine); + } +} void AssemblyWriter::printModule(const Module *M) { if (!M->getModuleIdentifier().empty() && @@ -849,8 +907,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 +922,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 +946,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 +959,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 +1039,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 +1074,7 @@ void AssemblyWriter::printFunction(const Function *F) { } const FunctionType *FT = F->getFunctionType(); + const ParamAttrsList *Attrs = F->getParamAttrs(); printType(F->getReturnType()) << ' '; if (!F->getName().empty()) Out << getLLVMName(F->getName(), GlobalPrefix); @@ -975,12 +1086,30 @@ 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 ? Attrs->getParamAttrs(Idx) + : ParamAttr::None)); + 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 = ParamAttr::None; + if (Attrs) ArgAttrs = Attrs->getParamAttrs(i+1); + if (ArgAttrs != ParamAttr::None) + Out << ' ' << ParamAttrsList::getParamAttrsText(ArgAttrs); + } } // Finish printing arguments... @@ -989,12 +1118,14 @@ void AssemblyWriter::printFunction(const Function *F) { Out << "..."; // Output varargs portion of signature! } Out << ')'; - if (FT->getParamAttrs(0)) - Out << ' ' << FunctionType::getParamAttrsText(FT->getParamAttrs(0)); + if (Attrs && Attrs->getParamAttrs(0) != ParamAttr::None) + Out << ' ' << Attrs->getParamAttrsTextByIndex(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"; @@ -1015,12 +1146,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 << ' ' << ParamAttrsList::getParamAttrsText(Attrs); // Output name, if available... if (Arg->hasName()) @@ -1044,7 +1176,7 @@ void AssemblyWriter::printBasicBlock(const BasicBlock *BB) { if (BB->getParent() == 0) Out << "\t\t; Error: Block without parent!"; else { - if (BB != &BB->getParent()->front()) { // Not the entry block? + if (BB != &BB->getParent()->getEntryBlock()) { // Not the entry block? // Output predecessors for the block... Out << "\t\t;"; pred_const_iterator PI = pred_begin(BB), PE = pred_end(BB); @@ -1159,6 +1291,9 @@ void AssemblyWriter::printInstruction(const Instruction &I) { writeOperand(I.getOperand(op ), false); Out << ','; writeOperand(I.getOperand(op+1), false); Out << " ]"; } + } else if (const GetResultInst *GRI = dyn_cast(&I)) { + writeOperand(I.getOperand(0), true); + Out << ", " << GRI->getIndex(); } else if (isa(I) && !Operand) { Out << " void"; } else if (const CallInst *CI = dyn_cast(&I)) { @@ -1167,14 +1302,15 @@ void AssemblyWriter::printInstruction(const Instruction &I) { case CallingConv::C: break; // default case CallingConv::Fast: Out << " fastcc"; break; case CallingConv::Cold: Out << " coldcc"; break; - case CallingConv::X86_StdCall: Out << "x86_stdcallcc "; break; - case CallingConv::X86_FastCall: Out << "x86_fastcallcc "; break; + case CallingConv::X86_StdCall: Out << " x86_stdcallcc"; break; + case CallingConv::X86_FastCall: Out << " x86_fastcallcc"; break; default: Out << " cc" << CI->getCallingConv(); break; } - const PointerType *PTy = cast(Operand->getType()); - const FunctionType *FTy = cast(PTy->getElementType()); - const Type *RetTy = FTy->getReturnType(); + const PointerType *PTy = cast(Operand->getType()); + const FunctionType *FTy = cast(PTy->getElementType()); + const Type *RetTy = FTy->getReturnType(); + 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, @@ -1192,17 +1328,17 @@ 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 (FTy->getParamAttrs(op) != FunctionType::NoAttributeSet) - Out << " " << FTy->getParamAttrsText(FTy->getParamAttrs(op)); + writeParamOperand(I.getOperand(op), PAL ? PAL->getParamAttrs(op) : + ParamAttr::None); } Out << " )"; - if (FTy->getParamAttrs(0) != FunctionType::NoAttributeSet) - Out << ' ' << FTy->getParamAttrsText(FTy->getParamAttrs(0)); + if (PAL && PAL->getParamAttrs(0) != ParamAttr::None) + Out << ' ' << PAL->getParamAttrsTextByIndex(0); } else if (const InvokeInst *II = dyn_cast(&I)) { - const PointerType *PTy = cast(Operand->getType()); - const FunctionType *FTy = cast(PTy->getElementType()); - const Type *RetTy = FTy->getReturnType(); + const PointerType *PTy = cast(Operand->getType()); + const FunctionType *FTy = cast(PTy->getElementType()); + const Type *RetTy = FTy->getReturnType(); + const ParamAttrsList *PAL = II->getParamAttrs(); // Print the calling convention being used. switch (II->getCallingConv()) { @@ -1231,14 +1367,13 @@ 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 (FTy->getParamAttrs(op-2) != FunctionType::NoAttributeSet) - Out << " " << FTy->getParamAttrsText(FTy->getParamAttrs(op-2)); + writeParamOperand(I.getOperand(op), PAL ? PAL->getParamAttrs(op-2) : + ParamAttr::None); } Out << " )"; - if (FTy->getParamAttrs(0) != FunctionType::NoAttributeSet) - Out << " " << FTy->getParamAttrsText(FTy->getParamAttrs(0)); + if (PAL && PAL->getParamAttrs(0) != ParamAttr::None) + Out << " " << PAL->getParamAttrsTextByIndex(0); Out << "\n\t\t\tto"; writeOperand(II->getNormalDest(), true); Out << " unwind"; @@ -1293,6 +1428,13 @@ void AssemblyWriter::printInstruction(const Instruction &I) { writeOperand(I.getOperand(i), PrintAllTypes); } } + + // Print post operand alignment for load/store + if (isa(I) && cast(I).getAlignment()) { + Out << ", align " << cast(I).getAlignment(); + } else if (isa(I) && cast(I).getAlignment()) { + Out << ", align " << cast(I).getAlignment(); + } printInfoComment(I); Out << "\n"; @@ -1315,6 +1457,12 @@ void GlobalVariable::print(std::ostream &o) const { W.write(this); } +void GlobalAlias::print(std::ostream &o) const { + SlotMachine SlotTable(getParent()); + AssemblyWriter W(o, SlotTable, getParent(), 0); + W.write(this); +} + void Function::print(std::ostream &o, AssemblyAnnotationWriter *AAW) const { SlotMachine SlotTable(getParent()); AssemblyWriter W(o, SlotTable, getParent(), AAW); @@ -1369,6 +1517,18 @@ void Value::dump() const { print(*cerr.stream()); cerr << '\n'; } // Located here because so much of the needed functionality is here. void Type::dump() const { print(*cerr.stream()); cerr << '\n'; } +void +ParamAttrsList::dump() const { + cerr << "PAL[ "; + for (unsigned i = 0; i < attrs.size(); ++i) { + uint16_t index = getParamIndex(i); + ParameterAttributes attrs = getParamAttrs(index); + cerr << "{" << index << "," << attrs << "} "; + } + + cerr << "]\n"; +} + //===----------------------------------------------------------------------===// // SlotMachine Implementation //===----------------------------------------------------------------------===// @@ -1385,6 +1545,7 @@ SlotMachine::SlotMachine(const Module *M) : TheModule(M) ///< Saved for lazy initialization. , TheFunction(0) , FunctionProcessed(false) + , mMap(), mNext(0), fMap(), fNext(0) { } @@ -1394,6 +1555,7 @@ SlotMachine::SlotMachine(const Function *F) : TheModule(F ? F->getParent() : 0) ///< Saved for lazy initialization , TheFunction(F) ///< Saved for lazy initialization , FunctionProcessed(false) + , mMap(), mNext(0), fMap(), fNext(0) { } @@ -1430,6 +1592,7 @@ void SlotMachine::processModule() { // Process the arguments, basic blocks, and instructions of a function. void SlotMachine::processFunction() { SC_DEBUG("begin processFunction!\n"); + fNext = 0; // Add all the function arguments with no names. for(Function::const_arg_iterator AI = TheFunction->arg_begin(), @@ -1471,12 +1634,10 @@ int SlotMachine::getGlobalSlot(const GlobalValue *V) { initialize(); // Find the type plane in the module map - TypedPlanes::const_iterator MI = mMap.find(V->getType()); + ValueMap::const_iterator MI = mMap.find(V); if (MI == mMap.end()) return -1; - - // Lookup the value in the module plane's map. - ValueMap::const_iterator MVI = MI->second.map.find(V); - return MVI != MI->second.map.end() ? int(MVI->second) : -1; + + return MI->second; } @@ -1487,36 +1648,28 @@ int SlotMachine::getLocalSlot(const Value *V) { // Check for uninitialized state and do lazy initialization. initialize(); - // Get the type of the value - const Type *VTy = V->getType(); - - TypedPlanes::const_iterator FI = fMap.find(VTy); + ValueMap::const_iterator FI = fMap.find(V); if (FI == fMap.end()) return -1; - // Lookup the Value in the function and module maps. - ValueMap::const_iterator FVI = FI->second.map.find(V); - - // If the value doesn't exist in the function map, it is a - if (FVI == FI->second.map.end()) return -1; - - return FVI->second; + return FI->second; } /// CreateModuleSlot - Insert the specified GlobalValue* into the slot table. void SlotMachine::CreateModuleSlot(const GlobalValue *V) { assert(V && "Can't insert a null Value into SlotMachine!"); + assert(V->getType() != Type::VoidTy && "Doesn't need a slot!"); + assert(!V->hasName() && "Doesn't need a slot!"); - unsigned DestSlot = 0; - const Type *VTy = V->getType(); - - ValuePlane &PlaneMap = mMap[VTy]; - DestSlot = PlaneMap.map[V] = PlaneMap.next_slot++; + unsigned DestSlot = mNext++; + mMap[V] = DestSlot; - SC_DEBUG(" Inserting value [" << VTy << "] = " << V << " slot=" << + SC_DEBUG(" Inserting value [" << V->getType() << "] = " << V << " slot=" << DestSlot << " ["); - // G = Global, F = Function, o = other - SC_DEBUG((isa(V) ? 'G' : 'F') << "]\n"); + // G = Global, F = Function, A = Alias, o = other + SC_DEBUG((isa(V) ? 'G' : + (isa ? 'F' : + (isa ? 'A' : 'o'))) << "]\n"); } @@ -1525,10 +1678,8 @@ void SlotMachine::CreateFunctionSlot(const Value *V) { const Type *VTy = V->getType(); assert(VTy != Type::VoidTy && !V->hasName() && "Doesn't need a slot!"); - unsigned DestSlot = 0; - - ValuePlane &PlaneMap = fMap[VTy]; - DestSlot = PlaneMap.map[V] = PlaneMap.next_slot++; + unsigned DestSlot = fNext++; + fMap[V] = DestSlot; // G = Global, F = Function, o = other SC_DEBUG(" Inserting value [" << VTy << "] = " << V << " slot=" <<