Index: stable/9/contrib/llvm/include/llvm/DIBuilder.h =================================================================== --- stable/9/contrib/llvm/include/llvm/DIBuilder.h (revision 283018) +++ stable/9/contrib/llvm/include/llvm/DIBuilder.h (revision 283019) @@ -1,697 +1,697 @@ //===--- llvm/DIBuilder.h - Debug Information Builder -----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines a DIBuilder that is useful for creating debugging // information entries in LLVM IR form. // //===----------------------------------------------------------------------===// #ifndef LLVM_DIBUILDER_H #define LLVM_DIBUILDER_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ValueHandle.h" namespace llvm { class BasicBlock; class Instruction; class Function; class Module; class Value; class LLVMContext; class MDNode; class StringRef; class DIBasicType; class DICompileUnit; class DICompositeType; class DIDerivedType; class DIDescriptor; class DIFile; class DIEnumerator; class DIType; class DIArray; class DIGlobalVariable; class DIImportedEntity; class DINameSpace; class DIVariable; class DISubrange; class DILexicalBlockFile; class DILexicalBlock; class DIScope; class DISubprogram; class DITemplateTypeParameter; class DITemplateValueParameter; class DIObjCProperty; class DIBuilder { private: Module &M; LLVMContext & VMContext; MDNode *TempEnumTypes; MDNode *TempRetainTypes; MDNode *TempSubprograms; MDNode *TempGVs; MDNode *TempImportedModules; Function *DeclareFn; // llvm.dbg.declare Function *ValueFn; // llvm.dbg.value SmallVector AllEnumTypes; /// Use TrackingVH to collect RetainTypes, since they can be updated /// later on. SmallVector, 4> AllRetainTypes; SmallVector AllSubprograms; SmallVector AllGVs; SmallVector AllImportedModules; DITemplateValueParameter createTemplateValueParameter(unsigned Tag, DIDescriptor Scope, StringRef Name, DIType Ty, Value *Val, MDNode *File = 0, unsigned LineNo = 0, unsigned ColumnNo = 0); DIBuilder(const DIBuilder &) LLVM_DELETED_FUNCTION; void operator=(const DIBuilder &) LLVM_DELETED_FUNCTION; public: explicit DIBuilder(Module &M); enum ComplexAddrKind { OpPlus=1, OpDeref }; /// finalize - Construct any deferred debug info descriptors. void finalize(); /// createCompileUnit - A CompileUnit provides an anchor for all debugging /// information generated during this instance of compilation. /// @param Lang Source programming language, eg. dwarf::DW_LANG_C99 /// @param File File name /// @param Dir Directory /// @param Producer String identify producer of debugging information. /// Usuall this is a compiler version string. /// @param isOptimized A boolean flag which indicates whether optimization /// is ON or not. /// @param Flags This string lists command line options. This string is /// directly embedded in debug info output which may be used /// by a tool analyzing generated debugging information. /// @param RV This indicates runtime version for languages like /// Objective-C. /// @param SplitName The name of the file that we'll split debug info out /// into. DICompileUnit createCompileUnit(unsigned Lang, StringRef File, StringRef Dir, StringRef Producer, bool isOptimized, StringRef Flags, unsigned RV, StringRef SplitName = StringRef()); /// createFile - Create a file descriptor to hold debugging information /// for a file. DIFile createFile(StringRef Filename, StringRef Directory); /// createEnumerator - Create a single enumerator value. DIEnumerator createEnumerator(StringRef Name, int64_t Val); /// \brief Create a DWARF unspecified type. DIBasicType createUnspecifiedType(StringRef Name); /// \brief Create C++11 nullptr type. DIBasicType createNullPtrType(); /// createBasicType - Create debugging information entry for a basic /// type. /// @param Name Type name. /// @param SizeInBits Size of the type. /// @param AlignInBits Type alignment. /// @param Encoding DWARF encoding code, e.g. dwarf::DW_ATE_float. DIBasicType createBasicType(StringRef Name, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Encoding); /// createQualifiedType - Create debugging information entry for a qualified /// type, e.g. 'const int'. /// @param Tag Tag identifing type, e.g. dwarf::TAG_volatile_type /// @param FromTy Base Type. DIDerivedType createQualifiedType(unsigned Tag, DIType FromTy); /// createPointerType - Create debugging information entry for a pointer. /// @param PointeeTy Type pointed by this pointer. /// @param SizeInBits Size. /// @param AlignInBits Alignment. (optional) /// @param Name Pointer type name. (optional) DIDerivedType createPointerType(DIType PointeeTy, uint64_t SizeInBits, uint64_t AlignInBits = 0, StringRef Name = StringRef()); /// \brief Create debugging information entry for a pointer to member. /// @param PointeeTy Type pointed to by this pointer. /// @param Class Type for which this pointer points to members of. DIDerivedType createMemberPointerType(DIType PointeeTy, DIType Class); /// createReferenceType - Create debugging information entry for a c++ /// style reference or rvalue reference type. DIDerivedType createReferenceType(unsigned Tag, DIType RTy); /// createTypedef - Create debugging information entry for a typedef. /// @param Ty Original type. /// @param Name Typedef name. /// @param File File where this type is defined. /// @param LineNo Line number. /// @param Context The surrounding context for the typedef. DIDerivedType createTypedef(DIType Ty, StringRef Name, DIFile File, unsigned LineNo, DIDescriptor Context); /// createFriend - Create debugging information entry for a 'friend'. DIDerivedType createFriend(DIType Ty, DIType FriendTy); /// createInheritance - Create debugging information entry to establish /// inheritance relationship between two types. /// @param Ty Original type. /// @param BaseTy Base type. Ty is inherits from base. /// @param BaseOffset Base offset. /// @param Flags Flags to describe inheritance attribute, /// e.g. private DIDerivedType createInheritance(DIType Ty, DIType BaseTy, uint64_t BaseOffset, unsigned Flags); /// createMemberType - Create debugging information entry for a member. /// @param Scope Member scope. /// @param Name Member name. /// @param File File where this member is defined. /// @param LineNo Line number. /// @param SizeInBits Member size. /// @param AlignInBits Member alignment. /// @param OffsetInBits Member offset. /// @param Flags Flags to encode member attribute, e.g. private /// @param Ty Parent type. DIDerivedType createMemberType(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNo, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, DIType Ty); /// createStaticMemberType - Create debugging information entry for a /// C++ static data member. /// @param Scope Member scope. /// @param Name Member name. /// @param File File where this member is declared. /// @param LineNo Line number. /// @param Ty Type of the static member. /// @param Flags Flags to encode member attribute, e.g. private. /// @param Val Const initializer of the member. DIDerivedType createStaticMemberType(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNo, DIType Ty, unsigned Flags, llvm::Value *Val); /// createObjCIVar - Create debugging information entry for Objective-C /// instance variable. /// @param Name Member name. /// @param File File where this member is defined. /// @param LineNo Line number. /// @param SizeInBits Member size. /// @param AlignInBits Member alignment. /// @param OffsetInBits Member offset. /// @param Flags Flags to encode member attribute, e.g. private /// @param Ty Parent type. /// @param PropertyName Name of the Objective C property associated with /// this ivar. /// @param PropertyGetterName Name of the Objective C property getter /// selector. /// @param PropertySetterName Name of the Objective C property setter /// selector. /// @param PropertyAttributes Objective C property attributes. DIDerivedType createObjCIVar(StringRef Name, DIFile File, unsigned LineNo, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, DIType Ty, StringRef PropertyName = StringRef(), StringRef PropertyGetterName = StringRef(), StringRef PropertySetterName = StringRef(), unsigned PropertyAttributes = 0); /// createObjCIVar - Create debugging information entry for Objective-C /// instance variable. /// @param Name Member name. /// @param File File where this member is defined. /// @param LineNo Line number. /// @param SizeInBits Member size. /// @param AlignInBits Member alignment. /// @param OffsetInBits Member offset. /// @param Flags Flags to encode member attribute, e.g. private /// @param Ty Parent type. /// @param PropertyNode Property associated with this ivar. DIDerivedType createObjCIVar(StringRef Name, DIFile File, unsigned LineNo, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, DIType Ty, MDNode *PropertyNode); /// createObjCProperty - Create debugging information entry for Objective-C /// property. /// @param Name Property name. /// @param File File where this property is defined. /// @param LineNumber Line number. /// @param GetterName Name of the Objective C property getter selector. /// @param SetterName Name of the Objective C property setter selector. /// @param PropertyAttributes Objective C property attributes. /// @param Ty Type. DIObjCProperty createObjCProperty(StringRef Name, DIFile File, unsigned LineNumber, StringRef GetterName, StringRef SetterName, unsigned PropertyAttributes, DIType Ty); /// createClassType - Create debugging information entry for a class. /// @param Scope Scope in which this class is defined. /// @param Name class name. /// @param File File where this member is defined. /// @param LineNumber Line number. /// @param SizeInBits Member size. /// @param AlignInBits Member alignment. /// @param OffsetInBits Member offset. /// @param Flags Flags to encode member attribute, e.g. private /// @param Elements class members. /// @param VTableHolder Debug info of the base class that contains vtable /// for this type. This is used in /// DW_AT_containing_type. See DWARF documentation /// for more info. /// @param TemplateParms Template type parameters. /// @param UniqueIdentifier A unique identifier for the class. DICompositeType createClassType(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, DIType DerivedFrom, DIArray Elements, DIType VTableHolder = DIType(), MDNode *TemplateParms = 0, StringRef UniqueIdentifier = StringRef()); /// createStructType - Create debugging information entry for a struct. /// @param Scope Scope in which this struct is defined. /// @param Name Struct name. /// @param File File where this member is defined. /// @param LineNumber Line number. /// @param SizeInBits Member size. /// @param AlignInBits Member alignment. /// @param Flags Flags to encode member attribute, e.g. private /// @param Elements Struct elements. /// @param RunTimeLang Optional parameter, Objective-C runtime version. /// @param UniqueIdentifier A unique identifier for the struct. DICompositeType createStructType(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, DIType DerivedFrom, DIArray Elements, unsigned RunTimeLang = 0, DIType VTableHolder = DIType(), StringRef UniqueIdentifier = StringRef()); /// createUnionType - Create debugging information entry for an union. /// @param Scope Scope in which this union is defined. /// @param Name Union name. /// @param File File where this member is defined. /// @param LineNumber Line number. /// @param SizeInBits Member size. /// @param AlignInBits Member alignment. /// @param Flags Flags to encode member attribute, e.g. private /// @param Elements Union elements. /// @param RunTimeLang Optional parameter, Objective-C runtime version. /// @param UniqueIdentifier A unique identifier for the union. DICompositeType createUnionType( DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, DIArray Elements, unsigned RunTimeLang = 0, StringRef UniqueIdentifier = StringRef()); /// createTemplateTypeParameter - Create debugging information for template /// type parameter. /// @param Scope Scope in which this type is defined. /// @param Name Type parameter name. /// @param Ty Parameter type. /// @param File File where this type parameter is defined. /// @param LineNo Line number. /// @param ColumnNo Column Number. DITemplateTypeParameter createTemplateTypeParameter(DIDescriptor Scope, StringRef Name, DIType Ty, MDNode *File = 0, unsigned LineNo = 0, unsigned ColumnNo = 0); /// createTemplateValueParameter - Create debugging information for template /// value parameter. /// @param Scope Scope in which this type is defined. /// @param Name Value parameter name. /// @param Ty Parameter type. /// @param Val Constant parameter value. /// @param File File where this type parameter is defined. /// @param LineNo Line number. /// @param ColumnNo Column Number. DITemplateValueParameter createTemplateValueParameter(DIDescriptor Scope, StringRef Name, DIType Ty, Value *Val, MDNode *File = 0, unsigned LineNo = 0, unsigned ColumnNo = 0); /// \brief Create debugging information for a template template parameter. /// @param Scope Scope in which this type is defined. /// @param Name Value parameter name. /// @param Ty Parameter type. /// @param Val The fully qualified name of the template. /// @param File File where this type parameter is defined. /// @param LineNo Line number. /// @param ColumnNo Column Number. DITemplateValueParameter createTemplateTemplateParameter(DIDescriptor Scope, StringRef Name, DIType Ty, StringRef Val, MDNode *File = 0, unsigned LineNo = 0, unsigned ColumnNo = 0); /// \brief Create debugging information for a template parameter pack. /// @param Scope Scope in which this type is defined. /// @param Name Value parameter name. /// @param Ty Parameter type. /// @param Val An array of types in the pack. /// @param File File where this type parameter is defined. /// @param LineNo Line number. /// @param ColumnNo Column Number. DITemplateValueParameter createTemplateParameterPack(DIDescriptor Scope, StringRef Name, DIType Ty, DIArray Val, MDNode *File = 0, unsigned LineNo = 0, unsigned ColumnNo = 0); /// createArrayType - Create debugging information entry for an array. /// @param Size Array size. /// @param AlignInBits Alignment. /// @param Ty Element type. /// @param Subscripts Subscripts. DICompositeType createArrayType(uint64_t Size, uint64_t AlignInBits, DIType Ty, DIArray Subscripts); /// createVectorType - Create debugging information entry for a vector type. /// @param Size Array size. /// @param AlignInBits Alignment. /// @param Ty Element type. /// @param Subscripts Subscripts. DICompositeType createVectorType(uint64_t Size, uint64_t AlignInBits, DIType Ty, DIArray Subscripts); /// createEnumerationType - Create debugging information entry for an /// enumeration. /// @param Scope Scope in which this enumeration is defined. /// @param Name Union name. /// @param File File where this member is defined. /// @param LineNumber Line number. /// @param SizeInBits Member size. /// @param AlignInBits Member alignment. /// @param Elements Enumeration elements. /// @param UnderlyingType Underlying type of a C++11/ObjC fixed enum. /// @param UniqueIdentifier A unique identifier for the enum. DICompositeType createEnumerationType(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, DIArray Elements, DIType UnderlyingType, StringRef UniqueIdentifier = StringRef()); /// createSubroutineType - Create subroutine type. /// @param File File in which this subroutine is defined. /// @param ParameterTypes An array of subroutine parameter types. This /// includes return type at 0th index. DICompositeType createSubroutineType(DIFile File, DIArray ParameterTypes); /// createArtificialType - Create a new DIType with "artificial" flag set. DIType createArtificialType(DIType Ty); /// createObjectPointerType - Create a new DIType with the "object pointer" /// flag set. DIType createObjectPointerType(DIType Ty); /// createForwardDecl - Create a temporary forward-declared type. DICompositeType createForwardDecl(unsigned Tag, StringRef Name, DIDescriptor Scope, DIFile F, unsigned Line, unsigned RuntimeLang = 0, uint64_t SizeInBits = 0, uint64_t AlignInBits = 0, StringRef UniqueIdentifier = StringRef()); /// retainType - Retain DIType in a module even if it is not referenced /// through debug info anchors. void retainType(DIType T); - /// createUnspecifiedParameter - Create unspeicified type descriptor + /// createUnspecifiedParameter - Create unspecified type descriptor /// for a subroutine type. DIDescriptor createUnspecifiedParameter(); /// getOrCreateArray - Get a DIArray, create one if required. DIArray getOrCreateArray(ArrayRef Elements); /// getOrCreateSubrange - Create a descriptor for a value range. This /// implicitly uniques the values returned. DISubrange getOrCreateSubrange(int64_t Lo, int64_t Count); /// createGlobalVariable - Create a new descriptor for the specified global. /// @param Name Name of the variable. /// @param File File where this variable is defined. /// @param LineNo Line number. /// @param Ty Variable Type. /// @param isLocalToUnit Boolean flag indicate whether this variable is /// externally visible or not. /// @param Val llvm::Value of the variable. DIGlobalVariable createGlobalVariable(StringRef Name, DIFile File, unsigned LineNo, DIType Ty, bool isLocalToUnit, llvm::Value *Val); /// \brief Create a new descriptor for the specified global. /// @param Name Name of the variable. /// @param LinkageName Mangled variable name. /// @param File File where this variable is defined. /// @param LineNo Line number. /// @param Ty Variable Type. /// @param isLocalToUnit Boolean flag indicate whether this variable is /// externally visible or not. /// @param Val llvm::Value of the variable. DIGlobalVariable createGlobalVariable(StringRef Name, StringRef LinkageName, DIFile File, unsigned LineNo, DIType Ty, bool isLocalToUnit, llvm::Value *Val); /// createStaticVariable - Create a new descriptor for the specified /// variable. /// @param Context Variable scope. /// @param Name Name of the variable. /// @param LinkageName Mangled name of the variable. /// @param File File where this variable is defined. /// @param LineNo Line number. /// @param Ty Variable Type. /// @param isLocalToUnit Boolean flag indicate whether this variable is /// externally visible or not. /// @param Val llvm::Value of the variable. /// @param Decl Reference to the corresponding declaration. DIGlobalVariable createStaticVariable(DIDescriptor Context, StringRef Name, StringRef LinkageName, DIFile File, unsigned LineNo, DIType Ty, bool isLocalToUnit, llvm::Value *Val, MDNode *Decl = NULL); /// createLocalVariable - Create a new descriptor for the specified /// local variable. /// @param Tag Dwarf TAG. Usually DW_TAG_auto_variable or /// DW_TAG_arg_variable. /// @param Scope Variable scope. /// @param Name Variable name. /// @param File File where this variable is defined. /// @param LineNo Line number. /// @param Ty Variable Type /// @param AlwaysPreserve Boolean. Set to true if debug info for this /// variable should be preserved in optimized build. /// @param Flags Flags, e.g. artificial variable. /// @param ArgNo If this variable is an argument then this argument's /// number. 1 indicates 1st argument. DIVariable createLocalVariable(unsigned Tag, DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNo, DIType Ty, bool AlwaysPreserve = false, unsigned Flags = 0, unsigned ArgNo = 0); /// createComplexVariable - Create a new descriptor for the specified /// variable which has a complex address expression for its address. /// @param Tag Dwarf TAG. Usually DW_TAG_auto_variable or /// DW_TAG_arg_variable. /// @param Scope Variable scope. /// @param Name Variable name. /// @param F File where this variable is defined. /// @param LineNo Line number. /// @param Ty Variable Type /// @param Addr An array of complex address operations. /// @param ArgNo If this variable is an argument then this argument's /// number. 1 indicates 1st argument. DIVariable createComplexVariable(unsigned Tag, DIDescriptor Scope, StringRef Name, DIFile F, unsigned LineNo, DIType Ty, ArrayRef Addr, unsigned ArgNo = 0); /// createFunction - Create a new descriptor for the specified subprogram. /// See comments in DISubprogram for descriptions of these fields. /// @param Scope Function scope. /// @param Name Function name. /// @param LinkageName Mangled function name. /// @param File File where this variable is defined. /// @param LineNo Line number. /// @param Ty Function type. /// @param isLocalToUnit True if this function is not externally visible.. /// @param isDefinition True if this is a function definition. /// @param ScopeLine Set to the beginning of the scope this starts /// @param Flags e.g. is this function prototyped or not. /// This flags are used to emit dwarf attributes. /// @param isOptimized True if optimization is ON. /// @param Fn llvm::Function pointer. /// @param TParam Function template parameters. DISubprogram createFunction(DIDescriptor Scope, StringRef Name, StringRef LinkageName, DIFile File, unsigned LineNo, DICompositeType Ty, bool isLocalToUnit, bool isDefinition, unsigned ScopeLine, unsigned Flags = 0, bool isOptimized = false, Function *Fn = 0, MDNode *TParam = 0, MDNode *Decl = 0); /// FIXME: this is added for dragonegg. Once we update dragonegg /// to call resolve function, this will be removed. DISubprogram createFunction(DIScopeRef Scope, StringRef Name, StringRef LinkageName, DIFile File, unsigned LineNo, DICompositeType Ty, bool isLocalToUnit, bool isDefinition, unsigned ScopeLine, unsigned Flags = 0, bool isOptimized = false, Function *Fn = 0, MDNode *TParam = 0, MDNode *Decl = 0); /// createMethod - Create a new descriptor for the specified C++ method. /// See comments in DISubprogram for descriptions of these fields. /// @param Scope Function scope. /// @param Name Function name. /// @param LinkageName Mangled function name. /// @param File File where this variable is defined. /// @param LineNo Line number. /// @param Ty Function type. /// @param isLocalToUnit True if this function is not externally visible.. /// @param isDefinition True if this is a function definition. /// @param Virtuality Attributes describing virtualness. e.g. pure /// virtual function. /// @param VTableIndex Index no of this method in virtual table. /// @param VTableHolder Type that holds vtable. /// @param Flags e.g. is this function prototyped or not. /// This flags are used to emit dwarf attributes. /// @param isOptimized True if optimization is ON. /// @param Fn llvm::Function pointer. /// @param TParam Function template parameters. DISubprogram createMethod(DIDescriptor Scope, StringRef Name, StringRef LinkageName, DIFile File, unsigned LineNo, DICompositeType Ty, bool isLocalToUnit, bool isDefinition, unsigned Virtuality = 0, unsigned VTableIndex = 0, DIType VTableHolder = DIType(), unsigned Flags = 0, bool isOptimized = false, Function *Fn = 0, MDNode *TParam = 0); /// createNameSpace - This creates new descriptor for a namespace /// with the specified parent scope. /// @param Scope Namespace scope /// @param Name Name of this namespace /// @param File Source file /// @param LineNo Line number DINameSpace createNameSpace(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNo); /// createLexicalBlockFile - This creates a descriptor for a lexical /// block with a new file attached. This merely extends the existing /// lexical block as it crosses a file. /// @param Scope Lexical block. /// @param File Source file. DILexicalBlockFile createLexicalBlockFile(DIDescriptor Scope, DIFile File); /// createLexicalBlock - This creates a descriptor for a lexical block /// with the specified parent context. /// @param Scope Parent lexical scope. /// @param File Source file /// @param Line Line number /// @param Col Column number DILexicalBlock createLexicalBlock(DIDescriptor Scope, DIFile File, unsigned Line, unsigned Col); /// \brief Create a descriptor for an imported module. /// @param Context The scope this module is imported into /// @param NS The namespace being imported here /// @param Line Line number DIImportedEntity createImportedModule(DIScope Context, DINameSpace NS, unsigned Line, StringRef Name = StringRef()); /// \brief Create a descriptor for an imported module. /// @param Context The scope this module is imported into /// @param NS An aliased namespace /// @param Line Line number DIImportedEntity createImportedModule(DIScope Context, DIImportedEntity NS, unsigned Line, StringRef Name); /// \brief Create a descriptor for an imported function. /// @param Context The scope this module is imported into /// @param Decl The declaration (or definition) of a function, type, or /// variable /// @param Line Line number DIImportedEntity createImportedDeclaration(DIScope Context, DIDescriptor Decl, unsigned Line); /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. /// @param Storage llvm::Value of the variable /// @param VarInfo Variable's debug info descriptor. /// @param InsertAtEnd Location for the new intrinsic. Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo, BasicBlock *InsertAtEnd); /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. /// @param Storage llvm::Value of the variable /// @param VarInfo Variable's debug info descriptor. /// @param InsertBefore Location for the new intrinsic. Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo, Instruction *InsertBefore); /// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. /// @param Val llvm::Value of the variable /// @param Offset Offset /// @param VarInfo Variable's debug info descriptor. /// @param InsertAtEnd Location for the new intrinsic. Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, DIVariable VarInfo, BasicBlock *InsertAtEnd); /// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. /// @param Val llvm::Value of the variable /// @param Offset Offset /// @param VarInfo Variable's debug info descriptor. /// @param InsertBefore Location for the new intrinsic. Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, DIVariable VarInfo, Instruction *InsertBefore); }; } // end namespace llvm #endif Index: stable/9/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp =================================================================== --- stable/9/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp (revision 283018) +++ stable/9/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp (revision 283019) @@ -1,1981 +1,1984 @@ //===-- llvm/CodeGen/DwarfCompileUnit.cpp - Dwarf Compile Unit ------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file contains support for constructing a dwarf compile unit. // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "dwarfdebug" #include "DwarfCompileUnit.h" #include "DwarfAccelTable.h" #include "DwarfDebug.h" #include "llvm/ADT/APFloat.h" #include "llvm/DIBuilder.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Instructions.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" #include "llvm/Target/Mangler.h" #include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetRegisterInfo.h" using namespace llvm; /// CompileUnit - Compile unit constructor. CompileUnit::CompileUnit(unsigned UID, DIE *D, DICompileUnit Node, AsmPrinter *A, DwarfDebug *DW, DwarfUnits *DWU) : UniqueID(UID), Node(Node), CUDie(D), Asm(A), DD(DW), DU(DWU), IndexTyDie(0), DebugInfoOffset(0) { DIEIntegerOne = new (DIEValueAllocator) DIEInteger(1); insertDIE(Node, D); } /// ~CompileUnit - Destructor for compile unit. CompileUnit::~CompileUnit() { for (unsigned j = 0, M = DIEBlocks.size(); j < M; ++j) DIEBlocks[j]->~DIEBlock(); } /// createDIEEntry - Creates a new DIEEntry to be a proxy for a debug /// information entry. DIEEntry *CompileUnit::createDIEEntry(DIE *Entry) { DIEEntry *Value = new (DIEValueAllocator) DIEEntry(Entry); return Value; } /// getDefaultLowerBound - Return the default lower bound for an array. If the /// DWARF version doesn't handle the language, return -1. int64_t CompileUnit::getDefaultLowerBound() const { switch (getLanguage()) { default: break; case dwarf::DW_LANG_C89: case dwarf::DW_LANG_C99: case dwarf::DW_LANG_C: case dwarf::DW_LANG_C_plus_plus: case dwarf::DW_LANG_ObjC: case dwarf::DW_LANG_ObjC_plus_plus: return 0; case dwarf::DW_LANG_Fortran77: case dwarf::DW_LANG_Fortran90: case dwarf::DW_LANG_Fortran95: return 1; // The languages below have valid values only if the DWARF version >= 4. case dwarf::DW_LANG_Java: case dwarf::DW_LANG_Python: case dwarf::DW_LANG_UPC: case dwarf::DW_LANG_D: if (dwarf::DWARF_VERSION >= 4) return 0; break; case dwarf::DW_LANG_Ada83: case dwarf::DW_LANG_Ada95: case dwarf::DW_LANG_Cobol74: case dwarf::DW_LANG_Cobol85: case dwarf::DW_LANG_Modula2: case dwarf::DW_LANG_Pascal83: case dwarf::DW_LANG_PLI: if (dwarf::DWARF_VERSION >= 4) return 1; break; } return -1; } /// Check whether the DIE for this MDNode can be shared across CUs. static bool isShareableAcrossCUs(DIDescriptor D) { // When the MDNode can be part of the type system, the DIE can be // shared across CUs. return D.isType() || (D.isSubprogram() && !DISubprogram(D).isDefinition()); } /// getDIE - Returns the debug information entry map slot for the /// specified debug variable. We delegate the request to DwarfDebug /// when the DIE for this MDNode can be shared across CUs. The mappings /// will be kept in DwarfDebug for shareable DIEs. DIE *CompileUnit::getDIE(DIDescriptor D) const { if (isShareableAcrossCUs(D)) return DD->getDIE(D); return MDNodeToDieMap.lookup(D); } /// insertDIE - Insert DIE into the map. We delegate the request to DwarfDebug /// when the DIE for this MDNode can be shared across CUs. The mappings /// will be kept in DwarfDebug for shareable DIEs. void CompileUnit::insertDIE(DIDescriptor Desc, DIE *D) { if (isShareableAcrossCUs(Desc)) { DD->insertDIE(Desc, D); return; } MDNodeToDieMap.insert(std::make_pair(Desc, D)); } /// addFlag - Add a flag that is true. void CompileUnit::addFlag(DIE *Die, dwarf::Attribute Attribute) { if (DD->getDwarfVersion() >= 4) Die->addValue(Attribute, dwarf::DW_FORM_flag_present, DIEIntegerOne); else Die->addValue(Attribute, dwarf::DW_FORM_flag, DIEIntegerOne); } /// addUInt - Add an unsigned integer attribute data and value. /// void CompileUnit::addUInt(DIE *Die, dwarf::Attribute Attribute, Optional Form, uint64_t Integer) { if (!Form) Form = DIEInteger::BestForm(false, Integer); DIEValue *Value = Integer == 1 ? DIEIntegerOne : new (DIEValueAllocator) DIEInteger(Integer); Die->addValue(Attribute, *Form, Value); } void CompileUnit::addUInt(DIEBlock *Block, dwarf::Form Form, uint64_t Integer) { addUInt(Block, (dwarf::Attribute)0, Form, Integer); } /// addSInt - Add an signed integer attribute data and value. /// void CompileUnit::addSInt(DIE *Die, dwarf::Attribute Attribute, Optional Form, int64_t Integer) { if (!Form) Form = DIEInteger::BestForm(true, Integer); DIEValue *Value = new (DIEValueAllocator) DIEInteger(Integer); Die->addValue(Attribute, *Form, Value); } void CompileUnit::addSInt(DIEBlock *Die, Optional Form, int64_t Integer) { addSInt(Die, (dwarf::Attribute)0, Form, Integer); } /// addString - Add a string attribute data and value. We always emit a /// reference to the string pool instead of immediate strings so that DIEs have /// more predictable sizes. In the case of split dwarf we emit an index /// into another table which gets us the static offset into the string /// table. void CompileUnit::addString(DIE *Die, dwarf::Attribute Attribute, StringRef String) { DIEValue *Value; dwarf::Form Form; if (!DD->useSplitDwarf()) { MCSymbol *Symb = DU->getStringPoolEntry(String); if (Asm->needsRelocationsForDwarfStringPool()) Value = new (DIEValueAllocator) DIELabel(Symb); else { MCSymbol *StringPool = DU->getStringPoolSym(); Value = new (DIEValueAllocator) DIEDelta(Symb, StringPool); } Form = dwarf::DW_FORM_strp; } else { unsigned idx = DU->getStringPoolIndex(String); Value = new (DIEValueAllocator) DIEInteger(idx); Form = dwarf::DW_FORM_GNU_str_index; } DIEValue *Str = new (DIEValueAllocator) DIEString(Value, String); Die->addValue(Attribute, Form, Str); } /// addLocalString - Add a string attribute data and value. This is guaranteed /// to be in the local string pool instead of indirected. void CompileUnit::addLocalString(DIE *Die, dwarf::Attribute Attribute, StringRef String) { MCSymbol *Symb = DU->getStringPoolEntry(String); DIEValue *Value; if (Asm->needsRelocationsForDwarfStringPool()) Value = new (DIEValueAllocator) DIELabel(Symb); else { MCSymbol *StringPool = DU->getStringPoolSym(); Value = new (DIEValueAllocator) DIEDelta(Symb, StringPool); } Die->addValue(Attribute, dwarf::DW_FORM_strp, Value); } /// addExpr - Add a Dwarf expression attribute data and value. /// void CompileUnit::addExpr(DIEBlock *Die, dwarf::Form Form, const MCExpr *Expr) { DIEValue *Value = new (DIEValueAllocator) DIEExpr(Expr); Die->addValue((dwarf::Attribute)0, Form, Value); } /// addLabel - Add a Dwarf label attribute data and value. /// void CompileUnit::addLabel(DIE *Die, dwarf::Attribute Attribute, dwarf::Form Form, const MCSymbol *Label) { DIEValue *Value = new (DIEValueAllocator) DIELabel(Label); Die->addValue(Attribute, Form, Value); } void CompileUnit::addLabel(DIEBlock *Die, dwarf::Form Form, const MCSymbol *Label) { addLabel(Die, (dwarf::Attribute)0, Form, Label); } /// addSectionLabel - Add a Dwarf section label attribute data and value. /// void CompileUnit::addSectionLabel(DIE *Die, dwarf::Attribute Attribute, const MCSymbol *Label) { if (DD->getDwarfVersion() >= 4) addLabel(Die, Attribute, dwarf::DW_FORM_sec_offset, Label); else addLabel(Die, Attribute, dwarf::DW_FORM_data4, Label); } /// addSectionOffset - Add an offset into a section attribute data and value. /// void CompileUnit::addSectionOffset(DIE *Die, dwarf::Attribute Attribute, uint64_t Integer) { if (DD->getDwarfVersion() >= 4) addUInt(Die, Attribute, dwarf::DW_FORM_sec_offset, Integer); else addUInt(Die, Attribute, dwarf::DW_FORM_data4, Integer); } /// addLabelAddress - Add a dwarf label attribute data and value using /// DW_FORM_addr or DW_FORM_GNU_addr_index. /// void CompileUnit::addLabelAddress(DIE *Die, dwarf::Attribute Attribute, MCSymbol *Label) { if (Label) DD->addArangeLabel(SymbolCU(this, Label)); if (!DD->useSplitDwarf()) { if (Label != NULL) { DIEValue *Value = new (DIEValueAllocator) DIELabel(Label); Die->addValue(Attribute, dwarf::DW_FORM_addr, Value); } else { DIEValue *Value = new (DIEValueAllocator) DIEInteger(0); Die->addValue(Attribute, dwarf::DW_FORM_addr, Value); } } else { unsigned idx = DU->getAddrPoolIndex(Label); DIEValue *Value = new (DIEValueAllocator) DIEInteger(idx); Die->addValue(Attribute, dwarf::DW_FORM_GNU_addr_index, Value); } } /// addOpAddress - Add a dwarf op address data and value using the /// form given and an op of either DW_FORM_addr or DW_FORM_GNU_addr_index. /// void CompileUnit::addOpAddress(DIEBlock *Die, const MCSymbol *Sym) { DD->addArangeLabel(SymbolCU(this, Sym)); if (!DD->useSplitDwarf()) { addUInt(Die, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); addLabel(Die, dwarf::DW_FORM_udata, Sym); } else { addUInt(Die, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_addr_index); addUInt(Die, dwarf::DW_FORM_GNU_addr_index, DU->getAddrPoolIndex(Sym)); } } /// addSectionDelta - Add a section label delta attribute data and value. /// void CompileUnit::addSectionDelta(DIE *Die, dwarf::Attribute Attribute, const MCSymbol *Hi, const MCSymbol *Lo) { DIEValue *Value = new (DIEValueAllocator) DIEDelta(Hi, Lo); if (DD->getDwarfVersion() >= 4) Die->addValue(Attribute, dwarf::DW_FORM_sec_offset, Value); else Die->addValue(Attribute, dwarf::DW_FORM_data4, Value); } /// addDIEEntry - Add a DIE attribute data and value. /// void CompileUnit::addDIEEntry(DIE *Die, dwarf::Attribute Attribute, DIE *Entry) { addDIEEntry(Die, Attribute, createDIEEntry(Entry)); } void CompileUnit::addDIEEntry(DIE *Die, dwarf::Attribute Attribute, DIEEntry *Entry) { const DIE *DieCU = Die->getCompileUnitOrNull(); const DIE *EntryCU = Entry->getEntry()->getCompileUnitOrNull(); if (!DieCU) // We assume that Die belongs to this CU, if it is not linked to any CU yet. DieCU = getCUDie(); if (!EntryCU) EntryCU = getCUDie(); Die->addValue(Attribute, EntryCU == DieCU ? dwarf::DW_FORM_ref4 : dwarf::DW_FORM_ref_addr, Entry); } /// Create a DIE with the given Tag, add the DIE to its parent, and /// call insertDIE if MD is not null. DIE *CompileUnit::createAndAddDIE(unsigned Tag, DIE &Parent, DIDescriptor N) { DIE *Die = new DIE(Tag); Parent.addChild(Die); if (N) insertDIE(N, Die); return Die; } /// addBlock - Add block data. /// void CompileUnit::addBlock(DIE *Die, dwarf::Attribute Attribute, DIEBlock *Block) { Block->ComputeSize(Asm); DIEBlocks.push_back(Block); // Memoize so we can call the destructor later on. Die->addValue(Attribute, Block->BestForm(), Block); } /// addSourceLine - Add location information to specified debug information /// entry. void CompileUnit::addSourceLine(DIE *Die, DIVariable V) { // Verify variable. if (!V.isVariable()) return; unsigned Line = V.getLineNumber(); if (Line == 0) return; unsigned FileID = DD->getOrCreateSourceID(V.getContext().getFilename(), V.getContext().getDirectory(), getUniqueID()); assert(FileID && "Invalid file id"); addUInt(Die, dwarf::DW_AT_decl_file, None, FileID); addUInt(Die, dwarf::DW_AT_decl_line, None, Line); } /// addSourceLine - Add location information to specified debug information /// entry. void CompileUnit::addSourceLine(DIE *Die, DIGlobalVariable G) { // Verify global variable. if (!G.isGlobalVariable()) return; unsigned Line = G.getLineNumber(); if (Line == 0) return; unsigned FileID = DD->getOrCreateSourceID(G.getFilename(), G.getDirectory(), getUniqueID()); assert(FileID && "Invalid file id"); addUInt(Die, dwarf::DW_AT_decl_file, None, FileID); addUInt(Die, dwarf::DW_AT_decl_line, None, Line); } /// addSourceLine - Add location information to specified debug information /// entry. void CompileUnit::addSourceLine(DIE *Die, DISubprogram SP) { // Verify subprogram. if (!SP.isSubprogram()) return; // If the line number is 0, don't add it. unsigned Line = SP.getLineNumber(); if (Line == 0) return; unsigned FileID = DD->getOrCreateSourceID(SP.getFilename(), SP.getDirectory(), getUniqueID()); assert(FileID && "Invalid file id"); addUInt(Die, dwarf::DW_AT_decl_file, None, FileID); addUInt(Die, dwarf::DW_AT_decl_line, None, Line); } /// addSourceLine - Add location information to specified debug information /// entry. void CompileUnit::addSourceLine(DIE *Die, DIType Ty) { // Verify type. if (!Ty.isType()) return; unsigned Line = Ty.getLineNumber(); if (Line == 0) return; unsigned FileID = DD->getOrCreateSourceID(Ty.getFilename(), Ty.getDirectory(), getUniqueID()); assert(FileID && "Invalid file id"); addUInt(Die, dwarf::DW_AT_decl_file, None, FileID); addUInt(Die, dwarf::DW_AT_decl_line, None, Line); } /// addSourceLine - Add location information to specified debug information /// entry. void CompileUnit::addSourceLine(DIE *Die, DIObjCProperty Ty) { // Verify type. if (!Ty.isObjCProperty()) return; unsigned Line = Ty.getLineNumber(); if (Line == 0) return; DIFile File = Ty.getFile(); unsigned FileID = DD->getOrCreateSourceID(File.getFilename(), File.getDirectory(), getUniqueID()); assert(FileID && "Invalid file id"); addUInt(Die, dwarf::DW_AT_decl_file, None, FileID); addUInt(Die, dwarf::DW_AT_decl_line, None, Line); } /// addSourceLine - Add location information to specified debug information /// entry. void CompileUnit::addSourceLine(DIE *Die, DINameSpace NS) { // Verify namespace. if (!NS.Verify()) return; unsigned Line = NS.getLineNumber(); if (Line == 0) return; StringRef FN = NS.getFilename(); unsigned FileID = DD->getOrCreateSourceID(FN, NS.getDirectory(), getUniqueID()); assert(FileID && "Invalid file id"); addUInt(Die, dwarf::DW_AT_decl_file, None, FileID); addUInt(Die, dwarf::DW_AT_decl_line, None, Line); } /// addVariableAddress - Add DW_AT_location attribute for a /// DbgVariable based on provided MachineLocation. void CompileUnit::addVariableAddress(const DbgVariable &DV, DIE *Die, MachineLocation Location) { if (DV.variableHasComplexAddress()) addComplexAddress(DV, Die, dwarf::DW_AT_location, Location); else if (DV.isBlockByrefVariable()) addBlockByrefAddress(DV, Die, dwarf::DW_AT_location, Location); else addAddress(Die, dwarf::DW_AT_location, Location, DV.getVariable().isIndirect()); } /// addRegisterOp - Add register operand. void CompileUnit::addRegisterOp(DIEBlock *TheDie, unsigned Reg) { const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); unsigned DWReg = RI->getDwarfRegNum(Reg, false); if (DWReg < 32) addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + DWReg); else { addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_regx); addUInt(TheDie, dwarf::DW_FORM_udata, DWReg); } } /// addRegisterOffset - Add register offset. void CompileUnit::addRegisterOffset(DIEBlock *TheDie, unsigned Reg, int64_t Offset) { const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); unsigned DWReg = RI->getDwarfRegNum(Reg, false); const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo(); if (Reg == TRI->getFrameRegister(*Asm->MF)) // If variable offset is based in frame register then use fbreg. addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_fbreg); else if (DWReg < 32) addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + DWReg); else { addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_bregx); addUInt(TheDie, dwarf::DW_FORM_udata, DWReg); } addSInt(TheDie, dwarf::DW_FORM_sdata, Offset); } /// addAddress - Add an address attribute to a die based on the location /// provided. void CompileUnit::addAddress(DIE *Die, dwarf::Attribute Attribute, const MachineLocation &Location, bool Indirect) { DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); if (Location.isReg() && !Indirect) addRegisterOp(Block, Location.getReg()); else { addRegisterOffset(Block, Location.getReg(), Location.getOffset()); if (Indirect && !Location.isReg()) { addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); } } // Now attach the location information to the DIE. addBlock(Die, Attribute, Block); } /// addComplexAddress - Start with the address based on the location provided, /// and generate the DWARF information necessary to find the actual variable /// given the extra address information encoded in the DIVariable, starting from /// the starting location. Add the DWARF information to the die. /// void CompileUnit::addComplexAddress(const DbgVariable &DV, DIE *Die, dwarf::Attribute Attribute, const MachineLocation &Location) { DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); unsigned N = DV.getNumAddrElements(); unsigned i = 0; if (Location.isReg()) { if (N >= 2 && DV.getAddrElement(0) == DIBuilder::OpPlus) { // If first address element is OpPlus then emit // DW_OP_breg + Offset instead of DW_OP_reg + Offset. addRegisterOffset(Block, Location.getReg(), DV.getAddrElement(1)); i = 2; } else addRegisterOp(Block, Location.getReg()); } else addRegisterOffset(Block, Location.getReg(), Location.getOffset()); for (; i < N; ++i) { uint64_t Element = DV.getAddrElement(i); if (Element == DIBuilder::OpPlus) { addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); addUInt(Block, dwarf::DW_FORM_udata, DV.getAddrElement(++i)); } else if (Element == DIBuilder::OpDeref) { if (!Location.isReg()) addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); } else llvm_unreachable("unknown DIBuilder Opcode"); } // Now attach the location information to the DIE. addBlock(Die, Attribute, Block); } /* Byref variables, in Blocks, are declared by the programmer as "SomeType VarName;", but the compiler creates a __Block_byref_x_VarName struct, and gives the variable VarName either the struct, or a pointer to the struct, as its type. This is necessary for various behind-the-scenes things the compiler needs to do with by-reference variables in Blocks. However, as far as the original *programmer* is concerned, the variable should still have type 'SomeType', as originally declared. The function getBlockByrefType dives into the __Block_byref_x_VarName struct to find the original type of the variable, which is then assigned to the variable's Debug Information Entry as its real type. So far, so good. However now the debugger will expect the variable VarName to have the type SomeType. So we need the location attribute for the variable to be an expression that explains to the debugger how to navigate through the pointers and struct to find the actual variable of type SomeType. The following function does just that. We start by getting the "normal" location for the variable. This will be the location of either the struct __Block_byref_x_VarName or the pointer to the struct __Block_byref_x_VarName. The struct will look something like: struct __Block_byref_x_VarName { ... struct __Block_byref_x_VarName *forwarding; ... SomeType VarName; ... }; If we are given the struct directly (as our starting point) we need to tell the debugger to: 1). Add the offset of the forwarding field. 2). Follow that pointer to get the real __Block_byref_x_VarName struct to use (the real one may have been copied onto the heap). 3). Add the offset for the field VarName, to find the actual variable. If we started with a pointer to the struct, then we need to dereference that pointer first, before the other steps. Translating this into DWARF ops, we will need to append the following to the current location description for the variable: DW_OP_deref -- optional, if we start with a pointer DW_OP_plus_uconst DW_OP_deref DW_OP_plus_uconst That is what this function does. */ /// addBlockByrefAddress - Start with the address based on the location /// provided, and generate the DWARF information necessary to find the /// actual Block variable (navigating the Block struct) based on the /// starting location. Add the DWARF information to the die. For /// more information, read large comment just above here. /// void CompileUnit::addBlockByrefAddress(const DbgVariable &DV, DIE *Die, dwarf::Attribute Attribute, const MachineLocation &Location) { DIType Ty = DV.getType(); DIType TmpTy = Ty; uint16_t Tag = Ty.getTag(); bool isPointer = false; StringRef varName = DV.getName(); if (Tag == dwarf::DW_TAG_pointer_type) { DIDerivedType DTy(Ty); TmpTy = resolve(DTy.getTypeDerivedFrom()); isPointer = true; } DICompositeType blockStruct(TmpTy); // Find the __forwarding field and the variable field in the __Block_byref // struct. DIArray Fields = blockStruct.getTypeArray(); DIDerivedType varField; DIDerivedType forwardingField; for (unsigned i = 0, N = Fields.getNumElements(); i < N; ++i) { DIDerivedType DT(Fields.getElement(i)); StringRef fieldName = DT.getName(); if (fieldName == "__forwarding") forwardingField = DT; else if (fieldName == varName) varField = DT; } // Get the offsets for the forwarding field and the variable field. unsigned forwardingFieldOffset = forwardingField.getOffsetInBits() >> 3; unsigned varFieldOffset = varField.getOffsetInBits() >> 2; // Decode the original location, and use that as the start of the byref // variable's location. DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); if (Location.isReg()) addRegisterOp(Block, Location.getReg()); else addRegisterOffset(Block, Location.getReg(), Location.getOffset()); // If we started with a pointer to the __Block_byref... struct, then // the first thing we need to do is dereference the pointer (DW_OP_deref). if (isPointer) addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); // Next add the offset for the '__forwarding' field: // DW_OP_plus_uconst ForwardingFieldOffset. Note there's no point in // adding the offset if it's 0. if (forwardingFieldOffset > 0) { addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); addUInt(Block, dwarf::DW_FORM_udata, forwardingFieldOffset); } // Now dereference the __forwarding field to get to the real __Block_byref // struct: DW_OP_deref. addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); // Now that we've got the real __Block_byref... struct, add the offset // for the variable's field to get to the location of the actual variable: // DW_OP_plus_uconst varFieldOffset. Again, don't add if it's 0. if (varFieldOffset > 0) { addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); addUInt(Block, dwarf::DW_FORM_udata, varFieldOffset); } // Now attach the location information to the DIE. addBlock(Die, Attribute, Block); } /// isTypeSigned - Return true if the type is signed. static bool isTypeSigned(DwarfDebug *DD, DIType Ty, int *SizeInBits) { if (Ty.isDerivedType()) return isTypeSigned(DD, DD->resolve(DIDerivedType(Ty).getTypeDerivedFrom()), SizeInBits); if (Ty.isBasicType()) if (DIBasicType(Ty).getEncoding() == dwarf::DW_ATE_signed || DIBasicType(Ty).getEncoding() == dwarf::DW_ATE_signed_char) { *SizeInBits = Ty.getSizeInBits(); return true; } return false; } /// Return true if type encoding is unsigned. static bool isUnsignedDIType(DwarfDebug *DD, DIType Ty) { DIDerivedType DTy(Ty); if (DTy.isDerivedType()) return isUnsignedDIType(DD, DD->resolve(DTy.getTypeDerivedFrom())); DIBasicType BTy(Ty); if (BTy.isBasicType()) { unsigned Encoding = BTy.getEncoding(); if (Encoding == dwarf::DW_ATE_unsigned || Encoding == dwarf::DW_ATE_unsigned_char || Encoding == dwarf::DW_ATE_boolean) return true; } return false; } /// If this type is derived from a base type then return base type size. static uint64_t getBaseTypeSize(DwarfDebug *DD, DIDerivedType Ty) { unsigned Tag = Ty.getTag(); if (Tag != dwarf::DW_TAG_member && Tag != dwarf::DW_TAG_typedef && Tag != dwarf::DW_TAG_const_type && Tag != dwarf::DW_TAG_volatile_type && Tag != dwarf::DW_TAG_restrict_type) return Ty.getSizeInBits(); DIType BaseType = DD->resolve(Ty.getTypeDerivedFrom()); // If this type is not derived from any type then take conservative approach. if (!BaseType.isValid()) return Ty.getSizeInBits(); // If this is a derived type, go ahead and get the base type, unless it's a // reference then it's just the size of the field. Pointer types have no need // of this since they're a different type of qualification on the type. if (BaseType.getTag() == dwarf::DW_TAG_reference_type || BaseType.getTag() == dwarf::DW_TAG_rvalue_reference_type) return Ty.getSizeInBits(); if (BaseType.isDerivedType()) return getBaseTypeSize(DD, DIDerivedType(BaseType)); return BaseType.getSizeInBits(); } /// addConstantValue - Add constant value entry in variable DIE. void CompileUnit::addConstantValue(DIE *Die, const MachineOperand &MO, DIType Ty) { // FIXME: This is a bit conservative/simple - it emits negative values at // their maximum bit width which is a bit unfortunate (& doesn't prefer // udata/sdata over dataN as suggested by the DWARF spec) assert(MO.isImm() && "Invalid machine operand!"); int SizeInBits = -1; bool SignedConstant = isTypeSigned(DD, Ty, &SizeInBits); dwarf::Form Form; // If we're a signed constant definitely use sdata. if (SignedConstant) { addSInt(Die, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, MO.getImm()); return; } // Else use data for now unless it's larger than we can deal with. switch (SizeInBits) { case 8: Form = dwarf::DW_FORM_data1; break; case 16: Form = dwarf::DW_FORM_data2; break; case 32: Form = dwarf::DW_FORM_data4; break; case 64: Form = dwarf::DW_FORM_data8; break; default: Form = dwarf::DW_FORM_udata; addUInt(Die, dwarf::DW_AT_const_value, Form, MO.getImm()); return; } addUInt(Die, dwarf::DW_AT_const_value, Form, MO.getImm()); } /// addConstantFPValue - Add constant value entry in variable DIE. void CompileUnit::addConstantFPValue(DIE *Die, const MachineOperand &MO) { assert(MO.isFPImm() && "Invalid machine operand!"); DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); APFloat FPImm = MO.getFPImm()->getValueAPF(); // Get the raw data form of the floating point. const APInt FltVal = FPImm.bitcastToAPInt(); const char *FltPtr = (const char *)FltVal.getRawData(); int NumBytes = FltVal.getBitWidth() / 8; // 8 bits per byte. bool LittleEndian = Asm->getDataLayout().isLittleEndian(); int Incr = (LittleEndian ? 1 : -1); int Start = (LittleEndian ? 0 : NumBytes - 1); int Stop = (LittleEndian ? NumBytes : -1); // Output the constant to DWARF one byte at a time. for (; Start != Stop; Start += Incr) addUInt(Block, dwarf::DW_FORM_data1, (unsigned char)0xFF & FltPtr[Start]); addBlock(Die, dwarf::DW_AT_const_value, Block); } /// addConstantFPValue - Add constant value entry in variable DIE. void CompileUnit::addConstantFPValue(DIE *Die, const ConstantFP *CFP) { // Pass this down to addConstantValue as an unsigned bag of bits. addConstantValue(Die, CFP->getValueAPF().bitcastToAPInt(), true); } /// addConstantValue - Add constant value entry in variable DIE. void CompileUnit::addConstantValue(DIE *Die, const ConstantInt *CI, bool Unsigned) { addConstantValue(Die, CI->getValue(), Unsigned); } // addConstantValue - Add constant value entry in variable DIE. void CompileUnit::addConstantValue(DIE *Die, const APInt &Val, bool Unsigned) { unsigned CIBitWidth = Val.getBitWidth(); if (CIBitWidth <= 64) { // If we're a signed constant definitely use sdata. if (!Unsigned) { addSInt(Die, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, Val.getSExtValue()); return; } // Else use data for now unless it's larger than we can deal with. dwarf::Form Form; switch (CIBitWidth) { case 8: Form = dwarf::DW_FORM_data1; break; case 16: Form = dwarf::DW_FORM_data2; break; case 32: Form = dwarf::DW_FORM_data4; break; case 64: Form = dwarf::DW_FORM_data8; break; default: addUInt(Die, dwarf::DW_AT_const_value, dwarf::DW_FORM_udata, Val.getZExtValue()); return; } addUInt(Die, dwarf::DW_AT_const_value, Form, Val.getZExtValue()); return; } DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); // Get the raw data form of the large APInt. const uint64_t *Ptr64 = Val.getRawData(); int NumBytes = Val.getBitWidth() / 8; // 8 bits per byte. bool LittleEndian = Asm->getDataLayout().isLittleEndian(); // Output the constant to DWARF one byte at a time. for (int i = 0; i < NumBytes; i++) { uint8_t c; if (LittleEndian) c = Ptr64[i / 8] >> (8 * (i & 7)); else c = Ptr64[(NumBytes - 1 - i) / 8] >> (8 * ((NumBytes - 1 - i) & 7)); addUInt(Block, dwarf::DW_FORM_data1, c); } addBlock(Die, dwarf::DW_AT_const_value, Block); } /// addTemplateParams - Add template parameters into buffer. void CompileUnit::addTemplateParams(DIE &Buffer, DIArray TParams) { // Add template parameters. for (unsigned i = 0, e = TParams.getNumElements(); i != e; ++i) { DIDescriptor Element = TParams.getElement(i); if (Element.isTemplateTypeParameter()) constructTemplateTypeParameterDIE(Buffer, DITemplateTypeParameter(Element)); else if (Element.isTemplateValueParameter()) constructTemplateValueParameterDIE(Buffer, DITemplateValueParameter(Element)); } } /// getOrCreateContextDIE - Get context owner's DIE. DIE *CompileUnit::getOrCreateContextDIE(DIScope Context) { if (!Context || Context.isFile()) return getCUDie(); if (Context.isType()) return getOrCreateTypeDIE(DIType(Context)); if (Context.isNameSpace()) return getOrCreateNameSpace(DINameSpace(Context)); if (Context.isSubprogram()) return getOrCreateSubprogramDIE(DISubprogram(Context)); return getDIE(Context); } /// getOrCreateTypeDIE - Find existing DIE or create new DIE for the /// given DIType. DIE *CompileUnit::getOrCreateTypeDIE(const MDNode *TyNode) { if (!TyNode) return NULL; DIType Ty(TyNode); assert(Ty.isType()); // Construct the context before querying for the existence of the DIE in case // such construction creates the DIE. DIE *ContextDIE = getOrCreateContextDIE(resolve(Ty.getContext())); assert(ContextDIE); DIE *TyDIE = getDIE(Ty); if (TyDIE) return TyDIE; // Create new type. TyDIE = createAndAddDIE(Ty.getTag(), *ContextDIE, Ty); if (Ty.isBasicType()) constructTypeDIE(*TyDIE, DIBasicType(Ty)); else if (Ty.isCompositeType()) constructTypeDIE(*TyDIE, DICompositeType(Ty)); else { assert(Ty.isDerivedType() && "Unknown kind of DIType"); constructTypeDIE(*TyDIE, DIDerivedType(Ty)); } // If this is a named finished type then include it in the list of types // for the accelerator tables. if (!Ty.getName().empty() && !Ty.isForwardDecl()) { bool IsImplementation = 0; if (Ty.isCompositeType()) { DICompositeType CT(Ty); // A runtime language of 0 actually means C/C++ and that any // non-negative value is some version of Objective-C/C++. IsImplementation = (CT.getRunTimeLang() == 0) || CT.isObjcClassComplete(); } unsigned Flags = IsImplementation ? dwarf::DW_FLAG_type_implementation : 0; addAccelType(Ty.getName(), std::make_pair(TyDIE, Flags)); } return TyDIE; } /// addType - Add a new type attribute to the specified entity. void CompileUnit::addType(DIE *Entity, DIType Ty, dwarf::Attribute Attribute) { assert(Ty && "Trying to add a type that doesn't exist?"); // Check for pre-existence. DIEEntry *Entry = getDIEEntry(Ty); // If it exists then use the existing value. if (Entry) { addDIEEntry(Entity, Attribute, Entry); return; } // Construct type. DIE *Buffer = getOrCreateTypeDIE(Ty); // Set up proxy. Entry = createDIEEntry(Buffer); insertDIEEntry(Ty, Entry); addDIEEntry(Entity, Attribute, Entry); // If this is a complete composite type then include it in the // list of global types. addGlobalType(Ty); } // Accelerator table mutators - add each name along with its companion // DIE to the proper table while ensuring that the name that we're going // to reference is in the string table. We do this since the names we // add may not only be identical to the names in the DIE. void CompileUnit::addAccelName(StringRef Name, DIE *Die) { DU->getStringPoolEntry(Name); std::vector &DIEs = AccelNames[Name]; DIEs.push_back(Die); } void CompileUnit::addAccelObjC(StringRef Name, DIE *Die) { DU->getStringPoolEntry(Name); std::vector &DIEs = AccelObjC[Name]; DIEs.push_back(Die); } void CompileUnit::addAccelNamespace(StringRef Name, DIE *Die) { DU->getStringPoolEntry(Name); std::vector &DIEs = AccelNamespace[Name]; DIEs.push_back(Die); } void CompileUnit::addAccelType(StringRef Name, std::pair Die) { DU->getStringPoolEntry(Name); std::vector > &DIEs = AccelTypes[Name]; DIEs.push_back(Die); } /// addGlobalName - Add a new global name to the compile unit. void CompileUnit::addGlobalName(StringRef Name, DIE *Die, DIScope Context) { std::string FullName = getParentContextString(Context) + Name.str(); GlobalNames[FullName] = Die; } /// addGlobalType - Add a new global type to the compile unit. /// void CompileUnit::addGlobalType(DIType Ty) { DIScope Context = resolve(Ty.getContext()); if (!Ty.getName().empty() && !Ty.isForwardDecl() && (!Context || Context.isCompileUnit() || Context.isFile() || Context.isNameSpace())) if (DIEEntry *Entry = getDIEEntry(Ty)) { std::string FullName = getParentContextString(Context) + Ty.getName().str(); GlobalTypes[FullName] = Entry->getEntry(); } } /// getParentContextString - Walks the metadata parent chain in a language /// specific manner (using the compile unit language) and returns /// it as a string. This is done at the metadata level because DIEs may /// not currently have been added to the parent context and walking the /// DIEs looking for names is more expensive than walking the metadata. std::string CompileUnit::getParentContextString(DIScope Context) const { if (!Context) return ""; // FIXME: Decide whether to implement this for non-C++ languages. if (getLanguage() != dwarf::DW_LANG_C_plus_plus) return ""; std::string CS; SmallVector Parents; while (!Context.isCompileUnit()) { Parents.push_back(Context); if (Context.getContext()) Context = resolve(Context.getContext()); else // Structure, etc types will have a NULL context if they're at the top // level. break; } // Reverse iterate over our list to go from the outermost construct to the // innermost. for (SmallVectorImpl::reverse_iterator I = Parents.rbegin(), E = Parents.rend(); I != E; ++I) { DIScope Ctx = *I; StringRef Name = Ctx.getName(); if (!Name.empty()) { CS += Name; CS += "::"; } } return CS; } /// addPubTypes - Add subprogram argument types for pubtypes section. void CompileUnit::addPubTypes(DISubprogram SP) { DICompositeType SPTy = SP.getType(); uint16_t SPTag = SPTy.getTag(); if (SPTag != dwarf::DW_TAG_subroutine_type) return; DIArray Args = SPTy.getTypeArray(); for (unsigned i = 0, e = Args.getNumElements(); i != e; ++i) { DIType ATy(Args.getElement(i)); if (!ATy.isType()) continue; addGlobalType(ATy); } } /// constructTypeDIE - Construct basic type die from DIBasicType. void CompileUnit::constructTypeDIE(DIE &Buffer, DIBasicType BTy) { // Get core information. StringRef Name = BTy.getName(); // Add name if not anonymous or intermediate type. if (!Name.empty()) addString(&Buffer, dwarf::DW_AT_name, Name); // An unspecified type only has a name attribute. if (BTy.getTag() == dwarf::DW_TAG_unspecified_type) return; addUInt(&Buffer, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, BTy.getEncoding()); uint64_t Size = BTy.getSizeInBits() >> 3; addUInt(&Buffer, dwarf::DW_AT_byte_size, None, Size); } /// constructTypeDIE - Construct derived type die from DIDerivedType. void CompileUnit::constructTypeDIE(DIE &Buffer, DIDerivedType DTy) { // Get core information. StringRef Name = DTy.getName(); uint64_t Size = DTy.getSizeInBits() >> 3; uint16_t Tag = Buffer.getTag(); // Map to main type, void will not have a type. DIType FromTy = resolve(DTy.getTypeDerivedFrom()); if (FromTy) addType(&Buffer, FromTy); // Add name if not anonymous or intermediate type. if (!Name.empty()) addString(&Buffer, dwarf::DW_AT_name, Name); // Add size if non-zero (derived types might be zero-sized.) if (Size && Tag != dwarf::DW_TAG_pointer_type) addUInt(&Buffer, dwarf::DW_AT_byte_size, None, Size); if (Tag == dwarf::DW_TAG_ptr_to_member_type) addDIEEntry(&Buffer, dwarf::DW_AT_containing_type, getOrCreateTypeDIE(resolve(DTy.getClassType()))); // Add source line info if available and TyDesc is not a forward declaration. if (!DTy.isForwardDecl()) addSourceLine(&Buffer, DTy); } +/// constructSubprogramArguments - Construct function argument DIEs. +void CompileUnit::constructSubprogramArguments(DIE &Buffer, DIArray Args) { + for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { + DIDescriptor Ty = Args.getElement(i); + if (Ty.isUnspecifiedParameter()) { + assert(i == N-1 && "ellipsis must be the last argument"); + createAndAddDIE(dwarf::DW_TAG_unspecified_parameters, Buffer); + } else { + DIE *Arg = createAndAddDIE(dwarf::DW_TAG_formal_parameter, Buffer); + addType(Arg, DIType(Ty)); + if (DIType(Ty).isArtificial()) + addFlag(Arg, dwarf::DW_AT_artificial); + } + } +} + /// Return true if the type is appropriately scoped to be contained inside /// its own type unit. static bool isTypeUnitScoped(DIType Ty, const DwarfDebug *DD) { DIScope Parent = DD->resolve(Ty.getContext()); while (Parent) { // Don't generate a hash for anything scoped inside a function. if (Parent.isSubprogram()) return false; Parent = DD->resolve(Parent.getContext()); } return true; } /// Return true if the type should be split out into a type unit. static bool shouldCreateTypeUnit(DICompositeType CTy, const DwarfDebug *DD) { uint16_t Tag = CTy.getTag(); switch (Tag) { case dwarf::DW_TAG_structure_type: case dwarf::DW_TAG_union_type: case dwarf::DW_TAG_enumeration_type: case dwarf::DW_TAG_class_type: // If this is a class, structure, union, or enumeration type // that is a definition (not a declaration), and not scoped // inside a function then separate this out as a type unit. return !CTy.isForwardDecl() && isTypeUnitScoped(CTy, DD); default: return false; } } /// constructTypeDIE - Construct type DIE from DICompositeType. void CompileUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { // Get core information. StringRef Name = CTy.getName(); uint64_t Size = CTy.getSizeInBits() >> 3; uint16_t Tag = Buffer.getTag(); switch (Tag) { case dwarf::DW_TAG_array_type: constructArrayTypeDIE(Buffer, CTy); break; case dwarf::DW_TAG_enumeration_type: constructEnumTypeDIE(Buffer, CTy); break; case dwarf::DW_TAG_subroutine_type: { // Add return type. A void return won't have a type. DIArray Elements = CTy.getTypeArray(); DIType RTy(Elements.getElement(0)); if (RTy) addType(&Buffer, RTy); bool isPrototyped = true; - // Add arguments. - for (unsigned i = 1, N = Elements.getNumElements(); i < N; ++i) { - DIDescriptor Ty = Elements.getElement(i); - if (Ty.isUnspecifiedParameter()) { - createAndAddDIE(dwarf::DW_TAG_unspecified_parameters, Buffer); - isPrototyped = false; - } else { - DIE *Arg = createAndAddDIE(dwarf::DW_TAG_formal_parameter, Buffer); - addType(Arg, DIType(Ty)); - if (DIType(Ty).isArtificial()) - addFlag(Arg, dwarf::DW_AT_artificial); - } - } + if (Elements.getNumElements() == 2 && + Elements.getElement(1).isUnspecifiedParameter()) + isPrototyped = false; + + constructSubprogramArguments(Buffer, Elements); + // Add prototype flag if we're dealing with a C language and the // function has been prototyped. uint16_t Language = getLanguage(); if (isPrototyped && (Language == dwarf::DW_LANG_C89 || Language == dwarf::DW_LANG_C99 || Language == dwarf::DW_LANG_ObjC)) addFlag(&Buffer, dwarf::DW_AT_prototyped); } break; case dwarf::DW_TAG_structure_type: case dwarf::DW_TAG_union_type: case dwarf::DW_TAG_class_type: { // Add elements to structure type. DIArray Elements = CTy.getTypeArray(); for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { DIDescriptor Element = Elements.getElement(i); DIE *ElemDie = NULL; if (Element.isSubprogram()) { DISubprogram SP(Element); ElemDie = getOrCreateSubprogramDIE(SP); if (SP.isProtected()) addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1, dwarf::DW_ACCESS_protected); else if (SP.isPrivate()) addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1, dwarf::DW_ACCESS_private); else addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1, dwarf::DW_ACCESS_public); if (SP.isExplicit()) addFlag(ElemDie, dwarf::DW_AT_explicit); } else if (Element.isDerivedType()) { DIDerivedType DDTy(Element); if (DDTy.getTag() == dwarf::DW_TAG_friend) { ElemDie = createAndAddDIE(dwarf::DW_TAG_friend, Buffer); addType(ElemDie, resolve(DDTy.getTypeDerivedFrom()), dwarf::DW_AT_friend); } else if (DDTy.isStaticMember()) { getOrCreateStaticMemberDIE(DDTy); } else { constructMemberDIE(Buffer, DDTy); } } else if (Element.isObjCProperty()) { DIObjCProperty Property(Element); ElemDie = createAndAddDIE(Property.getTag(), Buffer); StringRef PropertyName = Property.getObjCPropertyName(); addString(ElemDie, dwarf::DW_AT_APPLE_property_name, PropertyName); addType(ElemDie, Property.getType()); addSourceLine(ElemDie, Property); StringRef GetterName = Property.getObjCPropertyGetterName(); if (!GetterName.empty()) addString(ElemDie, dwarf::DW_AT_APPLE_property_getter, GetterName); StringRef SetterName = Property.getObjCPropertySetterName(); if (!SetterName.empty()) addString(ElemDie, dwarf::DW_AT_APPLE_property_setter, SetterName); unsigned PropertyAttributes = 0; if (Property.isReadOnlyObjCProperty()) PropertyAttributes |= dwarf::DW_APPLE_PROPERTY_readonly; if (Property.isReadWriteObjCProperty()) PropertyAttributes |= dwarf::DW_APPLE_PROPERTY_readwrite; if (Property.isAssignObjCProperty()) PropertyAttributes |= dwarf::DW_APPLE_PROPERTY_assign; if (Property.isRetainObjCProperty()) PropertyAttributes |= dwarf::DW_APPLE_PROPERTY_retain; if (Property.isCopyObjCProperty()) PropertyAttributes |= dwarf::DW_APPLE_PROPERTY_copy; if (Property.isNonAtomicObjCProperty()) PropertyAttributes |= dwarf::DW_APPLE_PROPERTY_nonatomic; if (PropertyAttributes) addUInt(ElemDie, dwarf::DW_AT_APPLE_property_attribute, None, PropertyAttributes); DIEEntry *Entry = getDIEEntry(Element); if (!Entry) { Entry = createDIEEntry(ElemDie); insertDIEEntry(Element, Entry); } } else continue; } if (CTy.isAppleBlockExtension()) addFlag(&Buffer, dwarf::DW_AT_APPLE_block); DICompositeType ContainingType(resolve(CTy.getContainingType())); if (ContainingType) addDIEEntry(&Buffer, dwarf::DW_AT_containing_type, getOrCreateTypeDIE(ContainingType)); if (CTy.isObjcClassComplete()) addFlag(&Buffer, dwarf::DW_AT_APPLE_objc_complete_type); // Add template parameters to a class, structure or union types. // FIXME: The support isn't in the metadata for this yet. if (Tag == dwarf::DW_TAG_class_type || Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type) addTemplateParams(Buffer, CTy.getTemplateParams()); break; } default: break; } // Add name if not anonymous or intermediate type. if (!Name.empty()) addString(&Buffer, dwarf::DW_AT_name, Name); if (Tag == dwarf::DW_TAG_enumeration_type || Tag == dwarf::DW_TAG_class_type || Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type) { // Add size if non-zero (derived types might be zero-sized.) // TODO: Do we care about size for enum forward declarations? if (Size) addUInt(&Buffer, dwarf::DW_AT_byte_size, None, Size); else if (!CTy.isForwardDecl()) // Add zero size if it is not a forward declaration. addUInt(&Buffer, dwarf::DW_AT_byte_size, None, 0); // If we're a forward decl, say so. if (CTy.isForwardDecl()) addFlag(&Buffer, dwarf::DW_AT_declaration); // Add source line info if available. if (!CTy.isForwardDecl()) addSourceLine(&Buffer, CTy); // No harm in adding the runtime language to the declaration. unsigned RLang = CTy.getRunTimeLang(); if (RLang) addUInt(&Buffer, dwarf::DW_AT_APPLE_runtime_class, dwarf::DW_FORM_data1, RLang); } // If this is a type applicable to a type unit it then add it to the // list of types we'll compute a hash for later. if (shouldCreateTypeUnit(CTy, DD)) DD->addTypeUnitType(&Buffer); } /// constructTemplateTypeParameterDIE - Construct new DIE for the given /// DITemplateTypeParameter. void CompileUnit::constructTemplateTypeParameterDIE(DIE &Buffer, DITemplateTypeParameter TP) { DIE *ParamDIE = createAndAddDIE(dwarf::DW_TAG_template_type_parameter, Buffer); // Add the type if it exists, it could be void and therefore no type. if (TP.getType()) addType(ParamDIE, resolve(TP.getType())); if (!TP.getName().empty()) addString(ParamDIE, dwarf::DW_AT_name, TP.getName()); } /// constructTemplateValueParameterDIE - Construct new DIE for the given /// DITemplateValueParameter. void CompileUnit::constructTemplateValueParameterDIE(DIE &Buffer, DITemplateValueParameter VP) { DIE *ParamDIE = createAndAddDIE(VP.getTag(), Buffer); // Add the type if there is one, template template and template parameter // packs will not have a type. if (VP.getTag() == dwarf::DW_TAG_template_value_parameter) addType(ParamDIE, resolve(VP.getType())); if (!VP.getName().empty()) addString(ParamDIE, dwarf::DW_AT_name, VP.getName()); if (Value *Val = VP.getValue()) { if (ConstantInt *CI = dyn_cast(Val)) addConstantValue(ParamDIE, CI, isUnsignedDIType(DD, resolve(VP.getType()))); else if (GlobalValue *GV = dyn_cast(Val)) { // For declaration non-type template parameters (such as global values and // functions) DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); addOpAddress(Block, Asm->getSymbol(GV)); // Emit DW_OP_stack_value to use the address as the immediate value of the // parameter, rather than a pointer to it. addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_stack_value); addBlock(ParamDIE, dwarf::DW_AT_location, Block); } else if (VP.getTag() == dwarf::DW_TAG_GNU_template_template_param) { assert(isa(Val)); addString(ParamDIE, dwarf::DW_AT_GNU_template_name, cast(Val)->getString()); } else if (VP.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack) { assert(isa(Val)); DIArray A(cast(Val)); addTemplateParams(*ParamDIE, A); } } } /// getOrCreateNameSpace - Create a DIE for DINameSpace. DIE *CompileUnit::getOrCreateNameSpace(DINameSpace NS) { // Construct the context before querying for the existence of the DIE in case // such construction creates the DIE. DIE *ContextDIE = getOrCreateContextDIE(NS.getContext()); DIE *NDie = getDIE(NS); if (NDie) return NDie; NDie = createAndAddDIE(dwarf::DW_TAG_namespace, *ContextDIE, NS); if (!NS.getName().empty()) { addString(NDie, dwarf::DW_AT_name, NS.getName()); addAccelNamespace(NS.getName(), NDie); addGlobalName(NS.getName(), NDie, NS.getContext()); } else addAccelNamespace("(anonymous namespace)", NDie); addSourceLine(NDie, NS); return NDie; } /// getOrCreateSubprogramDIE - Create new DIE using SP. DIE *CompileUnit::getOrCreateSubprogramDIE(DISubprogram SP) { // Construct the context before querying for the existence of the DIE in case // such construction creates the DIE (as is the case for member function // declarations). DIE *ContextDIE = getOrCreateContextDIE(resolve(SP.getContext())); DIE *SPDie = getDIE(SP); if (SPDie) return SPDie; DISubprogram SPDecl = SP.getFunctionDeclaration(); if (SPDecl.isSubprogram()) // Add subprogram definitions to the CU die directly. ContextDIE = CUDie.get(); // DW_TAG_inlined_subroutine may refer to this DIE. SPDie = createAndAddDIE(dwarf::DW_TAG_subprogram, *ContextDIE, SP); DIE *DeclDie = NULL; if (SPDecl.isSubprogram()) DeclDie = getOrCreateSubprogramDIE(SPDecl); // Add function template parameters. addTemplateParams(*SPDie, SP.getTemplateParams()); // If this DIE is going to refer declaration info using AT_specification // then there is no need to add other attributes. if (DeclDie) { // Refer function declaration directly. addDIEEntry(SPDie, dwarf::DW_AT_specification, DeclDie); return SPDie; } // Add the linkage name if we have one. StringRef LinkageName = SP.getLinkageName(); if (!LinkageName.empty()) addString(SPDie, dwarf::DW_AT_MIPS_linkage_name, GlobalValue::getRealLinkageName(LinkageName)); // Constructors and operators for anonymous aggregates do not have names. if (!SP.getName().empty()) addString(SPDie, dwarf::DW_AT_name, SP.getName()); addSourceLine(SPDie, SP); // Add the prototype if we have a prototype and we have a C like // language. uint16_t Language = getLanguage(); if (SP.isPrototyped() && (Language == dwarf::DW_LANG_C89 || Language == dwarf::DW_LANG_C99 || Language == dwarf::DW_LANG_ObjC)) addFlag(SPDie, dwarf::DW_AT_prototyped); DICompositeType SPTy = SP.getType(); assert(SPTy.getTag() == dwarf::DW_TAG_subroutine_type && "the type of a subprogram should be a subroutine"); DIArray Args = SPTy.getTypeArray(); // Add a return type. If this is a type like a C/C++ void type we don't add a // return type. if (Args.getElement(0)) addType(SPDie, DIType(Args.getElement(0))); unsigned VK = SP.getVirtuality(); if (VK) { addUInt(SPDie, dwarf::DW_AT_virtuality, dwarf::DW_FORM_data1, VK); DIEBlock *Block = getDIEBlock(); addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); addUInt(Block, dwarf::DW_FORM_udata, SP.getVirtualIndex()); addBlock(SPDie, dwarf::DW_AT_vtable_elem_location, Block); ContainingTypeMap.insert( std::make_pair(SPDie, resolve(SP.getContainingType()))); } if (!SP.isDefinition()) { addFlag(SPDie, dwarf::DW_AT_declaration); // Add arguments. Do not add arguments for subprogram definition. They will // be handled while processing variables. - for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { - DIE *Arg = createAndAddDIE(dwarf::DW_TAG_formal_parameter, *SPDie); - DIType ATy(Args.getElement(i)); - addType(Arg, ATy); - if (ATy.isArtificial()) - addFlag(Arg, dwarf::DW_AT_artificial); - } + constructSubprogramArguments(*SPDie, Args); } if (SP.isArtificial()) addFlag(SPDie, dwarf::DW_AT_artificial); if (!SP.isLocalToUnit()) addFlag(SPDie, dwarf::DW_AT_external); if (SP.isOptimized()) addFlag(SPDie, dwarf::DW_AT_APPLE_optimized); if (unsigned isa = Asm->getISAEncoding()) { addUInt(SPDie, dwarf::DW_AT_APPLE_isa, dwarf::DW_FORM_flag, isa); } return SPDie; } // Return const expression if value is a GEP to access merged global // constant. e.g. // i8* getelementptr ({ i8, i8, i8, i8 }* @_MergedGlobals, i32 0, i32 0) static const ConstantExpr *getMergedGlobalExpr(const Value *V) { const ConstantExpr *CE = dyn_cast_or_null(V); if (!CE || CE->getNumOperands() != 3 || CE->getOpcode() != Instruction::GetElementPtr) return NULL; // First operand points to a global struct. Value *Ptr = CE->getOperand(0); if (!isa(Ptr) || !isa(cast(Ptr->getType())->getElementType())) return NULL; // Second operand is zero. const ConstantInt *CI = dyn_cast_or_null(CE->getOperand(1)); if (!CI || !CI->isZero()) return NULL; // Third operand is offset. if (!isa(CE->getOperand(2))) return NULL; return CE; } /// createGlobalVariableDIE - create global variable DIE. void CompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) { // Check for pre-existence. if (getDIE(GV)) return; if (!GV.isGlobalVariable()) return; DIScope GVContext = GV.getContext(); DIType GTy = GV.getType(); // If this is a static data member definition, some attributes belong // to the declaration DIE. DIE *VariableDIE = NULL; bool IsStaticMember = false; DIDerivedType SDMDecl = GV.getStaticDataMemberDeclaration(); if (SDMDecl.Verify()) { assert(SDMDecl.isStaticMember() && "Expected static member decl"); // We need the declaration DIE that is in the static member's class. VariableDIE = getOrCreateStaticMemberDIE(SDMDecl); IsStaticMember = true; } // If this is not a static data member definition, create the variable // DIE and add the initial set of attributes to it. if (!VariableDIE) { // Construct the context before querying for the existence of the DIE in // case such construction creates the DIE. DIE *ContextDIE = getOrCreateContextDIE(GVContext); // Add to map. VariableDIE = createAndAddDIE(GV.getTag(), *ContextDIE, GV); // Add name and type. addString(VariableDIE, dwarf::DW_AT_name, GV.getDisplayName()); addType(VariableDIE, GTy); // Add scoping info. if (!GV.isLocalToUnit()) addFlag(VariableDIE, dwarf::DW_AT_external); // Add line number info. addSourceLine(VariableDIE, GV); } // Add location. bool addToAccelTable = false; DIE *VariableSpecDIE = NULL; bool isGlobalVariable = GV.getGlobal() != NULL; if (isGlobalVariable) { addToAccelTable = true; DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); const MCSymbol *Sym = Asm->getSymbol(GV.getGlobal()); if (GV.getGlobal()->isThreadLocal()) { // FIXME: Make this work with -gsplit-dwarf. unsigned PointerSize = Asm->getDataLayout().getPointerSize(); assert((PointerSize == 4 || PointerSize == 8) && "Add support for other sizes if necessary"); const MCExpr *Expr = Asm->getObjFileLowering().getDebugThreadLocalSymbol(Sym); // Based on GCC's support for TLS: if (!DD->useSplitDwarf()) { // 1) Start with a constNu of the appropriate pointer size addUInt(Block, dwarf::DW_FORM_data1, PointerSize == 4 ? dwarf::DW_OP_const4u : dwarf::DW_OP_const8u); // 2) containing the (relocated) offset of the TLS variable // within the module's TLS block. addExpr(Block, dwarf::DW_FORM_udata, Expr); } else { addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_const_index); addUInt(Block, dwarf::DW_FORM_udata, DU->getAddrPoolIndex(Expr)); } // 3) followed by a custom OP to make the debugger do a TLS lookup. addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_push_tls_address); } else addOpAddress(Block, Sym); // Do not create specification DIE if context is either compile unit // or a subprogram. if (GVContext && GV.isDefinition() && !GVContext.isCompileUnit() && !GVContext.isFile() && !DD->isSubprogramContext(GVContext)) { // Create specification DIE. VariableSpecDIE = createAndAddDIE(dwarf::DW_TAG_variable, *CUDie); addDIEEntry(VariableSpecDIE, dwarf::DW_AT_specification, VariableDIE); addBlock(VariableSpecDIE, dwarf::DW_AT_location, Block); // A static member's declaration is already flagged as such. if (!SDMDecl.Verify()) addFlag(VariableDIE, dwarf::DW_AT_declaration); } else { addBlock(VariableDIE, dwarf::DW_AT_location, Block); } // Add the linkage name. StringRef LinkageName = GV.getLinkageName(); if (!LinkageName.empty()) // From DWARF4: DIEs to which DW_AT_linkage_name may apply include: // TAG_common_block, TAG_constant, TAG_entry_point, TAG_subprogram and // TAG_variable. addString(IsStaticMember && VariableSpecDIE ? VariableSpecDIE : VariableDIE, dwarf::DW_AT_MIPS_linkage_name, GlobalValue::getRealLinkageName(LinkageName)); } else if (const ConstantInt *CI = dyn_cast_or_null(GV.getConstant())) { // AT_const_value was added when the static member was created. To avoid // emitting AT_const_value multiple times, we only add AT_const_value when // it is not a static member. if (!IsStaticMember) addConstantValue(VariableDIE, CI, isUnsignedDIType(DD, GTy)); } else if (const ConstantExpr *CE = getMergedGlobalExpr(GV->getOperand(11))) { addToAccelTable = true; // GV is a merged global. DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); Value *Ptr = CE->getOperand(0); addOpAddress(Block, Asm->getSymbol(cast(Ptr))); addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); SmallVector Idx(CE->op_begin() + 1, CE->op_end()); addUInt(Block, dwarf::DW_FORM_udata, Asm->getDataLayout().getIndexedOffset(Ptr->getType(), Idx)); addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); addBlock(VariableDIE, dwarf::DW_AT_location, Block); } if (addToAccelTable) { DIE *AddrDIE = VariableSpecDIE ? VariableSpecDIE : VariableDIE; addAccelName(GV.getName(), AddrDIE); // If the linkage name is different than the name, go ahead and output // that as well into the name table. if (GV.getLinkageName() != "" && GV.getName() != GV.getLinkageName()) addAccelName(GV.getLinkageName(), AddrDIE); } if (!GV.isLocalToUnit()) addGlobalName(GV.getName(), VariableSpecDIE ? VariableSpecDIE : VariableDIE, GV.getContext()); } /// constructSubrangeDIE - Construct subrange DIE from DISubrange. void CompileUnit::constructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy) { DIE *DW_Subrange = createAndAddDIE(dwarf::DW_TAG_subrange_type, Buffer); addDIEEntry(DW_Subrange, dwarf::DW_AT_type, IndexTy); // The LowerBound value defines the lower bounds which is typically zero for // C/C++. The Count value is the number of elements. Values are 64 bit. If // Count == -1 then the array is unbounded and we do not emit // DW_AT_lower_bound and DW_AT_upper_bound attributes. If LowerBound == 0 and // Count == 0, then the array has zero elements in which case we do not emit // an upper bound. int64_t LowerBound = SR.getLo(); int64_t DefaultLowerBound = getDefaultLowerBound(); int64_t Count = SR.getCount(); if (DefaultLowerBound == -1 || LowerBound != DefaultLowerBound) addUInt(DW_Subrange, dwarf::DW_AT_lower_bound, None, LowerBound); if (Count != -1 && Count != 0) // FIXME: An unbounded array should reference the expression that defines // the array. addUInt(DW_Subrange, dwarf::DW_AT_upper_bound, None, LowerBound + Count - 1); } /// constructArrayTypeDIE - Construct array type DIE from DICompositeType. void CompileUnit::constructArrayTypeDIE(DIE &Buffer, DICompositeType CTy) { if (CTy.isVector()) addFlag(&Buffer, dwarf::DW_AT_GNU_vector); // Emit the element type. addType(&Buffer, resolve(CTy.getTypeDerivedFrom())); // Get an anonymous type for index type. // FIXME: This type should be passed down from the front end // as different languages may have different sizes for indexes. DIE *IdxTy = getIndexTyDie(); if (!IdxTy) { // Construct an anonymous type for index type. IdxTy = createAndAddDIE(dwarf::DW_TAG_base_type, *CUDie.get()); addString(IdxTy, dwarf::DW_AT_name, "int"); addUInt(IdxTy, dwarf::DW_AT_byte_size, None, sizeof(int32_t)); addUInt(IdxTy, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, dwarf::DW_ATE_signed); setIndexTyDie(IdxTy); } // Add subranges to array type. DIArray Elements = CTy.getTypeArray(); for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { DIDescriptor Element = Elements.getElement(i); if (Element.getTag() == dwarf::DW_TAG_subrange_type) constructSubrangeDIE(Buffer, DISubrange(Element), IdxTy); } } /// constructEnumTypeDIE - Construct an enum type DIE from DICompositeType. void CompileUnit::constructEnumTypeDIE(DIE &Buffer, DICompositeType CTy) { DIArray Elements = CTy.getTypeArray(); // Add enumerators to enumeration type. for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { DIEnumerator Enum(Elements.getElement(i)); if (Enum.isEnumerator()) { DIE *Enumerator = createAndAddDIE(dwarf::DW_TAG_enumerator, Buffer); StringRef Name = Enum.getName(); addString(Enumerator, dwarf::DW_AT_name, Name); int64_t Value = Enum.getEnumValue(); addSInt(Enumerator, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, Value); } } DIType DTy = resolve(CTy.getTypeDerivedFrom()); if (DTy) { addType(&Buffer, DTy); addFlag(&Buffer, dwarf::DW_AT_enum_class); } } /// constructContainingTypeDIEs - Construct DIEs for types that contain /// vtables. void CompileUnit::constructContainingTypeDIEs() { for (DenseMap::iterator CI = ContainingTypeMap.begin(), CE = ContainingTypeMap.end(); CI != CE; ++CI) { DIE *SPDie = CI->first; DIDescriptor D(CI->second); if (!D) continue; DIE *NDie = getDIE(D); if (!NDie) continue; addDIEEntry(SPDie, dwarf::DW_AT_containing_type, NDie); } } /// constructVariableDIE - Construct a DIE for the given DbgVariable. DIE *CompileUnit::constructVariableDIE(DbgVariable &DV, bool isScopeAbstract) { StringRef Name = DV.getName(); // Define variable debug information entry. DIE *VariableDie = new DIE(DV.getTag()); DbgVariable *AbsVar = DV.getAbstractVariable(); DIE *AbsDIE = AbsVar ? AbsVar->getDIE() : NULL; if (AbsDIE) addDIEEntry(VariableDie, dwarf::DW_AT_abstract_origin, AbsDIE); else { if (!Name.empty()) addString(VariableDie, dwarf::DW_AT_name, Name); addSourceLine(VariableDie, DV.getVariable()); addType(VariableDie, DV.getType()); } if (DV.isArtificial()) addFlag(VariableDie, dwarf::DW_AT_artificial); if (isScopeAbstract) { DV.setDIE(VariableDie); return VariableDie; } // Add variable address. unsigned Offset = DV.getDotDebugLocOffset(); if (Offset != ~0U) { addSectionLabel(VariableDie, dwarf::DW_AT_location, Asm->GetTempSymbol("debug_loc", Offset)); DV.setDIE(VariableDie); return VariableDie; } // Check if variable is described by a DBG_VALUE instruction. if (const MachineInstr *DVInsn = DV.getMInsn()) { assert(DVInsn->getNumOperands() == 3); if (DVInsn->getOperand(0).isReg()) { const MachineOperand RegOp = DVInsn->getOperand(0); // If the second operand is an immediate, this is an indirect value. if (DVInsn->getOperand(1).isImm()) { MachineLocation Location(RegOp.getReg(), DVInsn->getOperand(1).getImm()); addVariableAddress(DV, VariableDie, Location); } else if (RegOp.getReg()) addVariableAddress(DV, VariableDie, MachineLocation(RegOp.getReg())); } else if (DVInsn->getOperand(0).isImm()) addConstantValue(VariableDie, DVInsn->getOperand(0), DV.getType()); else if (DVInsn->getOperand(0).isFPImm()) addConstantFPValue(VariableDie, DVInsn->getOperand(0)); else if (DVInsn->getOperand(0).isCImm()) addConstantValue(VariableDie, DVInsn->getOperand(0).getCImm(), isUnsignedDIType(DD, DV.getType())); DV.setDIE(VariableDie); return VariableDie; } else { // .. else use frame index. int FI = DV.getFrameIndex(); if (FI != ~0) { unsigned FrameReg = 0; const TargetFrameLowering *TFI = Asm->TM.getFrameLowering(); int Offset = TFI->getFrameIndexReference(*Asm->MF, FI, FrameReg); MachineLocation Location(FrameReg, Offset); addVariableAddress(DV, VariableDie, Location); } } DV.setDIE(VariableDie); return VariableDie; } /// constructMemberDIE - Construct member DIE from DIDerivedType. void CompileUnit::constructMemberDIE(DIE &Buffer, DIDerivedType DT) { DIE *MemberDie = createAndAddDIE(DT.getTag(), Buffer); StringRef Name = DT.getName(); if (!Name.empty()) addString(MemberDie, dwarf::DW_AT_name, Name); addType(MemberDie, resolve(DT.getTypeDerivedFrom())); addSourceLine(MemberDie, DT); if (DT.getTag() == dwarf::DW_TAG_inheritance && DT.isVirtual()) { // For C++, virtual base classes are not at fixed offset. Use following // expression to extract appropriate offset from vtable. // BaseAddr = ObAddr + *((*ObAddr) - Offset) DIEBlock *VBaseLocationDie = new (DIEValueAllocator) DIEBlock(); addUInt(VBaseLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_dup); addUInt(VBaseLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); addUInt(VBaseLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); addUInt(VBaseLocationDie, dwarf::DW_FORM_udata, DT.getOffsetInBits()); addUInt(VBaseLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_minus); addUInt(VBaseLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); addUInt(VBaseLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); addBlock(MemberDie, dwarf::DW_AT_data_member_location, VBaseLocationDie); } else { uint64_t Size = DT.getSizeInBits(); uint64_t FieldSize = getBaseTypeSize(DD, DT); uint64_t OffsetInBytes; if (Size != FieldSize) { // Handle bitfield. addUInt(MemberDie, dwarf::DW_AT_byte_size, None, getBaseTypeSize(DD, DT) >> 3); addUInt(MemberDie, dwarf::DW_AT_bit_size, None, DT.getSizeInBits()); uint64_t Offset = DT.getOffsetInBits(); uint64_t AlignMask = ~(DT.getAlignInBits() - 1); uint64_t HiMark = (Offset + FieldSize) & AlignMask; uint64_t FieldOffset = (HiMark - FieldSize); Offset -= FieldOffset; // Maybe we need to work from the other end. if (Asm->getDataLayout().isLittleEndian()) Offset = FieldSize - (Offset + Size); addUInt(MemberDie, dwarf::DW_AT_bit_offset, None, Offset); // Here WD_AT_data_member_location points to the anonymous // field that includes this bit field. OffsetInBytes = FieldOffset >> 3; } else // This is not a bitfield. OffsetInBytes = DT.getOffsetInBits() >> 3; if (DD->getDwarfVersion() <= 2) { DIEBlock *MemLocationDie = new (DIEValueAllocator) DIEBlock(); addUInt(MemLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); addUInt(MemLocationDie, dwarf::DW_FORM_udata, OffsetInBytes); addBlock(MemberDie, dwarf::DW_AT_data_member_location, MemLocationDie); } else addUInt(MemberDie, dwarf::DW_AT_data_member_location, None, OffsetInBytes); } if (DT.isProtected()) addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1, dwarf::DW_ACCESS_protected); else if (DT.isPrivate()) addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1, dwarf::DW_ACCESS_private); // Otherwise C++ member and base classes are considered public. else addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1, dwarf::DW_ACCESS_public); if (DT.isVirtual()) addUInt(MemberDie, dwarf::DW_AT_virtuality, dwarf::DW_FORM_data1, dwarf::DW_VIRTUALITY_virtual); // Objective-C properties. if (MDNode *PNode = DT.getObjCProperty()) if (DIEEntry *PropertyDie = getDIEEntry(PNode)) MemberDie->addValue(dwarf::DW_AT_APPLE_property, dwarf::DW_FORM_ref4, PropertyDie); if (DT.isArtificial()) addFlag(MemberDie, dwarf::DW_AT_artificial); } /// getOrCreateStaticMemberDIE - Create new DIE for C++ static member. DIE *CompileUnit::getOrCreateStaticMemberDIE(DIDerivedType DT) { if (!DT.Verify()) return NULL; // Construct the context before querying for the existence of the DIE in case // such construction creates the DIE. DIE *ContextDIE = getOrCreateContextDIE(resolve(DT.getContext())); assert(dwarf::isType(ContextDIE->getTag()) && "Static member should belong to a type."); DIE *StaticMemberDIE = getDIE(DT); if (StaticMemberDIE) return StaticMemberDIE; StaticMemberDIE = createAndAddDIE(DT.getTag(), *ContextDIE, DT); DIType Ty = resolve(DT.getTypeDerivedFrom()); addString(StaticMemberDIE, dwarf::DW_AT_name, DT.getName()); addType(StaticMemberDIE, Ty); addSourceLine(StaticMemberDIE, DT); addFlag(StaticMemberDIE, dwarf::DW_AT_external); addFlag(StaticMemberDIE, dwarf::DW_AT_declaration); // FIXME: We could omit private if the parent is a class_type, and // public if the parent is something else. if (DT.isProtected()) addUInt(StaticMemberDIE, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1, dwarf::DW_ACCESS_protected); else if (DT.isPrivate()) addUInt(StaticMemberDIE, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1, dwarf::DW_ACCESS_private); else addUInt(StaticMemberDIE, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1, dwarf::DW_ACCESS_public); if (const ConstantInt *CI = dyn_cast_or_null(DT.getConstant())) addConstantValue(StaticMemberDIE, CI, isUnsignedDIType(DD, Ty)); if (const ConstantFP *CFP = dyn_cast_or_null(DT.getConstant())) addConstantFPValue(StaticMemberDIE, CFP); return StaticMemberDIE; } void CompileUnit::emitHeader(const MCSection *ASection, const MCSymbol *ASectionSym) { Asm->OutStreamer.AddComment("DWARF version number"); Asm->EmitInt16(DD->getDwarfVersion()); Asm->OutStreamer.AddComment("Offset Into Abbrev. Section"); Asm->EmitSectionOffset(Asm->GetTempSymbol(ASection->getLabelBeginName()), ASectionSym); Asm->OutStreamer.AddComment("Address Size (in bytes)"); Asm->EmitInt8(Asm->getDataLayout().getPointerSize()); } Index: stable/9/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h =================================================================== --- stable/9/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h (revision 283018) +++ stable/9/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h (revision 283019) @@ -1,416 +1,419 @@ //===-- llvm/CodeGen/DwarfCompileUnit.h - Dwarf Compile Unit ---*- C++ -*--===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file contains support for writing dwarf compile unit. // //===----------------------------------------------------------------------===// #ifndef CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H #define CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H #include "DIE.h" #include "DwarfDebug.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringMap.h" #include "llvm/DebugInfo.h" #include "llvm/MC/MCExpr.h" namespace llvm { class MachineLocation; class MachineOperand; class ConstantInt; class ConstantFP; class DbgVariable; //===----------------------------------------------------------------------===// /// CompileUnit - This dwarf writer support class manages information associated /// with a source file. class CompileUnit { /// UniqueID - a numeric ID unique among all CUs in the module /// unsigned UniqueID; /// Node - MDNode for the compile unit. DICompileUnit Node; /// CUDie - Compile unit debug information entry. /// const OwningPtr CUDie; /// Asm - Target of Dwarf emission. AsmPrinter *Asm; // Holders for some common dwarf information. DwarfDebug *DD; DwarfUnits *DU; /// IndexTyDie - An anonymous type for index type. Owned by CUDie. DIE *IndexTyDie; /// MDNodeToDieMap - Tracks the mapping of unit level debug information /// variables to debug information entries. DenseMap MDNodeToDieMap; /// MDNodeToDIEEntryMap - Tracks the mapping of unit level debug information /// descriptors to debug information entries using a DIEEntry proxy. DenseMap MDNodeToDIEEntryMap; /// GlobalNames - A map of globally visible named entities for this unit. /// StringMap GlobalNames; /// GlobalTypes - A map of globally visible types for this unit. /// StringMap GlobalTypes; /// AccelNames - A map of names for the name accelerator table. /// StringMap > AccelNames; StringMap > AccelObjC; StringMap > AccelNamespace; StringMap > > AccelTypes; /// DIEBlocks - A list of all the DIEBlocks in use. std::vector DIEBlocks; /// ContainingTypeMap - This map is used to keep track of subprogram DIEs that /// need DW_AT_containing_type attribute. This attribute points to a DIE that /// corresponds to the MDNode mapped with the subprogram DIE. DenseMap ContainingTypeMap; // DIEValueAllocator - All DIEValues are allocated through this allocator. BumpPtrAllocator DIEValueAllocator; // DIEIntegerOne - A preallocated DIEValue because 1 is used frequently. DIEInteger *DIEIntegerOne; public: CompileUnit(unsigned UID, DIE *D, DICompileUnit CU, AsmPrinter *A, DwarfDebug *DW, DwarfUnits *DWU); ~CompileUnit(); // Accessors. unsigned getUniqueID() const { return UniqueID; } uint16_t getLanguage() const { return Node.getLanguage(); } DICompileUnit getNode() const { return Node; } DIE *getCUDie() const { return CUDie.get(); } const StringMap &getGlobalNames() const { return GlobalNames; } const StringMap &getGlobalTypes() const { return GlobalTypes; } const StringMap > &getAccelNames() const { return AccelNames; } const StringMap > &getAccelObjC() const { return AccelObjC; } const StringMap > &getAccelNamespace() const { return AccelNamespace; } const StringMap > > & getAccelTypes() const { return AccelTypes; } unsigned getDebugInfoOffset() const { return DebugInfoOffset; } void setDebugInfoOffset(unsigned DbgInfoOff) { DebugInfoOffset = DbgInfoOff; } /// hasContent - Return true if this compile unit has something to write out. /// bool hasContent() const { return !CUDie->getChildren().empty(); } /// getParentContextString - Get a string containing the language specific /// context for a global name. std::string getParentContextString(DIScope Context) const; /// addGlobalName - Add a new global entity to the compile unit. /// void addGlobalName(StringRef Name, DIE *Die, DIScope Context); /// addGlobalType - Add a new global type to the compile unit. /// void addGlobalType(DIType Ty); /// addPubTypes - Add a set of types from the subprogram to the global types. void addPubTypes(DISubprogram SP); /// addAccelName - Add a new name to the name accelerator table. void addAccelName(StringRef Name, DIE *Die); /// addAccelObjC - Add a new name to the ObjC accelerator table. void addAccelObjC(StringRef Name, DIE *Die); /// addAccelNamespace - Add a new name to the namespace accelerator table. void addAccelNamespace(StringRef Name, DIE *Die); /// addAccelType - Add a new type to the type accelerator table. void addAccelType(StringRef Name, std::pair Die); /// getDIE - Returns the debug information entry map slot for the /// specified debug variable. We delegate the request to DwarfDebug /// when the MDNode can be part of the type system, since DIEs for /// the type system can be shared across CUs and the mappings are /// kept in DwarfDebug. DIE *getDIE(DIDescriptor D) const; DIEBlock *getDIEBlock() { return new (DIEValueAllocator) DIEBlock(); } /// insertDIE - Insert DIE into the map. We delegate the request to DwarfDebug /// when the MDNode can be part of the type system, since DIEs for /// the type system can be shared across CUs and the mappings are /// kept in DwarfDebug. void insertDIE(DIDescriptor Desc, DIE *D); /// addDie - Adds or interns the DIE to the compile unit. /// void addDie(DIE *Buffer) { CUDie->addChild(Buffer); } /// addFlag - Add a flag that is true to the DIE. void addFlag(DIE *Die, dwarf::Attribute Attribute); /// addUInt - Add an unsigned integer attribute data and value. /// void addUInt(DIE *Die, dwarf::Attribute Attribute, Optional Form, uint64_t Integer); void addUInt(DIEBlock *Block, dwarf::Form Form, uint64_t Integer); /// addSInt - Add an signed integer attribute data and value. /// void addSInt(DIE *Die, dwarf::Attribute Attribute, Optional Form, int64_t Integer); void addSInt(DIEBlock *Die, Optional Form, int64_t Integer); /// addString - Add a string attribute data and value. /// void addString(DIE *Die, dwarf::Attribute Attribute, const StringRef Str); /// addLocalString - Add a string attribute data and value. /// void addLocalString(DIE *Die, dwarf::Attribute Attribute, const StringRef Str); /// addExpr - Add a Dwarf expression attribute data and value. /// void addExpr(DIEBlock *Die, dwarf::Form Form, const MCExpr *Expr); /// addLabel - Add a Dwarf label attribute data and value. /// void addLabel(DIE *Die, dwarf::Attribute Attribute, dwarf::Form Form, const MCSymbol *Label); void addLabel(DIEBlock *Die, dwarf::Form Form, const MCSymbol *Label); /// addSectionLabel - Add a Dwarf section label attribute data and value. /// void addSectionLabel(DIE *Die, dwarf::Attribute Attribute, const MCSymbol *Label); /// addSectionOffset - Add an offset into a section attribute data and value. /// void addSectionOffset(DIE *Die, dwarf::Attribute Attribute, uint64_t Integer); /// addLabelAddress - Add a dwarf label attribute data and value using /// either DW_FORM_addr or DW_FORM_GNU_addr_index. /// void addLabelAddress(DIE *Die, dwarf::Attribute Attribute, MCSymbol *Label); /// addOpAddress - Add a dwarf op address data and value using the /// form given and an op of either DW_FORM_addr or DW_FORM_GNU_addr_index. /// void addOpAddress(DIEBlock *Die, const MCSymbol *Label); /// addSectionDelta - Add a label delta attribute data and value. void addSectionDelta(DIE *Die, dwarf::Attribute Attribute, const MCSymbol *Hi, const MCSymbol *Lo); /// addDIEEntry - Add a DIE attribute data and value. /// void addDIEEntry(DIE *Die, dwarf::Attribute Attribute, DIE *Entry); /// addDIEEntry - Add a DIE attribute data and value. /// void addDIEEntry(DIE *Die, dwarf::Attribute Attribute, DIEEntry *Entry); /// addBlock - Add block data. /// void addBlock(DIE *Die, dwarf::Attribute Attribute, DIEBlock *Block); /// addSourceLine - Add location information to specified debug information /// entry. void addSourceLine(DIE *Die, DIVariable V); void addSourceLine(DIE *Die, DIGlobalVariable G); void addSourceLine(DIE *Die, DISubprogram SP); void addSourceLine(DIE *Die, DIType Ty); void addSourceLine(DIE *Die, DINameSpace NS); void addSourceLine(DIE *Die, DIObjCProperty Ty); /// addAddress - Add an address attribute to a die based on the location /// provided. void addAddress(DIE *Die, dwarf::Attribute Attribute, const MachineLocation &Location, bool Indirect = false); /// addConstantValue - Add constant value entry in variable DIE. void addConstantValue(DIE *Die, const MachineOperand &MO, DIType Ty); void addConstantValue(DIE *Die, const ConstantInt *CI, bool Unsigned); void addConstantValue(DIE *Die, const APInt &Val, bool Unsigned); /// addConstantFPValue - Add constant value entry in variable DIE. void addConstantFPValue(DIE *Die, const MachineOperand &MO); void addConstantFPValue(DIE *Die, const ConstantFP *CFP); /// addTemplateParams - Add template parameters in buffer. void addTemplateParams(DIE &Buffer, DIArray TParams); /// addRegisterOp - Add register operand. void addRegisterOp(DIEBlock *TheDie, unsigned Reg); /// addRegisterOffset - Add register offset. void addRegisterOffset(DIEBlock *TheDie, unsigned Reg, int64_t Offset); /// addComplexAddress - Start with the address based on the location provided, /// and generate the DWARF information necessary to find the actual variable /// (navigating the extra location information encoded in the type) based on /// the starting location. Add the DWARF information to the die. /// void addComplexAddress(const DbgVariable &DV, DIE *Die, dwarf::Attribute Attribute, const MachineLocation &Location); // FIXME: Should be reformulated in terms of addComplexAddress. /// addBlockByrefAddress - Start with the address based on the location /// provided, and generate the DWARF information necessary to find the /// actual Block variable (navigating the Block struct) based on the /// starting location. Add the DWARF information to the die. Obsolete, /// please use addComplexAddress instead. /// void addBlockByrefAddress(const DbgVariable &DV, DIE *Die, dwarf::Attribute Attribute, const MachineLocation &Location); /// addVariableAddress - Add DW_AT_location attribute for a /// DbgVariable based on provided MachineLocation. void addVariableAddress(const DbgVariable &DV, DIE *Die, MachineLocation Location); /// addType - Add a new type attribute to the specified entity. This takes /// and attribute parameter because DW_AT_friend attributes are also /// type references. void addType(DIE *Entity, DIType Ty, dwarf::Attribute Attribute = dwarf::DW_AT_type); /// getOrCreateNameSpace - Create a DIE for DINameSpace. DIE *getOrCreateNameSpace(DINameSpace NS); /// getOrCreateSubprogramDIE - Create new DIE using SP. DIE *getOrCreateSubprogramDIE(DISubprogram SP); /// getOrCreateTypeDIE - Find existing DIE or create new DIE for the /// given DIType. DIE *getOrCreateTypeDIE(const MDNode *N); /// getOrCreateContextDIE - Get context owner's DIE. DIE *getOrCreateContextDIE(DIScope Context); /// createGlobalVariableDIE - create global variable DIE. void createGlobalVariableDIE(DIGlobalVariable GV); /// constructContainingTypeDIEs - Construct DIEs for types that contain /// vtables. void constructContainingTypeDIEs(); /// constructVariableDIE - Construct a DIE for the given DbgVariable. DIE *constructVariableDIE(DbgVariable &DV, bool isScopeAbstract); /// Create a DIE with the given Tag, add the DIE to its parent, and /// call insertDIE if MD is not null. DIE *createAndAddDIE(unsigned Tag, DIE &Parent, DIDescriptor N = DIDescriptor()); /// Compute the size of a header for this unit, not including the initial /// length field. unsigned getHeaderSize() const { return sizeof(int16_t) + // DWARF version number sizeof(int32_t) + // Offset Into Abbrev. Section sizeof(int8_t); // Pointer Size (in bytes) } /// Emit the header for this unit, not including the initial length field. void emitHeader(const MCSection *ASection, const MCSymbol *ASectionSym); private: + /// constructSubprogramArguments - Construct function argument DIEs. + void constructSubprogramArguments(DIE &Buffer, DIArray Args); + /// constructTypeDIE - Construct basic type die from DIBasicType. void constructTypeDIE(DIE &Buffer, DIBasicType BTy); /// constructTypeDIE - Construct derived type die from DIDerivedType. void constructTypeDIE(DIE &Buffer, DIDerivedType DTy); /// constructTypeDIE - Construct type DIE from DICompositeType. void constructTypeDIE(DIE &Buffer, DICompositeType CTy); /// constructSubrangeDIE - Construct subrange DIE from DISubrange. void constructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy); /// constructArrayTypeDIE - Construct array type DIE from DICompositeType. void constructArrayTypeDIE(DIE &Buffer, DICompositeType CTy); /// constructEnumTypeDIE - Construct enum type DIE from DIEnumerator. void constructEnumTypeDIE(DIE &Buffer, DICompositeType CTy); /// constructMemberDIE - Construct member DIE from DIDerivedType. void constructMemberDIE(DIE &Buffer, DIDerivedType DT); /// constructTemplateTypeParameterDIE - Construct new DIE for the given /// DITemplateTypeParameter. void constructTemplateTypeParameterDIE(DIE &Buffer, DITemplateTypeParameter TP); /// constructTemplateValueParameterDIE - Construct new DIE for the given /// DITemplateValueParameter. void constructTemplateValueParameterDIE(DIE &Buffer, DITemplateValueParameter TVP); /// getOrCreateStaticMemberDIE - Create new static data member DIE. DIE *getOrCreateStaticMemberDIE(DIDerivedType DT); /// Offset of the CUDie from beginning of debug info section. unsigned DebugInfoOffset; /// getLowerBoundDefault - Return the default lower bound for an array. If the /// DWARF version doesn't handle the language, return -1. int64_t getDefaultLowerBound() const; /// getDIEEntry - Returns the debug information entry for the specified /// debug variable. DIEEntry *getDIEEntry(const MDNode *N) const { return MDNodeToDIEEntryMap.lookup(N); } /// insertDIEEntry - Insert debug information entry into the map. void insertDIEEntry(const MDNode *N, DIEEntry *E) { MDNodeToDIEEntryMap.insert(std::make_pair(N, E)); } // getIndexTyDie - Get an anonymous type for index type. DIE *getIndexTyDie() { return IndexTyDie; } // setIndexTyDie - Set D as anonymous type for index which can be reused // later. void setIndexTyDie(DIE *D) { IndexTyDie = D; } /// createDIEEntry - Creates a new DIEEntry to be a proxy for a debug /// information entry. DIEEntry *createDIEEntry(DIE *Entry); /// resolve - Look in the DwarfDebug map for the MDNode that /// corresponds to the reference. template T resolve(DIRef Ref) const { return DD->resolve(Ref); } }; } // end llvm namespace #endif Index: stable/9/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp =================================================================== --- stable/9/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (revision 283018) +++ stable/9/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (revision 283019) @@ -1,3057 +1,3073 @@ //===-- llvm/CodeGen/DwarfDebug.cpp - Dwarf Debug Framework ---------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file contains support for writing dwarf debug info into asm files. // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "dwarfdebug" #include "DwarfDebug.h" #include "DIE.h" #include "DIEHash.h" #include "DwarfAccelTable.h" #include "DwarfCompileUnit.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Triple.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/DIBuilder.h" #include "llvm/DebugInfo.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Module.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/MD5.h" #include "llvm/Support/Path.h" #include "llvm/Support/Timer.h" #include "llvm/Support/ValueHandle.h" #include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" using namespace llvm; static cl::opt DisableDebugInfoPrinting("disable-debug-info-print", cl::Hidden, cl::desc("Disable debug info printing")); static cl::opt UnknownLocations( "use-unknown-locations", cl::Hidden, cl::desc("Make an absence of debug location information explicit."), cl::init(false)); static cl::opt GenerateODRHash("generate-odr-hash", cl::Hidden, cl::desc("Add an ODR hash to external type DIEs."), cl::init(false)); static cl::opt GenerateCUHash("generate-cu-hash", cl::Hidden, cl::desc("Add the CU hash as the dwo_id."), cl::init(false)); static cl::opt GenerateGnuPubSections("generate-gnu-dwarf-pub-sections", cl::Hidden, cl::desc("Generate GNU-style pubnames and pubtypes"), cl::init(false)); namespace { enum DefaultOnOff { Default, Enable, Disable }; } static cl::opt DwarfAccelTables("dwarf-accel-tables", cl::Hidden, cl::desc("Output prototype dwarf accelerator tables."), cl::values(clEnumVal(Default, "Default for platform"), clEnumVal(Enable, "Enabled"), clEnumVal(Disable, "Disabled"), clEnumValEnd), cl::init(Default)); static cl::opt SplitDwarf("split-dwarf", cl::Hidden, cl::desc("Output prototype dwarf split debug info."), cl::values(clEnumVal(Default, "Default for platform"), clEnumVal(Enable, "Enabled"), clEnumVal(Disable, "Disabled"), clEnumValEnd), cl::init(Default)); static cl::opt DwarfPubSections("generate-dwarf-pub-sections", cl::Hidden, cl::desc("Generate DWARF pubnames and pubtypes sections"), cl::values(clEnumVal(Default, "Default for platform"), clEnumVal(Enable, "Enabled"), clEnumVal(Disable, "Disabled"), clEnumValEnd), cl::init(Default)); static cl::opt DwarfVersionNumber("dwarf-version", cl::Hidden, cl::desc("Generate DWARF for dwarf version."), cl::init(0)); static const char *const DWARFGroupName = "DWARF Emission"; static const char *const DbgTimerName = "DWARF Debug Writer"; //===----------------------------------------------------------------------===// // Configuration values for initial hash set sizes (log2). // static const unsigned InitAbbreviationsSetSize = 9; // log2(512) namespace llvm { /// resolve - Look in the DwarfDebug map for the MDNode that /// corresponds to the reference. template T DbgVariable::resolve(DIRef Ref) const { return DD->resolve(Ref); } DIType DbgVariable::getType() const { DIType Ty = Var.getType(); // FIXME: isBlockByrefVariable should be reformulated in terms of complex // addresses instead. if (Var.isBlockByrefVariable()) { /* Byref variables, in Blocks, are declared by the programmer as "SomeType VarName;", but the compiler creates a __Block_byref_x_VarName struct, and gives the variable VarName either the struct, or a pointer to the struct, as its type. This is necessary for various behind-the-scenes things the compiler needs to do with by-reference variables in blocks. However, as far as the original *programmer* is concerned, the variable should still have type 'SomeType', as originally declared. The following function dives into the __Block_byref_x_VarName struct to find the original type of the variable. This will be passed back to the code generating the type for the Debug Information Entry for the variable 'VarName'. 'VarName' will then have the original type 'SomeType' in its debug information. The original type 'SomeType' will be the type of the field named 'VarName' inside the __Block_byref_x_VarName struct. NOTE: In order for this to not completely fail on the debugger side, the Debug Information Entry for the variable VarName needs to have a DW_AT_location that tells the debugger how to unwind through the pointers and __Block_byref_x_VarName struct to find the actual value of the variable. The function addBlockByrefType does this. */ DIType subType = Ty; uint16_t tag = Ty.getTag(); if (tag == dwarf::DW_TAG_pointer_type) subType = resolve(DIDerivedType(Ty).getTypeDerivedFrom()); DIArray Elements = DICompositeType(subType).getTypeArray(); for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { DIDerivedType DT(Elements.getElement(i)); if (getName() == DT.getName()) return (resolve(DT.getTypeDerivedFrom())); } } return Ty; } } // end llvm namespace /// Return Dwarf Version by checking module flags. static unsigned getDwarfVersionFromModule(const Module *M) { Value *Val = M->getModuleFlag("Dwarf Version"); if (!Val) return dwarf::DWARF_VERSION; return cast(Val)->getZExtValue(); } DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) : Asm(A), MMI(Asm->MMI), FirstCU(0), AbbreviationsSet(InitAbbreviationsSetSize), SourceIdMap(DIEValueAllocator), PrevLabel(NULL), GlobalCUIndexCount(0), InfoHolder(A, &AbbreviationsSet, Abbreviations, "info_string", DIEValueAllocator), SkeletonAbbrevSet(InitAbbreviationsSetSize), SkeletonHolder(A, &SkeletonAbbrevSet, SkeletonAbbrevs, "skel_string", DIEValueAllocator) { DwarfInfoSectionSym = DwarfAbbrevSectionSym = 0; DwarfStrSectionSym = TextSectionSym = 0; DwarfDebugRangeSectionSym = DwarfDebugLocSectionSym = DwarfLineSectionSym = 0; DwarfAddrSectionSym = 0; DwarfAbbrevDWOSectionSym = DwarfStrDWOSectionSym = 0; FunctionBeginSym = FunctionEndSym = 0; // Turn on accelerator tables for Darwin by default, pubnames by // default for non-Darwin, and handle split dwarf. bool IsDarwin = Triple(A->getTargetTriple()).isOSDarwin(); if (DwarfAccelTables == Default) HasDwarfAccelTables = IsDarwin; else HasDwarfAccelTables = DwarfAccelTables == Enable; if (SplitDwarf == Default) HasSplitDwarf = false; else HasSplitDwarf = SplitDwarf == Enable; if (DwarfPubSections == Default) HasDwarfPubSections = !IsDarwin; else HasDwarfPubSections = DwarfPubSections == Enable; DwarfVersion = DwarfVersionNumber ? DwarfVersionNumber : getDwarfVersionFromModule(MMI->getModule()); { NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); beginModule(); } } // Switch to the specified MCSection and emit an assembler // temporary label to it if SymbolStem is specified. static MCSymbol *emitSectionSym(AsmPrinter *Asm, const MCSection *Section, const char *SymbolStem = 0) { Asm->OutStreamer.SwitchSection(Section); if (!SymbolStem) return 0; MCSymbol *TmpSym = Asm->GetTempSymbol(SymbolStem); Asm->OutStreamer.EmitLabel(TmpSym); return TmpSym; } MCSymbol *DwarfUnits::getStringPoolSym() { return Asm->GetTempSymbol(StringPref); } MCSymbol *DwarfUnits::getStringPoolEntry(StringRef Str) { std::pair &Entry = StringPool.GetOrCreateValue(Str).getValue(); if (Entry.first) return Entry.first; Entry.second = NextStringPoolNumber++; return Entry.first = Asm->GetTempSymbol(StringPref, Entry.second); } unsigned DwarfUnits::getStringPoolIndex(StringRef Str) { std::pair &Entry = StringPool.GetOrCreateValue(Str).getValue(); if (Entry.first) return Entry.second; Entry.second = NextStringPoolNumber++; Entry.first = Asm->GetTempSymbol(StringPref, Entry.second); return Entry.second; } unsigned DwarfUnits::getAddrPoolIndex(const MCSymbol *Sym) { return getAddrPoolIndex(MCSymbolRefExpr::Create(Sym, Asm->OutContext)); } unsigned DwarfUnits::getAddrPoolIndex(const MCExpr *Sym) { std::pair::iterator, bool> P = AddressPool.insert(std::make_pair(Sym, NextAddrPoolNumber)); if (P.second) ++NextAddrPoolNumber; return P.first->second; } // Define a unique number for the abbreviation. // void DwarfUnits::assignAbbrevNumber(DIEAbbrev &Abbrev) { // Check the set for priors. DIEAbbrev *InSet = AbbreviationsSet->GetOrInsertNode(&Abbrev); // If it's newly added. if (InSet == &Abbrev) { // Add to abbreviation list. Abbreviations.push_back(&Abbrev); // Assign the vector position + 1 as its number. Abbrev.setNumber(Abbreviations.size()); } else { // Assign existing abbreviation number. Abbrev.setNumber(InSet->getNumber()); } } static bool isObjCClass(StringRef Name) { return Name.startswith("+") || Name.startswith("-"); } static bool hasObjCCategory(StringRef Name) { if (!isObjCClass(Name)) return false; return Name.find(") ") != StringRef::npos; } static void getObjCClassCategory(StringRef In, StringRef &Class, StringRef &Category) { if (!hasObjCCategory(In)) { Class = In.slice(In.find('[') + 1, In.find(' ')); Category = ""; return; } Class = In.slice(In.find('[') + 1, In.find('(')); Category = In.slice(In.find('[') + 1, In.find(' ')); return; } static StringRef getObjCMethodName(StringRef In) { return In.slice(In.find(' ') + 1, In.find(']')); } // Helper for sorting sections into a stable output order. static bool SectionSort(const MCSection *A, const MCSection *B) { std::string LA = (A ? A->getLabelBeginName() : ""); std::string LB = (B ? B->getLabelBeginName() : ""); return LA < LB; } // Add the various names to the Dwarf accelerator table names. // TODO: Determine whether or not we should add names for programs // that do not have a DW_AT_name or DW_AT_linkage_name field - this // is only slightly different than the lookup of non-standard ObjC names. static void addSubprogramNames(CompileUnit *TheCU, DISubprogram SP, DIE* Die) { if (!SP.isDefinition()) return; TheCU->addAccelName(SP.getName(), Die); // If the linkage name is different than the name, go ahead and output // that as well into the name table. if (SP.getLinkageName() != "" && SP.getName() != SP.getLinkageName()) TheCU->addAccelName(SP.getLinkageName(), Die); // If this is an Objective-C selector name add it to the ObjC accelerator // too. if (isObjCClass(SP.getName())) { StringRef Class, Category; getObjCClassCategory(SP.getName(), Class, Category); TheCU->addAccelObjC(Class, Die); if (Category != "") TheCU->addAccelObjC(Category, Die); // Also add the base method name to the name table. TheCU->addAccelName(getObjCMethodName(SP.getName()), Die); } } /// isSubprogramContext - Return true if Context is either a subprogram /// or another context nested inside a subprogram. bool DwarfDebug::isSubprogramContext(const MDNode *Context) { if (!Context) return false; DIDescriptor D(Context); if (D.isSubprogram()) return true; if (D.isType()) return isSubprogramContext(resolve(DIType(Context).getContext())); return false; } // Find DIE for the given subprogram and attach appropriate DW_AT_low_pc // and DW_AT_high_pc attributes. If there are global variables in this // scope then create and insert DIEs for these variables. DIE *DwarfDebug::updateSubprogramScopeDIE(CompileUnit *SPCU, DISubprogram SP) { DIE *SPDie = SPCU->getDIE(SP); assert(SPDie && "Unable to find subprogram DIE!"); // If we're updating an abstract DIE, then we will be adding the children and // object pointer later on. But what we don't want to do is process the // concrete DIE twice. if (DIE *AbsSPDIE = AbstractSPDies.lookup(SP)) { // Pick up abstract subprogram DIE. SPDie = SPCU->createAndAddDIE(dwarf::DW_TAG_subprogram, *SPCU->getCUDie()); SPCU->addDIEEntry(SPDie, dwarf::DW_AT_abstract_origin, AbsSPDIE); } else { DISubprogram SPDecl = SP.getFunctionDeclaration(); if (!SPDecl.isSubprogram()) { // There is not any need to generate specification DIE for a function // defined at compile unit level. If a function is defined inside another // function then gdb prefers the definition at top level and but does not // expect specification DIE in parent function. So avoid creating // specification DIE for a function defined inside a function. DIScope SPContext = resolve(SP.getContext()); if (SP.isDefinition() && !SPContext.isCompileUnit() && !SPContext.isFile() && !isSubprogramContext(SPContext)) { SPCU->addFlag(SPDie, dwarf::DW_AT_declaration); // Add arguments. DICompositeType SPTy = SP.getType(); DIArray Args = SPTy.getTypeArray(); uint16_t SPTag = SPTy.getTag(); if (SPTag == dwarf::DW_TAG_subroutine_type) + // FIXME: Use DwarfUnit::constructSubprogramArguments() here. for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { - DIE *Arg = - SPCU->createAndAddDIE(dwarf::DW_TAG_formal_parameter, *SPDie); DIType ATy(Args.getElement(i)); - SPCU->addType(Arg, ATy); - if (ATy.isArtificial()) - SPCU->addFlag(Arg, dwarf::DW_AT_artificial); - if (ATy.isObjectPointer()) - SPCU->addDIEEntry(SPDie, dwarf::DW_AT_object_pointer, Arg); + if (ATy.isUnspecifiedParameter()) { + assert(i == N-1 && "ellipsis must be the last argument"); + SPCU->createAndAddDIE(dwarf::DW_TAG_unspecified_parameters, *SPDie); + } else { + DIE *Arg = + SPCU->createAndAddDIE(dwarf::DW_TAG_formal_parameter, *SPDie); + SPCU->addType(Arg, ATy); + if (ATy.isArtificial()) + SPCU->addFlag(Arg, dwarf::DW_AT_artificial); + if (ATy.isObjectPointer()) + SPCU->addDIEEntry(SPDie, dwarf::DW_AT_object_pointer, Arg); + } } DIE *SPDeclDie = SPDie; SPDie = SPCU->createAndAddDIE(dwarf::DW_TAG_subprogram, *SPCU->getCUDie()); SPCU->addDIEEntry(SPDie, dwarf::DW_AT_specification, SPDeclDie); } } } SPCU->addLabelAddress(SPDie, dwarf::DW_AT_low_pc, Asm->GetTempSymbol("func_begin", Asm->getFunctionNumber())); SPCU->addLabelAddress(SPDie, dwarf::DW_AT_high_pc, Asm->GetTempSymbol("func_end", Asm->getFunctionNumber())); const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); MachineLocation Location(RI->getFrameRegister(*Asm->MF)); SPCU->addAddress(SPDie, dwarf::DW_AT_frame_base, Location); // Add name to the name table, we do this here because we're guaranteed // to have concrete versions of our DW_TAG_subprogram nodes. addSubprogramNames(SPCU, SP, SPDie); return SPDie; } /// Check whether we should create a DIE for the given Scope, return true /// if we don't create a DIE (the corresponding DIE is null). bool DwarfDebug::isLexicalScopeDIENull(LexicalScope *Scope) { if (Scope->isAbstractScope()) return false; // We don't create a DIE if there is no Range. const SmallVectorImpl &Ranges = Scope->getRanges(); if (Ranges.empty()) return true; if (Ranges.size() > 1) return false; // We don't create a DIE if we have a single Range and the end label // is null. SmallVectorImpl::const_iterator RI = Ranges.begin(); MCSymbol *End = getLabelAfterInsn(RI->second); return !End; } // Construct new DW_TAG_lexical_block for this scope and attach // DW_AT_low_pc/DW_AT_high_pc labels. DIE *DwarfDebug::constructLexicalScopeDIE(CompileUnit *TheCU, LexicalScope *Scope) { if (isLexicalScopeDIENull(Scope)) return 0; DIE *ScopeDIE = new DIE(dwarf::DW_TAG_lexical_block); if (Scope->isAbstractScope()) return ScopeDIE; const SmallVectorImpl &Ranges = Scope->getRanges(); // If we have multiple ranges, emit them into the range section. if (Ranges.size() > 1) { // .debug_range section has not been laid out yet. Emit offset in // .debug_range as a uint, size 4, for now. emitDIE will handle // DW_AT_ranges appropriately. TheCU->addSectionOffset(ScopeDIE, dwarf::DW_AT_ranges, DebugRangeSymbols.size() * Asm->getDataLayout().getPointerSize()); for (SmallVectorImpl::const_iterator RI = Ranges.begin(), RE = Ranges.end(); RI != RE; ++RI) { DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first)); DebugRangeSymbols.push_back(getLabelAfterInsn(RI->second)); } // Terminate the range list. DebugRangeSymbols.push_back(NULL); DebugRangeSymbols.push_back(NULL); return ScopeDIE; } // Construct the address range for this DIE. SmallVectorImpl::const_iterator RI = Ranges.begin(); MCSymbol *Start = getLabelBeforeInsn(RI->first); MCSymbol *End = getLabelAfterInsn(RI->second); assert(End && "End label should not be null!"); assert(Start->isDefined() && "Invalid starting label for an inlined scope!"); assert(End->isDefined() && "Invalid end label for an inlined scope!"); TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_low_pc, Start); TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_high_pc, End); return ScopeDIE; } // This scope represents inlined body of a function. Construct DIE to // represent this concrete inlined copy of the function. DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU, LexicalScope *Scope) { const SmallVectorImpl &Ranges = Scope->getRanges(); assert(Ranges.empty() == false && "LexicalScope does not have instruction markers!"); if (!Scope->getScopeNode()) return NULL; DIScope DS(Scope->getScopeNode()); DISubprogram InlinedSP = getDISubprogram(DS); DIE *OriginDIE = TheCU->getDIE(InlinedSP); if (!OriginDIE) { DEBUG(dbgs() << "Unable to find original DIE for an inlined subprogram."); return NULL; } DIE *ScopeDIE = new DIE(dwarf::DW_TAG_inlined_subroutine); TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin, OriginDIE); if (Ranges.size() > 1) { // .debug_range section has not been laid out yet. Emit offset in // .debug_range as a uint, size 4, for now. emitDIE will handle // DW_AT_ranges appropriately. TheCU->addSectionOffset(ScopeDIE, dwarf::DW_AT_ranges, DebugRangeSymbols.size() * Asm->getDataLayout().getPointerSize()); for (SmallVectorImpl::const_iterator RI = Ranges.begin(), RE = Ranges.end(); RI != RE; ++RI) { DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first)); DebugRangeSymbols.push_back(getLabelAfterInsn(RI->second)); } DebugRangeSymbols.push_back(NULL); DebugRangeSymbols.push_back(NULL); } else { SmallVectorImpl::const_iterator RI = Ranges.begin(); MCSymbol *StartLabel = getLabelBeforeInsn(RI->first); MCSymbol *EndLabel = getLabelAfterInsn(RI->second); if (StartLabel == 0 || EndLabel == 0) llvm_unreachable("Unexpected Start and End labels for an inlined scope!"); assert(StartLabel->isDefined() && "Invalid starting label for an inlined scope!"); assert(EndLabel->isDefined() && "Invalid end label for an inlined scope!"); TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_low_pc, StartLabel); TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_high_pc, EndLabel); } InlinedSubprogramDIEs.insert(OriginDIE); // Add the call site information to the DIE. DILocation DL(Scope->getInlinedAt()); TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_file, None, getOrCreateSourceID(DL.getFilename(), DL.getDirectory(), TheCU->getUniqueID())); TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_line, None, DL.getLineNumber()); // Add name to the name table, we do this here because we're guaranteed // to have concrete versions of our DW_TAG_inlined_subprogram nodes. addSubprogramNames(TheCU, InlinedSP, ScopeDIE); return ScopeDIE; } DIE *DwarfDebug::createScopeChildrenDIE(CompileUnit *TheCU, LexicalScope *Scope, SmallVectorImpl &Children) { DIE *ObjectPointer = NULL; // Collect arguments for current function. - if (LScopes.isCurrentFunctionScope(Scope)) + if (LScopes.isCurrentFunctionScope(Scope)) { for (unsigned i = 0, N = CurrentFnArguments.size(); i < N; ++i) if (DbgVariable *ArgDV = CurrentFnArguments[i]) if (DIE *Arg = TheCU->constructVariableDIE(*ArgDV, Scope->isAbstractScope())) { Children.push_back(Arg); if (ArgDV->isObjectPointer()) ObjectPointer = Arg; } + + // Create the unspecified parameter that marks a function as variadic. + DISubprogram SP(Scope->getScopeNode()); + assert(SP.Verify()); + DIArray FnArgs = SP.getType().getTypeArray(); + if (FnArgs.getElement(FnArgs.getNumElements()-1).isUnspecifiedParameter()) { + DIE *Ellipsis = new DIE(dwarf::DW_TAG_unspecified_parameters); + Children.push_back(Ellipsis); + } + } // Collect lexical scope children first. const SmallVectorImpl &Variables =ScopeVariables.lookup(Scope); for (unsigned i = 0, N = Variables.size(); i < N; ++i) if (DIE *Variable = TheCU->constructVariableDIE(*Variables[i], Scope->isAbstractScope())) { Children.push_back(Variable); if (Variables[i]->isObjectPointer()) ObjectPointer = Variable; } const SmallVectorImpl &Scopes = Scope->getChildren(); for (unsigned j = 0, M = Scopes.size(); j < M; ++j) if (DIE *Nested = constructScopeDIE(TheCU, Scopes[j])) Children.push_back(Nested); return ObjectPointer; } // Construct a DIE for this scope. DIE *DwarfDebug::constructScopeDIE(CompileUnit *TheCU, LexicalScope *Scope) { if (!Scope || !Scope->getScopeNode()) return NULL; DIScope DS(Scope->getScopeNode()); SmallVector Children; DIE *ObjectPointer = NULL; bool ChildrenCreated = false; // We try to create the scope DIE first, then the children DIEs. This will // avoid creating un-used children then removing them later when we find out // the scope DIE is null. DIE *ScopeDIE = NULL; if (Scope->getInlinedAt()) ScopeDIE = constructInlinedScopeDIE(TheCU, Scope); else if (DS.isSubprogram()) { ProcessedSPNodes.insert(DS); if (Scope->isAbstractScope()) { ScopeDIE = TheCU->getDIE(DS); // Note down abstract DIE. if (ScopeDIE) AbstractSPDies.insert(std::make_pair(DS, ScopeDIE)); } else ScopeDIE = updateSubprogramScopeDIE(TheCU, DISubprogram(DS)); } else { // Early exit when we know the scope DIE is going to be null. if (isLexicalScopeDIENull(Scope)) return NULL; // We create children here when we know the scope DIE is not going to be // null and the children will be added to the scope DIE. ObjectPointer = createScopeChildrenDIE(TheCU, Scope, Children); ChildrenCreated = true; // There is no need to emit empty lexical block DIE. std::pair Range = std::equal_range( ScopesWithImportedEntities.begin(), ScopesWithImportedEntities.end(), std::pair(DS, (const MDNode*)0), less_first()); if (Children.empty() && Range.first == Range.second) return NULL; ScopeDIE = constructLexicalScopeDIE(TheCU, Scope); assert(ScopeDIE && "Scope DIE should not be null."); for (ImportedEntityMap::const_iterator i = Range.first; i != Range.second; ++i) constructImportedEntityDIE(TheCU, i->second, ScopeDIE); } if (!ScopeDIE) { assert(Children.empty() && "We create children only when the scope DIE is not null."); return NULL; } if (!ChildrenCreated) // We create children when the scope DIE is not null. ObjectPointer = createScopeChildrenDIE(TheCU, Scope, Children); // Add children for (SmallVectorImpl::iterator I = Children.begin(), E = Children.end(); I != E; ++I) ScopeDIE->addChild(*I); if (DS.isSubprogram() && ObjectPointer != NULL) TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, ObjectPointer); if (DS.isSubprogram()) TheCU->addPubTypes(DISubprogram(DS)); return ScopeDIE; } // Look up the source id with the given directory and source file names. // If none currently exists, create a new id and insert it in the // SourceIds map. This can update DirectoryNames and SourceFileNames maps // as well. unsigned DwarfDebug::getOrCreateSourceID(StringRef FileName, StringRef DirName, unsigned CUID) { // If we use .loc in assembly, we can't separate .file entries according to // compile units. Thus all files will belong to the default compile unit. // FIXME: add a better feature test than hasRawTextSupport. Even better, // extend .file to support this. if (Asm->TM.hasMCUseLoc() && Asm->OutStreamer.hasRawTextSupport()) CUID = 0; // If FE did not provide a file name, then assume stdin. if (FileName.empty()) return getOrCreateSourceID("", StringRef(), CUID); // TODO: this might not belong here. See if we can factor this better. if (DirName == CompilationDir) DirName = ""; // FileIDCUMap stores the current ID for the given compile unit. unsigned SrcId = FileIDCUMap[CUID] + 1; // We look up the CUID/file/dir by concatenating them with a zero byte. SmallString<128> NamePair; NamePair += utostr(CUID); NamePair += '\0'; NamePair += DirName; NamePair += '\0'; // Zero bytes are not allowed in paths. NamePair += FileName; StringMapEntry &Ent = SourceIdMap.GetOrCreateValue(NamePair, SrcId); if (Ent.getValue() != SrcId) return Ent.getValue(); FileIDCUMap[CUID] = SrcId; // Print out a .file directive to specify files for .loc directives. Asm->OutStreamer.EmitDwarfFileDirective(SrcId, DirName, FileName, CUID); return SrcId; } // Create new CompileUnit for the given metadata node with tag // DW_TAG_compile_unit. CompileUnit *DwarfDebug::constructCompileUnit(DICompileUnit DIUnit) { StringRef FN = DIUnit.getFilename(); CompilationDir = DIUnit.getDirectory(); DIE *Die = new DIE(dwarf::DW_TAG_compile_unit); CompileUnit *NewCU = new CompileUnit(GlobalCUIndexCount++, Die, DIUnit, Asm, this, &InfoHolder); FileIDCUMap[NewCU->getUniqueID()] = 0; // Call this to emit a .file directive if it wasn't emitted for the source // file this CU comes from yet. getOrCreateSourceID(FN, CompilationDir, NewCU->getUniqueID()); NewCU->addString(Die, dwarf::DW_AT_producer, DIUnit.getProducer()); NewCU->addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2, DIUnit.getLanguage()); NewCU->addString(Die, dwarf::DW_AT_name, FN); // 2.17.1 requires that we use DW_AT_low_pc for a single entry point // into an entity. We're using 0 (or a NULL label) for this. For // split dwarf it's in the skeleton CU so omit it here. if (!useSplitDwarf()) NewCU->addLabelAddress(Die, dwarf::DW_AT_low_pc, NULL); // Define start line table label for each Compile Unit. MCSymbol *LineTableStartSym = Asm->GetTempSymbol("line_table_start", NewCU->getUniqueID()); Asm->OutStreamer.getContext().setMCLineTableSymbol(LineTableStartSym, NewCU->getUniqueID()); // Use a single line table if we are using .loc and generating assembly. bool UseTheFirstCU = (Asm->TM.hasMCUseLoc() && Asm->OutStreamer.hasRawTextSupport()) || (NewCU->getUniqueID() == 0); if (!useSplitDwarf()) { // DW_AT_stmt_list is a offset of line number information for this // compile unit in debug_line section. For split dwarf this is // left in the skeleton CU and so not included. // The line table entries are not always emitted in assembly, so it // is not okay to use line_table_start here. if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) NewCU->addSectionLabel( Die, dwarf::DW_AT_stmt_list, UseTheFirstCU ? Asm->GetTempSymbol("section_line") : LineTableStartSym); else if (UseTheFirstCU) NewCU->addSectionOffset(Die, dwarf::DW_AT_stmt_list, 0); else NewCU->addSectionDelta(Die, dwarf::DW_AT_stmt_list, LineTableStartSym, DwarfLineSectionSym); // If we're using split dwarf the compilation dir is going to be in the // skeleton CU and so we don't need to duplicate it here. if (!CompilationDir.empty()) NewCU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir); // Flags to let the linker know we have emitted new style pubnames. Only // emit it here if we don't have a skeleton CU for split dwarf. if (GenerateGnuPubSections) { if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) NewCU->addSectionLabel( Die, dwarf::DW_AT_GNU_pubnames, Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID())); else NewCU->addSectionDelta( Die, dwarf::DW_AT_GNU_pubnames, Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID()), DwarfGnuPubNamesSectionSym); if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) NewCU->addSectionLabel( Die, dwarf::DW_AT_GNU_pubtypes, Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID())); else NewCU->addSectionDelta( Die, dwarf::DW_AT_GNU_pubtypes, Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID()), DwarfGnuPubTypesSectionSym); } } if (DIUnit.isOptimized()) NewCU->addFlag(Die, dwarf::DW_AT_APPLE_optimized); StringRef Flags = DIUnit.getFlags(); if (!Flags.empty()) NewCU->addString(Die, dwarf::DW_AT_APPLE_flags, Flags); if (unsigned RVer = DIUnit.getRunTimeVersion()) NewCU->addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers, dwarf::DW_FORM_data1, RVer); if (!FirstCU) FirstCU = NewCU; InfoHolder.addUnit(NewCU); CUMap.insert(std::make_pair(DIUnit, NewCU)); CUDieMap.insert(std::make_pair(Die, NewCU)); return NewCU; } // Construct subprogram DIE. void DwarfDebug::constructSubprogramDIE(CompileUnit *TheCU, const MDNode *N) { // FIXME: We should only call this routine once, however, during LTO if a // program is defined in multiple CUs we could end up calling it out of // beginModule as we walk the CUs. CompileUnit *&CURef = SPMap[N]; if (CURef) return; CURef = TheCU; DISubprogram SP(N); if (!SP.isDefinition()) // This is a method declaration which will be handled while constructing // class type. return; DIE *SubprogramDie = TheCU->getOrCreateSubprogramDIE(SP); // Expose as a global name. TheCU->addGlobalName(SP.getName(), SubprogramDie, resolve(SP.getContext())); } void DwarfDebug::constructImportedEntityDIE(CompileUnit *TheCU, const MDNode *N) { DIImportedEntity Module(N); if (!Module.Verify()) return; if (DIE *D = TheCU->getOrCreateContextDIE(Module.getContext())) constructImportedEntityDIE(TheCU, Module, D); } void DwarfDebug::constructImportedEntityDIE(CompileUnit *TheCU, const MDNode *N, DIE *Context) { DIImportedEntity Module(N); if (!Module.Verify()) return; return constructImportedEntityDIE(TheCU, Module, Context); } void DwarfDebug::constructImportedEntityDIE(CompileUnit *TheCU, const DIImportedEntity &Module, DIE *Context) { assert(Module.Verify() && "Use one of the MDNode * overloads to handle invalid metadata"); assert(Context && "Should always have a context for an imported_module"); DIE *IMDie = new DIE(Module.getTag()); TheCU->insertDIE(Module, IMDie); DIE *EntityDie; DIDescriptor Entity = Module.getEntity(); if (Entity.isNameSpace()) EntityDie = TheCU->getOrCreateNameSpace(DINameSpace(Entity)); else if (Entity.isSubprogram()) EntityDie = TheCU->getOrCreateSubprogramDIE(DISubprogram(Entity)); else if (Entity.isType()) EntityDie = TheCU->getOrCreateTypeDIE(DIType(Entity)); else EntityDie = TheCU->getDIE(Entity); unsigned FileID = getOrCreateSourceID(Module.getContext().getFilename(), Module.getContext().getDirectory(), TheCU->getUniqueID()); TheCU->addUInt(IMDie, dwarf::DW_AT_decl_file, None, FileID); TheCU->addUInt(IMDie, dwarf::DW_AT_decl_line, None, Module.getLineNumber()); TheCU->addDIEEntry(IMDie, dwarf::DW_AT_import, EntityDie); StringRef Name = Module.getName(); if (!Name.empty()) TheCU->addString(IMDie, dwarf::DW_AT_name, Name); Context->addChild(IMDie); } // Emit all Dwarf sections that should come prior to the content. Create // global DIEs and emit initial debug info sections. This is invoked by // the target AsmPrinter. void DwarfDebug::beginModule() { if (DisableDebugInfoPrinting) return; const Module *M = MMI->getModule(); // If module has named metadata anchors then use them, otherwise scan the // module using debug info finder to collect debug info. NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); if (!CU_Nodes) return; TypeIdentifierMap = generateDITypeIdentifierMap(CU_Nodes); // Emit initial sections so we can reference labels later. emitSectionLabels(); for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { DICompileUnit CUNode(CU_Nodes->getOperand(i)); CompileUnit *CU = constructCompileUnit(CUNode); DIArray ImportedEntities = CUNode.getImportedEntities(); for (unsigned i = 0, e = ImportedEntities.getNumElements(); i != e; ++i) ScopesWithImportedEntities.push_back(std::make_pair( DIImportedEntity(ImportedEntities.getElement(i)).getContext(), ImportedEntities.getElement(i))); std::sort(ScopesWithImportedEntities.begin(), ScopesWithImportedEntities.end(), less_first()); DIArray GVs = CUNode.getGlobalVariables(); for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i) CU->createGlobalVariableDIE(DIGlobalVariable(GVs.getElement(i))); DIArray SPs = CUNode.getSubprograms(); for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) constructSubprogramDIE(CU, SPs.getElement(i)); DIArray EnumTypes = CUNode.getEnumTypes(); for (unsigned i = 0, e = EnumTypes.getNumElements(); i != e; ++i) CU->getOrCreateTypeDIE(EnumTypes.getElement(i)); DIArray RetainedTypes = CUNode.getRetainedTypes(); for (unsigned i = 0, e = RetainedTypes.getNumElements(); i != e; ++i) CU->getOrCreateTypeDIE(RetainedTypes.getElement(i)); // Emit imported_modules last so that the relevant context is already // available. for (unsigned i = 0, e = ImportedEntities.getNumElements(); i != e; ++i) constructImportedEntityDIE(CU, ImportedEntities.getElement(i)); } // Tell MMI that we have debug info. MMI->setDebugInfoAvailability(true); // Prime section data. SectionMap[Asm->getObjFileLowering().getTextSection()]; } // Attach DW_AT_inline attribute with inlined subprogram DIEs. void DwarfDebug::computeInlinedDIEs() { // Attach DW_AT_inline attribute with inlined subprogram DIEs. for (SmallPtrSet::iterator AI = InlinedSubprogramDIEs.begin(), AE = InlinedSubprogramDIEs.end(); AI != AE; ++AI) { DIE *ISP = *AI; FirstCU->addUInt(ISP, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined); } for (DenseMap::iterator AI = AbstractSPDies.begin(), AE = AbstractSPDies.end(); AI != AE; ++AI) { DIE *ISP = AI->second; if (InlinedSubprogramDIEs.count(ISP)) continue; FirstCU->addUInt(ISP, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined); } } // Collect info for variables that were optimized out. void DwarfDebug::collectDeadVariables() { const Module *M = MMI->getModule(); if (NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu")) { for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { DICompileUnit TheCU(CU_Nodes->getOperand(i)); DIArray Subprograms = TheCU.getSubprograms(); for (unsigned i = 0, e = Subprograms.getNumElements(); i != e; ++i) { DISubprogram SP(Subprograms.getElement(i)); if (ProcessedSPNodes.count(SP) != 0) continue; if (!SP.isSubprogram()) continue; if (!SP.isDefinition()) continue; DIArray Variables = SP.getVariables(); if (Variables.getNumElements() == 0) continue; // Construct subprogram DIE and add variables DIEs. CompileUnit *SPCU = CUMap.lookup(TheCU); assert(SPCU && "Unable to find Compile Unit!"); // FIXME: See the comment in constructSubprogramDIE about duplicate // subprogram DIEs. constructSubprogramDIE(SPCU, SP); DIE *SPDIE = SPCU->getDIE(SP); for (unsigned vi = 0, ve = Variables.getNumElements(); vi != ve; ++vi) { DIVariable DV(Variables.getElement(vi)); if (!DV.isVariable()) continue; DbgVariable NewVar(DV, NULL, this); if (DIE *VariableDIE = SPCU->constructVariableDIE(NewVar, false)) SPDIE->addChild(VariableDIE); } } } } } // Type Signature [7.27] and ODR Hash code. /// \brief Grabs the string in whichever attribute is passed in and returns /// a reference to it. Returns "" if the attribute doesn't exist. static StringRef getDIEStringAttr(DIE *Die, unsigned Attr) { DIEValue *V = Die->findAttribute(Attr); if (DIEString *S = dyn_cast_or_null(V)) return S->getString(); return StringRef(""); } /// Return true if the current DIE is contained within an anonymous namespace. static bool isContainedInAnonNamespace(DIE *Die) { DIE *Parent = Die->getParent(); while (Parent) { if (Parent->getTag() == dwarf::DW_TAG_namespace && getDIEStringAttr(Parent, dwarf::DW_AT_name) == "") return true; Parent = Parent->getParent(); } return false; } /// Test if the current CU language is C++ and that we have /// a named type that is not contained in an anonymous namespace. static bool shouldAddODRHash(CompileUnit *CU, DIE *Die) { return CU->getLanguage() == dwarf::DW_LANG_C_plus_plus && getDIEStringAttr(Die, dwarf::DW_AT_name) != "" && !isContainedInAnonNamespace(Die); } void DwarfDebug::finalizeModuleInfo() { // Collect info for variables that were optimized out. collectDeadVariables(); // Attach DW_AT_inline attribute with inlined subprogram DIEs. computeInlinedDIEs(); // Split out type units and conditionally add an ODR tag to the split // out type. // FIXME: Do type splitting. for (unsigned i = 0, e = TypeUnits.size(); i != e; ++i) { DIE *Die = TypeUnits[i]; DIEHash Hash; // If we've requested ODR hashes and it's applicable for an ODR hash then // add the ODR signature now. // FIXME: This should be added onto the type unit, not the type, but this // works as an intermediate stage. if (GenerateODRHash && shouldAddODRHash(CUMap.begin()->second, Die)) CUMap.begin()->second->addUInt(Die, dwarf::DW_AT_GNU_odr_signature, dwarf::DW_FORM_data8, Hash.computeDIEODRSignature(*Die)); } // Handle anything that needs to be done on a per-cu basis. for (DenseMap::iterator CUI = CUMap.begin(), CUE = CUMap.end(); CUI != CUE; ++CUI) { CompileUnit *TheCU = CUI->second; // Emit DW_AT_containing_type attribute to connect types with their // vtable holding type. TheCU->constructContainingTypeDIEs(); // If we're splitting the dwarf out now that we've got the entire // CU then construct a skeleton CU based upon it. if (useSplitDwarf()) { uint64_t ID = 0; if (GenerateCUHash) { DIEHash CUHash; ID = CUHash.computeCUSignature(*TheCU->getCUDie()); } // This should be a unique identifier when we want to build .dwp files. TheCU->addUInt(TheCU->getCUDie(), dwarf::DW_AT_GNU_dwo_id, dwarf::DW_FORM_data8, ID); // Now construct the skeleton CU associated. CompileUnit *SkCU = constructSkeletonCU(TheCU); // This should be a unique identifier when we want to build .dwp files. SkCU->addUInt(SkCU->getCUDie(), dwarf::DW_AT_GNU_dwo_id, dwarf::DW_FORM_data8, ID); } } // Compute DIE offsets and sizes. InfoHolder.computeSizeAndOffsets(); if (useSplitDwarf()) SkeletonHolder.computeSizeAndOffsets(); } void DwarfDebug::endSections() { // Filter labels by section. for (size_t n = 0; n < ArangeLabels.size(); n++) { const SymbolCU &SCU = ArangeLabels[n]; if (SCU.Sym->isInSection()) { // Make a note of this symbol and it's section. const MCSection *Section = &SCU.Sym->getSection(); if (!Section->getKind().isMetadata()) SectionMap[Section].push_back(SCU); } else { // Some symbols (e.g. common/bss on mach-o) can have no section but still // appear in the output. This sucks as we rely on sections to build // arange spans. We can do it without, but it's icky. SectionMap[NULL].push_back(SCU); } } // Build a list of sections used. std::vector Sections; for (SectionMapType::iterator it = SectionMap.begin(); it != SectionMap.end(); it++) { const MCSection *Section = it->first; Sections.push_back(Section); } // Sort the sections into order. // This is only done to ensure consistent output order across different runs. std::sort(Sections.begin(), Sections.end(), SectionSort); // Add terminating symbols for each section. for (unsigned ID=0;IDGetTempSymbol("debug_end", ID); Asm->OutStreamer.SwitchSection(Section); Asm->OutStreamer.EmitLabel(Sym); } // Insert a final terminator. SectionMap[Section].push_back(SymbolCU(NULL, Sym)); } } // Emit all Dwarf sections that should come after the content. void DwarfDebug::endModule() { if (!FirstCU) return; // End any existing sections. // TODO: Does this need to happen? endSections(); // Finalize the debug info for the module. finalizeModuleInfo(); if (!useSplitDwarf()) { emitDebugStr(); // Emit all the DIEs into a debug info section. emitDebugInfo(); // Corresponding abbreviations into a abbrev section. emitAbbreviations(); // Emit info into a debug loc section. emitDebugLoc(); // Emit info into a debug aranges section. emitDebugARanges(); // Emit info into a debug ranges section. emitDebugRanges(); // Emit info into a debug macinfo section. emitDebugMacInfo(); } else { // TODO: Fill this in for separated debug sections and separate // out information into new sections. emitDebugStr(); if (useSplitDwarf()) emitDebugStrDWO(); // Emit the debug info section and compile units. emitDebugInfo(); emitDebugInfoDWO(); // Corresponding abbreviations into a abbrev section. emitAbbreviations(); emitDebugAbbrevDWO(); // Emit info into a debug loc section. emitDebugLoc(); // Emit info into a debug aranges section. emitDebugARanges(); // Emit info into a debug ranges section. emitDebugRanges(); // Emit info into a debug macinfo section. emitDebugMacInfo(); // Emit DWO addresses. InfoHolder.emitAddresses(Asm->getObjFileLowering().getDwarfAddrSection()); } // Emit info into the dwarf accelerator table sections. if (useDwarfAccelTables()) { emitAccelNames(); emitAccelObjC(); emitAccelNamespaces(); emitAccelTypes(); } // Emit the pubnames and pubtypes sections if requested. if (HasDwarfPubSections) { emitDebugPubNames(GenerateGnuPubSections); emitDebugPubTypes(GenerateGnuPubSections); } // clean up. SPMap.clear(); for (DenseMap::iterator I = CUMap.begin(), E = CUMap.end(); I != E; ++I) delete I->second; for (SmallVectorImpl::iterator I = SkeletonCUs.begin(), E = SkeletonCUs.end(); I != E; ++I) delete *I; // Reset these for the next Module if we have one. FirstCU = NULL; } // Find abstract variable, if any, associated with Var. DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &DV, DebugLoc ScopeLoc) { LLVMContext &Ctx = DV->getContext(); // More then one inlined variable corresponds to one abstract variable. DIVariable Var = cleanseInlinedVariable(DV, Ctx); DbgVariable *AbsDbgVariable = AbstractVariables.lookup(Var); if (AbsDbgVariable) return AbsDbgVariable; LexicalScope *Scope = LScopes.findAbstractScope(ScopeLoc.getScope(Ctx)); if (!Scope) return NULL; AbsDbgVariable = new DbgVariable(Var, NULL, this); addScopeVariable(Scope, AbsDbgVariable); AbstractVariables[Var] = AbsDbgVariable; return AbsDbgVariable; } // If Var is a current function argument then add it to CurrentFnArguments list. bool DwarfDebug::addCurrentFnArgument(const MachineFunction *MF, DbgVariable *Var, LexicalScope *Scope) { if (!LScopes.isCurrentFunctionScope(Scope)) return false; DIVariable DV = Var->getVariable(); if (DV.getTag() != dwarf::DW_TAG_arg_variable) return false; unsigned ArgNo = DV.getArgNumber(); if (ArgNo == 0) return false; size_t Size = CurrentFnArguments.size(); if (Size == 0) CurrentFnArguments.resize(MF->getFunction()->arg_size()); // llvm::Function argument size is not good indicator of how many // arguments does the function have at source level. if (ArgNo > Size) CurrentFnArguments.resize(ArgNo * 2); CurrentFnArguments[ArgNo - 1] = Var; return true; } // Collect variable information from side table maintained by MMI. void DwarfDebug::collectVariableInfoFromMMITable(const MachineFunction *MF, SmallPtrSet &Processed) { MachineModuleInfo::VariableDbgInfoMapTy &VMap = MMI->getVariableDbgInfo(); for (MachineModuleInfo::VariableDbgInfoMapTy::iterator VI = VMap.begin(), VE = VMap.end(); VI != VE; ++VI) { const MDNode *Var = VI->first; if (!Var) continue; Processed.insert(Var); DIVariable DV(Var); const std::pair &VP = VI->second; LexicalScope *Scope = LScopes.findLexicalScope(VP.second); // If variable scope is not found then skip this variable. if (Scope == 0) continue; DbgVariable *AbsDbgVariable = findAbstractVariable(DV, VP.second); DbgVariable *RegVar = new DbgVariable(DV, AbsDbgVariable, this); RegVar->setFrameIndex(VP.first); if (!addCurrentFnArgument(MF, RegVar, Scope)) addScopeVariable(Scope, RegVar); if (AbsDbgVariable) AbsDbgVariable->setFrameIndex(VP.first); } } // Return true if debug value, encoded by DBG_VALUE instruction, is in a // defined reg. static bool isDbgValueInDefinedReg(const MachineInstr *MI) { assert(MI->isDebugValue() && "Invalid DBG_VALUE machine instruction!"); return MI->getNumOperands() == 3 && MI->getOperand(0).isReg() && MI->getOperand(0).getReg() && (MI->getOperand(1).isImm() || (MI->getOperand(1).isReg() && MI->getOperand(1).getReg() == 0U)); } // Get .debug_loc entry for the instruction range starting at MI. static DotDebugLocEntry getDebugLocEntry(AsmPrinter *Asm, const MCSymbol *FLabel, const MCSymbol *SLabel, const MachineInstr *MI) { const MDNode *Var = MI->getOperand(MI->getNumOperands() - 1).getMetadata(); assert(MI->getNumOperands() == 3); if (MI->getOperand(0).isReg()) { MachineLocation MLoc; // If the second operand is an immediate, this is a // register-indirect address. if (!MI->getOperand(1).isImm()) MLoc.set(MI->getOperand(0).getReg()); else MLoc.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm()); return DotDebugLocEntry(FLabel, SLabel, MLoc, Var); } if (MI->getOperand(0).isImm()) return DotDebugLocEntry(FLabel, SLabel, MI->getOperand(0).getImm()); if (MI->getOperand(0).isFPImm()) return DotDebugLocEntry(FLabel, SLabel, MI->getOperand(0).getFPImm()); if (MI->getOperand(0).isCImm()) return DotDebugLocEntry(FLabel, SLabel, MI->getOperand(0).getCImm()); llvm_unreachable("Unexpected 3 operand DBG_VALUE instruction!"); } // Find variables for each lexical scope. void DwarfDebug::collectVariableInfo(const MachineFunction *MF, SmallPtrSet &Processed) { // Grab the variable info that was squirreled away in the MMI side-table. collectVariableInfoFromMMITable(MF, Processed); for (SmallVectorImpl::const_iterator UVI = UserVariables.begin(), UVE = UserVariables.end(); UVI != UVE; ++UVI) { const MDNode *Var = *UVI; if (Processed.count(Var)) continue; // History contains relevant DBG_VALUE instructions for Var and instructions // clobbering it. SmallVectorImpl &History = DbgValues[Var]; if (History.empty()) continue; const MachineInstr *MInsn = History.front(); DIVariable DV(Var); LexicalScope *Scope = NULL; if (DV.getTag() == dwarf::DW_TAG_arg_variable && DISubprogram(DV.getContext()).describes(MF->getFunction())) Scope = LScopes.getCurrentFunctionScope(); else if (MDNode *IA = DV.getInlinedAt()) Scope = LScopes.findInlinedScope(DebugLoc::getFromDILocation(IA)); else Scope = LScopes.findLexicalScope(cast(DV->getOperand(1))); // If variable scope is not found then skip this variable. if (!Scope) continue; Processed.insert(DV); assert(MInsn->isDebugValue() && "History must begin with debug value"); DbgVariable *AbsVar = findAbstractVariable(DV, MInsn->getDebugLoc()); DbgVariable *RegVar = new DbgVariable(DV, AbsVar, this); if (!addCurrentFnArgument(MF, RegVar, Scope)) addScopeVariable(Scope, RegVar); if (AbsVar) AbsVar->setMInsn(MInsn); // Simplify ranges that are fully coalesced. if (History.size() <= 1 || (History.size() == 2 && MInsn->isIdenticalTo(History.back()))) { RegVar->setMInsn(MInsn); continue; } // Handle multiple DBG_VALUE instructions describing one variable. RegVar->setDotDebugLocOffset(DotDebugLocEntries.size()); for (SmallVectorImpl::const_iterator HI = History.begin(), HE = History.end(); HI != HE; ++HI) { const MachineInstr *Begin = *HI; assert(Begin->isDebugValue() && "Invalid History entry"); // Check if DBG_VALUE is truncating a range. if (Begin->getNumOperands() > 1 && Begin->getOperand(0).isReg() && !Begin->getOperand(0).getReg()) continue; // Compute the range for a register location. const MCSymbol *FLabel = getLabelBeforeInsn(Begin); const MCSymbol *SLabel = 0; if (HI + 1 == HE) // If Begin is the last instruction in History then its value is valid // until the end of the function. SLabel = FunctionEndSym; else { const MachineInstr *End = HI[1]; DEBUG(dbgs() << "DotDebugLoc Pair:\n" << "\t" << *Begin << "\t" << *End << "\n"); if (End->isDebugValue()) SLabel = getLabelBeforeInsn(End); else { // End is a normal instruction clobbering the range. SLabel = getLabelAfterInsn(End); assert(SLabel && "Forgot label after clobber instruction"); ++HI; } } // The value is valid until the next DBG_VALUE or clobber. DotDebugLocEntries.push_back(getDebugLocEntry(Asm, FLabel, SLabel, Begin)); } DotDebugLocEntries.push_back(DotDebugLocEntry()); } // Collect info for variables that were optimized out. LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); DIArray Variables = DISubprogram(FnScope->getScopeNode()).getVariables(); for (unsigned i = 0, e = Variables.getNumElements(); i != e; ++i) { DIVariable DV(Variables.getElement(i)); if (!DV || !DV.isVariable() || !Processed.insert(DV)) continue; if (LexicalScope *Scope = LScopes.findLexicalScope(DV.getContext())) addScopeVariable(Scope, new DbgVariable(DV, NULL, this)); } } // Return Label preceding the instruction. MCSymbol *DwarfDebug::getLabelBeforeInsn(const MachineInstr *MI) { MCSymbol *Label = LabelsBeforeInsn.lookup(MI); assert(Label && "Didn't insert label before instruction"); return Label; } // Return Label immediately following the instruction. MCSymbol *DwarfDebug::getLabelAfterInsn(const MachineInstr *MI) { return LabelsAfterInsn.lookup(MI); } // Process beginning of an instruction. void DwarfDebug::beginInstruction(const MachineInstr *MI) { // Check if source location changes, but ignore DBG_VALUE locations. if (!MI->isDebugValue()) { DebugLoc DL = MI->getDebugLoc(); if (DL != PrevInstLoc && (!DL.isUnknown() || UnknownLocations)) { unsigned Flags = 0; PrevInstLoc = DL; if (DL == PrologEndLoc) { Flags |= DWARF2_FLAG_PROLOGUE_END; PrologEndLoc = DebugLoc(); } if (PrologEndLoc.isUnknown()) Flags |= DWARF2_FLAG_IS_STMT; if (!DL.isUnknown()) { const MDNode *Scope = DL.getScope(Asm->MF->getFunction()->getContext()); recordSourceLine(DL.getLine(), DL.getCol(), Scope, Flags); } else recordSourceLine(0, 0, 0, 0); } } // Insert labels where requested. DenseMap::iterator I = LabelsBeforeInsn.find(MI); // No label needed. if (I == LabelsBeforeInsn.end()) return; // Label already assigned. if (I->second) return; if (!PrevLabel) { PrevLabel = MMI->getContext().CreateTempSymbol(); Asm->OutStreamer.EmitLabel(PrevLabel); } I->second = PrevLabel; } // Process end of an instruction. void DwarfDebug::endInstruction(const MachineInstr *MI) { // Don't create a new label after DBG_VALUE instructions. // They don't generate code. if (!MI->isDebugValue()) PrevLabel = 0; DenseMap::iterator I = LabelsAfterInsn.find(MI); // No label needed. if (I == LabelsAfterInsn.end()) return; // Label already assigned. if (I->second) return; // We need a label after this instruction. if (!PrevLabel) { PrevLabel = MMI->getContext().CreateTempSymbol(); Asm->OutStreamer.EmitLabel(PrevLabel); } I->second = PrevLabel; } // Each LexicalScope has first instruction and last instruction to mark // beginning and end of a scope respectively. Create an inverse map that list // scopes starts (and ends) with an instruction. One instruction may start (or // end) multiple scopes. Ignore scopes that are not reachable. void DwarfDebug::identifyScopeMarkers() { SmallVector WorkList; WorkList.push_back(LScopes.getCurrentFunctionScope()); while (!WorkList.empty()) { LexicalScope *S = WorkList.pop_back_val(); const SmallVectorImpl &Children = S->getChildren(); if (!Children.empty()) for (SmallVectorImpl::const_iterator SI = Children.begin(), SE = Children.end(); SI != SE; ++SI) WorkList.push_back(*SI); if (S->isAbstractScope()) continue; const SmallVectorImpl &Ranges = S->getRanges(); if (Ranges.empty()) continue; for (SmallVectorImpl::const_iterator RI = Ranges.begin(), RE = Ranges.end(); RI != RE; ++RI) { assert(RI->first && "InsnRange does not have first instruction!"); assert(RI->second && "InsnRange does not have second instruction!"); requestLabelBeforeInsn(RI->first); requestLabelAfterInsn(RI->second); } } } // Get MDNode for DebugLoc's scope. static MDNode *getScopeNode(DebugLoc DL, const LLVMContext &Ctx) { if (MDNode *InlinedAt = DL.getInlinedAt(Ctx)) return getScopeNode(DebugLoc::getFromDILocation(InlinedAt), Ctx); return DL.getScope(Ctx); } // Walk up the scope chain of given debug loc and find line number info // for the function. static DebugLoc getFnDebugLoc(DebugLoc DL, const LLVMContext &Ctx) { const MDNode *Scope = getScopeNode(DL, Ctx); DISubprogram SP = getDISubprogram(Scope); if (SP.isSubprogram()) { // Check for number of operands since the compatibility is // cheap here. if (SP->getNumOperands() > 19) return DebugLoc::get(SP.getScopeLineNumber(), 0, SP); else return DebugLoc::get(SP.getLineNumber(), 0, SP); } return DebugLoc(); } // Gather pre-function debug information. Assumes being called immediately // after the function entry point has been emitted. void DwarfDebug::beginFunction(const MachineFunction *MF) { // If there's no debug info for the function we're not going to do anything. if (!MMI->hasDebugInfo()) return; // Grab the lexical scopes for the function, if we don't have any of those // then we're not going to be able to do anything. LScopes.initialize(*MF); if (LScopes.empty()) return; assert(UserVariables.empty() && DbgValues.empty() && "Maps weren't cleaned"); // Make sure that each lexical scope will have a begin/end label. identifyScopeMarkers(); // Set DwarfCompileUnitID in MCContext to the Compile Unit this function // belongs to so that we add to the correct per-cu line table in the // non-asm case. LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); CompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); assert(TheCU && "Unable to find compile unit!"); if (Asm->TM.hasMCUseLoc() && Asm->OutStreamer.hasRawTextSupport()) // Use a single line table if we are using .loc and generating assembly. Asm->OutStreamer.getContext().setDwarfCompileUnitID(0); else Asm->OutStreamer.getContext().setDwarfCompileUnitID(TheCU->getUniqueID()); // Emit a label for the function so that we have a beginning address. FunctionBeginSym = Asm->GetTempSymbol("func_begin", Asm->getFunctionNumber()); // Assumes in correct section after the entry point. Asm->OutStreamer.EmitLabel(FunctionBeginSym); const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo(); // LiveUserVar - Map physreg numbers to the MDNode they contain. std::vector LiveUserVar(TRI->getNumRegs()); for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); I != E; ++I) { bool AtBlockEntry = true; for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); II != IE; ++II) { const MachineInstr *MI = II; if (MI->isDebugValue()) { assert(MI->getNumOperands() > 1 && "Invalid machine instruction!"); // Keep track of user variables. const MDNode *Var = MI->getOperand(MI->getNumOperands() - 1).getMetadata(); // Variable is in a register, we need to check for clobbers. if (isDbgValueInDefinedReg(MI)) LiveUserVar[MI->getOperand(0).getReg()] = Var; // Check the history of this variable. SmallVectorImpl &History = DbgValues[Var]; if (History.empty()) { UserVariables.push_back(Var); // The first mention of a function argument gets the FunctionBeginSym // label, so arguments are visible when breaking at function entry. DIVariable DV(Var); if (DV.isVariable() && DV.getTag() == dwarf::DW_TAG_arg_variable && getDISubprogram(DV.getContext()).describes(MF->getFunction())) LabelsBeforeInsn[MI] = FunctionBeginSym; } else { // We have seen this variable before. Try to coalesce DBG_VALUEs. const MachineInstr *Prev = History.back(); if (Prev->isDebugValue()) { // Coalesce identical entries at the end of History. if (History.size() >= 2 && Prev->isIdenticalTo(History[History.size() - 2])) { DEBUG(dbgs() << "Coalescing identical DBG_VALUE entries:\n" << "\t" << *Prev << "\t" << *History[History.size() - 2] << "\n"); History.pop_back(); } // Terminate old register assignments that don't reach MI; MachineFunction::const_iterator PrevMBB = Prev->getParent(); if (PrevMBB != I && (!AtBlockEntry || llvm::next(PrevMBB) != I) && isDbgValueInDefinedReg(Prev)) { // Previous register assignment needs to terminate at the end of // its basic block. MachineBasicBlock::const_iterator LastMI = PrevMBB->getLastNonDebugInstr(); if (LastMI == PrevMBB->end()) { // Drop DBG_VALUE for empty range. DEBUG(dbgs() << "Dropping DBG_VALUE for empty range:\n" << "\t" << *Prev << "\n"); History.pop_back(); } else if (llvm::next(PrevMBB) != PrevMBB->getParent()->end()) // Terminate after LastMI. History.push_back(LastMI); } } } History.push_back(MI); } else { // Not a DBG_VALUE instruction. if (!MI->isLabel()) AtBlockEntry = false; // First known non-DBG_VALUE and non-frame setup location marks // the beginning of the function body. if (!MI->getFlag(MachineInstr::FrameSetup) && (PrologEndLoc.isUnknown() && !MI->getDebugLoc().isUnknown())) PrologEndLoc = MI->getDebugLoc(); // Check if the instruction clobbers any registers with debug vars. for (MachineInstr::const_mop_iterator MOI = MI->operands_begin(), MOE = MI->operands_end(); MOI != MOE; ++MOI) { if (!MOI->isReg() || !MOI->isDef() || !MOI->getReg()) continue; for (MCRegAliasIterator AI(MOI->getReg(), TRI, true); AI.isValid(); ++AI) { unsigned Reg = *AI; const MDNode *Var = LiveUserVar[Reg]; if (!Var) continue; // Reg is now clobbered. LiveUserVar[Reg] = 0; // Was MD last defined by a DBG_VALUE referring to Reg? DbgValueHistoryMap::iterator HistI = DbgValues.find(Var); if (HistI == DbgValues.end()) continue; SmallVectorImpl &History = HistI->second; if (History.empty()) continue; const MachineInstr *Prev = History.back(); // Sanity-check: Register assignments are terminated at the end of // their block. if (!Prev->isDebugValue() || Prev->getParent() != MI->getParent()) continue; // Is the variable still in Reg? if (!isDbgValueInDefinedReg(Prev) || Prev->getOperand(0).getReg() != Reg) continue; // Var is clobbered. Make sure the next instruction gets a label. History.push_back(MI); } } } } } for (DbgValueHistoryMap::iterator I = DbgValues.begin(), E = DbgValues.end(); I != E; ++I) { SmallVectorImpl &History = I->second; if (History.empty()) continue; // Make sure the final register assignments are terminated. const MachineInstr *Prev = History.back(); if (Prev->isDebugValue() && isDbgValueInDefinedReg(Prev)) { const MachineBasicBlock *PrevMBB = Prev->getParent(); MachineBasicBlock::const_iterator LastMI = PrevMBB->getLastNonDebugInstr(); if (LastMI == PrevMBB->end()) // Drop DBG_VALUE for empty range. History.pop_back(); else if (PrevMBB != &PrevMBB->getParent()->back()) { // Terminate after LastMI. History.push_back(LastMI); } } // Request labels for the full history. for (unsigned i = 0, e = History.size(); i != e; ++i) { const MachineInstr *MI = History[i]; if (MI->isDebugValue()) requestLabelBeforeInsn(MI); else requestLabelAfterInsn(MI); } } PrevInstLoc = DebugLoc(); PrevLabel = FunctionBeginSym; // Record beginning of function. if (!PrologEndLoc.isUnknown()) { DebugLoc FnStartDL = getFnDebugLoc(PrologEndLoc, MF->getFunction()->getContext()); recordSourceLine( FnStartDL.getLine(), FnStartDL.getCol(), FnStartDL.getScope(MF->getFunction()->getContext()), // We'd like to list the prologue as "not statements" but GDB behaves // poorly if we do that. Revisit this with caution/GDB (7.5+) testing. DWARF2_FLAG_IS_STMT); } } void DwarfDebug::addScopeVariable(LexicalScope *LS, DbgVariable *Var) { SmallVectorImpl &Vars = ScopeVariables[LS]; DIVariable DV = Var->getVariable(); // Variables with positive arg numbers are parameters. if (unsigned ArgNum = DV.getArgNumber()) { // Keep all parameters in order at the start of the variable list to ensure // function types are correct (no out-of-order parameters) // // This could be improved by only doing it for optimized builds (unoptimized // builds have the right order to begin with), searching from the back (this // would catch the unoptimized case quickly), or doing a binary search // rather than linear search. SmallVectorImpl::iterator I = Vars.begin(); while (I != Vars.end()) { unsigned CurNum = (*I)->getVariable().getArgNumber(); // A local (non-parameter) variable has been found, insert immediately // before it. if (CurNum == 0) break; // A later indexed parameter has been found, insert immediately before it. if (CurNum > ArgNum) break; ++I; } Vars.insert(I, Var); return; } Vars.push_back(Var); } // Gather and emit post-function debug information. void DwarfDebug::endFunction(const MachineFunction *MF) { if (!MMI->hasDebugInfo() || LScopes.empty()) return; // Define end label for subprogram. FunctionEndSym = Asm->GetTempSymbol("func_end", Asm->getFunctionNumber()); // Assumes in correct section after the entry point. Asm->OutStreamer.EmitLabel(FunctionEndSym); // Set DwarfCompileUnitID in MCContext to default value. Asm->OutStreamer.getContext().setDwarfCompileUnitID(0); SmallPtrSet ProcessedVars; collectVariableInfo(MF, ProcessedVars); LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); CompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); assert(TheCU && "Unable to find compile unit!"); // Construct abstract scopes. ArrayRef AList = LScopes.getAbstractScopesList(); for (unsigned i = 0, e = AList.size(); i != e; ++i) { LexicalScope *AScope = AList[i]; DISubprogram SP(AScope->getScopeNode()); if (SP.isSubprogram()) { // Collect info for variables that were optimized out. DIArray Variables = SP.getVariables(); for (unsigned i = 0, e = Variables.getNumElements(); i != e; ++i) { DIVariable DV(Variables.getElement(i)); if (!DV || !DV.isVariable() || !ProcessedVars.insert(DV)) continue; // Check that DbgVariable for DV wasn't created earlier, when // findAbstractVariable() was called for inlined instance of DV. LLVMContext &Ctx = DV->getContext(); DIVariable CleanDV = cleanseInlinedVariable(DV, Ctx); if (AbstractVariables.lookup(CleanDV)) continue; if (LexicalScope *Scope = LScopes.findAbstractScope(DV.getContext())) addScopeVariable(Scope, new DbgVariable(DV, NULL, this)); } } if (ProcessedSPNodes.count(AScope->getScopeNode()) == 0) constructScopeDIE(TheCU, AScope); } DIE *CurFnDIE = constructScopeDIE(TheCU, FnScope); if (!MF->getTarget().Options.DisableFramePointerElim(*MF)) TheCU->addFlag(CurFnDIE, dwarf::DW_AT_APPLE_omit_frame_ptr); // Clear debug info for (ScopeVariablesMap::iterator I = ScopeVariables.begin(), E = ScopeVariables.end(); I != E; ++I) DeleteContainerPointers(I->second); ScopeVariables.clear(); DeleteContainerPointers(CurrentFnArguments); UserVariables.clear(); DbgValues.clear(); AbstractVariables.clear(); LabelsBeforeInsn.clear(); LabelsAfterInsn.clear(); PrevLabel = NULL; } // Register a source line with debug info. Returns the unique label that was // emitted and which provides correspondence to the source line list. void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S, unsigned Flags) { StringRef Fn; StringRef Dir; unsigned Src = 1; if (S) { DIDescriptor Scope(S); if (Scope.isCompileUnit()) { DICompileUnit CU(S); Fn = CU.getFilename(); Dir = CU.getDirectory(); } else if (Scope.isFile()) { DIFile F(S); Fn = F.getFilename(); Dir = F.getDirectory(); } else if (Scope.isSubprogram()) { DISubprogram SP(S); Fn = SP.getFilename(); Dir = SP.getDirectory(); } else if (Scope.isLexicalBlockFile()) { DILexicalBlockFile DBF(S); Fn = DBF.getFilename(); Dir = DBF.getDirectory(); } else if (Scope.isLexicalBlock()) { DILexicalBlock DB(S); Fn = DB.getFilename(); Dir = DB.getDirectory(); } else llvm_unreachable("Unexpected scope info"); Src = getOrCreateSourceID(Fn, Dir, Asm->OutStreamer.getContext().getDwarfCompileUnitID()); } Asm->OutStreamer.EmitDwarfLocDirective(Src, Line, Col, Flags, 0, 0, Fn); } //===----------------------------------------------------------------------===// // Emit Methods //===----------------------------------------------------------------------===// // Compute the size and offset of a DIE. The offset is relative to start of the // CU. It returns the offset after laying out the DIE. unsigned DwarfUnits::computeSizeAndOffset(DIE *Die, unsigned Offset) { // Get the children. const std::vector &Children = Die->getChildren(); // Record the abbreviation. assignAbbrevNumber(Die->getAbbrev()); // Get the abbreviation for this DIE. unsigned AbbrevNumber = Die->getAbbrevNumber(); const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1]; // Set DIE offset Die->setOffset(Offset); // Start the size with the size of abbreviation code. Offset += MCAsmInfo::getULEB128Size(AbbrevNumber); const SmallVectorImpl &Values = Die->getValues(); const SmallVectorImpl &AbbrevData = Abbrev->getData(); // Size the DIE attribute values. for (unsigned i = 0, N = Values.size(); i < N; ++i) // Size attribute value. Offset += Values[i]->SizeOf(Asm, AbbrevData[i].getForm()); // Size the DIE children if any. if (!Children.empty()) { assert(Abbrev->getChildrenFlag() == dwarf::DW_CHILDREN_yes && "Children flag not set"); for (unsigned j = 0, M = Children.size(); j < M; ++j) Offset = computeSizeAndOffset(Children[j], Offset); // End of children marker. Offset += sizeof(int8_t); } Die->setSize(Offset - Die->getOffset()); return Offset; } // Compute the size and offset for each DIE. void DwarfUnits::computeSizeAndOffsets() { // Offset from the first CU in the debug info section is 0 initially. unsigned SecOffset = 0; // Iterate over each compile unit and set the size and offsets for each // DIE within each compile unit. All offsets are CU relative. for (SmallVectorImpl::iterator I = CUs.begin(), E = CUs.end(); I != E; ++I) { (*I)->setDebugInfoOffset(SecOffset); // CU-relative offset is reset to 0 here. unsigned Offset = sizeof(int32_t) + // Length of Unit Info (*I)->getHeaderSize(); // Unit-specific headers // EndOffset here is CU-relative, after laying out // all of the CU DIE. unsigned EndOffset = computeSizeAndOffset((*I)->getCUDie(), Offset); SecOffset += EndOffset; } } // Emit initial Dwarf sections with a label at the start of each one. void DwarfDebug::emitSectionLabels() { const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); // Dwarf sections base addresses. DwarfInfoSectionSym = emitSectionSym(Asm, TLOF.getDwarfInfoSection(), "section_info"); DwarfAbbrevSectionSym = emitSectionSym(Asm, TLOF.getDwarfAbbrevSection(), "section_abbrev"); if (useSplitDwarf()) DwarfAbbrevDWOSectionSym = emitSectionSym(Asm, TLOF.getDwarfAbbrevDWOSection(), "section_abbrev_dwo"); emitSectionSym(Asm, TLOF.getDwarfARangesSection()); if (const MCSection *MacroInfo = TLOF.getDwarfMacroInfoSection()) emitSectionSym(Asm, MacroInfo); DwarfLineSectionSym = emitSectionSym(Asm, TLOF.getDwarfLineSection(), "section_line"); emitSectionSym(Asm, TLOF.getDwarfLocSection()); if (GenerateGnuPubSections) { DwarfGnuPubNamesSectionSym = emitSectionSym(Asm, TLOF.getDwarfGnuPubNamesSection()); DwarfGnuPubTypesSectionSym = emitSectionSym(Asm, TLOF.getDwarfGnuPubTypesSection()); } else if (HasDwarfPubSections) { emitSectionSym(Asm, TLOF.getDwarfPubNamesSection()); emitSectionSym(Asm, TLOF.getDwarfPubTypesSection()); } DwarfStrSectionSym = emitSectionSym(Asm, TLOF.getDwarfStrSection(), "info_string"); if (useSplitDwarf()) { DwarfStrDWOSectionSym = emitSectionSym(Asm, TLOF.getDwarfStrDWOSection(), "skel_string"); DwarfAddrSectionSym = emitSectionSym(Asm, TLOF.getDwarfAddrSection(), "addr_sec"); } DwarfDebugRangeSectionSym = emitSectionSym(Asm, TLOF.getDwarfRangesSection(), "debug_range"); DwarfDebugLocSectionSym = emitSectionSym(Asm, TLOF.getDwarfLocSection(), "section_debug_loc"); TextSectionSym = emitSectionSym(Asm, TLOF.getTextSection(), "text_begin"); emitSectionSym(Asm, TLOF.getDataSection()); } // Recursively emits a debug information entry. void DwarfDebug::emitDIE(DIE *Die, ArrayRef Abbrevs) { // Get the abbreviation for this DIE. unsigned AbbrevNumber = Die->getAbbrevNumber(); const DIEAbbrev *Abbrev = Abbrevs[AbbrevNumber - 1]; // Emit the code (index) for the abbreviation. if (Asm->isVerbose()) Asm->OutStreamer.AddComment("Abbrev [" + Twine(AbbrevNumber) + "] 0x" + Twine::utohexstr(Die->getOffset()) + ":0x" + Twine::utohexstr(Die->getSize()) + " " + dwarf::TagString(Abbrev->getTag())); Asm->EmitULEB128(AbbrevNumber); const SmallVectorImpl &Values = Die->getValues(); const SmallVectorImpl &AbbrevData = Abbrev->getData(); // Emit the DIE attribute values. for (unsigned i = 0, N = Values.size(); i < N; ++i) { dwarf::Attribute Attr = AbbrevData[i].getAttribute(); dwarf::Form Form = AbbrevData[i].getForm(); assert(Form && "Too many attributes for DIE (check abbreviation)"); if (Asm->isVerbose()) Asm->OutStreamer.AddComment(dwarf::AttributeString(Attr)); switch (Attr) { case dwarf::DW_AT_abstract_origin: case dwarf::DW_AT_type: case dwarf::DW_AT_friend: case dwarf::DW_AT_specification: case dwarf::DW_AT_import: case dwarf::DW_AT_containing_type: { DIEEntry *E = cast(Values[i]); DIE *Origin = E->getEntry(); unsigned Addr = Origin->getOffset(); if (Form == dwarf::DW_FORM_ref_addr) { assert(!useSplitDwarf() && "TODO: dwo files can't have relocations."); // For DW_FORM_ref_addr, output the offset from beginning of debug info // section. Origin->getOffset() returns the offset from start of the // compile unit. CompileUnit *CU = CUDieMap.lookup(Origin->getCompileUnit()); assert(CU && "CUDie should belong to a CU."); Addr += CU->getDebugInfoOffset(); if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) Asm->EmitLabelPlusOffset(DwarfInfoSectionSym, Addr, DIEEntry::getRefAddrSize(Asm)); else Asm->EmitLabelOffsetDifference(DwarfInfoSectionSym, Addr, DwarfInfoSectionSym, DIEEntry::getRefAddrSize(Asm)); } else { // Make sure Origin belong to the same CU. assert(Die->getCompileUnit() == Origin->getCompileUnit() && "The referenced DIE should belong to the same CU in ref4"); Asm->EmitInt32(Addr); } break; } case dwarf::DW_AT_ranges: { // DW_AT_range Value encodes offset in debug_range section. DIEInteger *V = cast(Values[i]); if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) { Asm->EmitLabelPlusOffset(DwarfDebugRangeSectionSym, V->getValue(), 4); } else { Asm->EmitLabelOffsetDifference(DwarfDebugRangeSectionSym, V->getValue(), DwarfDebugRangeSectionSym, 4); } break; } case dwarf::DW_AT_location: { if (DIELabel *L = dyn_cast(Values[i])) { if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) Asm->EmitSectionOffset(L->getValue(), DwarfDebugLocSectionSym); else Asm->EmitLabelDifference(L->getValue(), DwarfDebugLocSectionSym, 4); } else { Values[i]->EmitValue(Asm, Form); } break; } case dwarf::DW_AT_accessibility: { if (Asm->isVerbose()) { DIEInteger *V = cast(Values[i]); Asm->OutStreamer.AddComment(dwarf::AccessibilityString(V->getValue())); } Values[i]->EmitValue(Asm, Form); break; } default: // Emit an attribute using the defined form. Values[i]->EmitValue(Asm, Form); break; } } // Emit the DIE children if any. if (Abbrev->getChildrenFlag() == dwarf::DW_CHILDREN_yes) { const std::vector &Children = Die->getChildren(); for (unsigned j = 0, M = Children.size(); j < M; ++j) emitDIE(Children[j], Abbrevs); if (Asm->isVerbose()) Asm->OutStreamer.AddComment("End Of Children Mark"); Asm->EmitInt8(0); } } // Emit the various dwarf units to the unit section USection with // the abbreviations going into ASection. void DwarfUnits::emitUnits(DwarfDebug *DD, const MCSection *USection, const MCSection *ASection, const MCSymbol *ASectionSym) { Asm->OutStreamer.SwitchSection(USection); for (SmallVectorImpl::iterator I = CUs.begin(), E = CUs.end(); I != E; ++I) { CompileUnit *TheCU = *I; DIE *Die = TheCU->getCUDie(); // Emit the compile units header. Asm->OutStreamer .EmitLabel(Asm->GetTempSymbol(USection->getLabelBeginName(), TheCU->getUniqueID())); // Emit size of content not including length itself Asm->OutStreamer.AddComment("Length of Unit"); Asm->EmitInt32(TheCU->getHeaderSize() + Die->getSize()); TheCU->emitHeader(ASection, ASectionSym); DD->emitDIE(Die, Abbreviations); Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol(USection->getLabelEndName(), TheCU->getUniqueID())); } } // Emit the debug info section. void DwarfDebug::emitDebugInfo() { DwarfUnits &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; Holder.emitUnits(this, Asm->getObjFileLowering().getDwarfInfoSection(), Asm->getObjFileLowering().getDwarfAbbrevSection(), DwarfAbbrevSectionSym); } // Emit the abbreviation section. void DwarfDebug::emitAbbreviations() { if (!useSplitDwarf()) emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevSection(), &Abbreviations); else emitSkeletonAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevSection()); } void DwarfDebug::emitAbbrevs(const MCSection *Section, std::vector *Abbrevs) { // Check to see if it is worth the effort. if (!Abbrevs->empty()) { // Start the debug abbrev section. Asm->OutStreamer.SwitchSection(Section); MCSymbol *Begin = Asm->GetTempSymbol(Section->getLabelBeginName()); Asm->OutStreamer.EmitLabel(Begin); // For each abbrevation. for (unsigned i = 0, N = Abbrevs->size(); i < N; ++i) { // Get abbreviation data const DIEAbbrev *Abbrev = Abbrevs->at(i); // Emit the abbrevations code (base 1 index.) Asm->EmitULEB128(Abbrev->getNumber(), "Abbreviation Code"); // Emit the abbreviations data. Abbrev->Emit(Asm); } // Mark end of abbreviations. Asm->EmitULEB128(0, "EOM(3)"); MCSymbol *End = Asm->GetTempSymbol(Section->getLabelEndName()); Asm->OutStreamer.EmitLabel(End); } } // Emit the last address of the section and the end of the line matrix. void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) { // Define last address of section. Asm->OutStreamer.AddComment("Extended Op"); Asm->EmitInt8(0); Asm->OutStreamer.AddComment("Op size"); Asm->EmitInt8(Asm->getDataLayout().getPointerSize() + 1); Asm->OutStreamer.AddComment("DW_LNE_set_address"); Asm->EmitInt8(dwarf::DW_LNE_set_address); Asm->OutStreamer.AddComment("Section end label"); Asm->OutStreamer.EmitSymbolValue(Asm->GetTempSymbol("section_end",SectionEnd), Asm->getDataLayout().getPointerSize()); // Mark end of matrix. Asm->OutStreamer.AddComment("DW_LNE_end_sequence"); Asm->EmitInt8(0); Asm->EmitInt8(1); Asm->EmitInt8(1); } // Emit visible names into a hashed accelerator table section. void DwarfDebug::emitAccelNames() { DwarfAccelTable AT(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)); for (DenseMap::iterator I = CUMap.begin(), E = CUMap.end(); I != E; ++I) { CompileUnit *TheCU = I->second; const StringMap > &Names = TheCU->getAccelNames(); for (StringMap >::const_iterator GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) { StringRef Name = GI->getKey(); const std::vector &Entities = GI->second; for (std::vector::const_iterator DI = Entities.begin(), DE = Entities.end(); DI != DE; ++DI) AT.AddName(Name, (*DI)); } } AT.FinalizeTable(Asm, "Names"); Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfAccelNamesSection()); MCSymbol *SectionBegin = Asm->GetTempSymbol("names_begin"); Asm->OutStreamer.EmitLabel(SectionBegin); // Emit the full data. AT.Emit(Asm, SectionBegin, &InfoHolder); } // Emit objective C classes and categories into a hashed accelerator table // section. void DwarfDebug::emitAccelObjC() { DwarfAccelTable AT(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)); for (DenseMap::iterator I = CUMap.begin(), E = CUMap.end(); I != E; ++I) { CompileUnit *TheCU = I->second; const StringMap > &Names = TheCU->getAccelObjC(); for (StringMap >::const_iterator GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) { StringRef Name = GI->getKey(); const std::vector &Entities = GI->second; for (std::vector::const_iterator DI = Entities.begin(), DE = Entities.end(); DI != DE; ++DI) AT.AddName(Name, (*DI)); } } AT.FinalizeTable(Asm, "ObjC"); Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering() .getDwarfAccelObjCSection()); MCSymbol *SectionBegin = Asm->GetTempSymbol("objc_begin"); Asm->OutStreamer.EmitLabel(SectionBegin); // Emit the full data. AT.Emit(Asm, SectionBegin, &InfoHolder); } // Emit namespace dies into a hashed accelerator table. void DwarfDebug::emitAccelNamespaces() { DwarfAccelTable AT(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)); for (DenseMap::iterator I = CUMap.begin(), E = CUMap.end(); I != E; ++I) { CompileUnit *TheCU = I->second; const StringMap > &Names = TheCU->getAccelNamespace(); for (StringMap >::const_iterator GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) { StringRef Name = GI->getKey(); const std::vector &Entities = GI->second; for (std::vector::const_iterator DI = Entities.begin(), DE = Entities.end(); DI != DE; ++DI) AT.AddName(Name, (*DI)); } } AT.FinalizeTable(Asm, "namespac"); Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering() .getDwarfAccelNamespaceSection()); MCSymbol *SectionBegin = Asm->GetTempSymbol("namespac_begin"); Asm->OutStreamer.EmitLabel(SectionBegin); // Emit the full data. AT.Emit(Asm, SectionBegin, &InfoHolder); } // Emit type dies into a hashed accelerator table. void DwarfDebug::emitAccelTypes() { std::vector Atoms; Atoms.push_back(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)); Atoms.push_back(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2)); Atoms.push_back(DwarfAccelTable::Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1)); DwarfAccelTable AT(Atoms); for (DenseMap::iterator I = CUMap.begin(), E = CUMap.end(); I != E; ++I) { CompileUnit *TheCU = I->second; const StringMap > > &Names = TheCU->getAccelTypes(); for (StringMap > >::const_iterator GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) { StringRef Name = GI->getKey(); const std::vector > &Entities = GI->second; for (std::vector >::const_iterator DI = Entities.begin(), DE = Entities.end(); DI !=DE; ++DI) AT.AddName(Name, (*DI).first, (*DI).second); } } AT.FinalizeTable(Asm, "types"); Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering() .getDwarfAccelTypesSection()); MCSymbol *SectionBegin = Asm->GetTempSymbol("types_begin"); Asm->OutStreamer.EmitLabel(SectionBegin); // Emit the full data. AT.Emit(Asm, SectionBegin, &InfoHolder); } // Public name handling. // The format for the various pubnames: // // dwarf pubnames - offset/name pairs where the offset is the offset into the CU // for the DIE that is named. // // gnu pubnames - offset/index value/name tuples where the offset is the offset // into the CU and the index value is computed according to the type of value // for the DIE that is named. // // For type units the offset is the offset of the skeleton DIE. For split dwarf // it's the offset within the debug_info/debug_types dwo section, however, the // reference in the pubname header doesn't change. /// computeIndexValue - Compute the gdb index value for the DIE and CU. static dwarf::PubIndexEntryDescriptor computeIndexValue(CompileUnit *CU, DIE *Die) { dwarf::GDBIndexEntryLinkage Linkage = dwarf::GIEL_STATIC; // We could have a specification DIE that has our most of our knowledge, // look for that now. DIEValue *SpecVal = Die->findAttribute(dwarf::DW_AT_specification); if (SpecVal) { DIE *SpecDIE = cast(SpecVal)->getEntry(); if (SpecDIE->findAttribute(dwarf::DW_AT_external)) Linkage = dwarf::GIEL_EXTERNAL; } else if (Die->findAttribute(dwarf::DW_AT_external)) Linkage = dwarf::GIEL_EXTERNAL; switch (Die->getTag()) { case dwarf::DW_TAG_class_type: case dwarf::DW_TAG_structure_type: case dwarf::DW_TAG_union_type: case dwarf::DW_TAG_enumeration_type: return dwarf::PubIndexEntryDescriptor( dwarf::GIEK_TYPE, CU->getLanguage() != dwarf::DW_LANG_C_plus_plus ? dwarf::GIEL_STATIC : dwarf::GIEL_EXTERNAL); case dwarf::DW_TAG_typedef: case dwarf::DW_TAG_base_type: case dwarf::DW_TAG_subrange_type: return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_TYPE, dwarf::GIEL_STATIC); case dwarf::DW_TAG_namespace: return dwarf::GIEK_TYPE; case dwarf::DW_TAG_subprogram: return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_FUNCTION, Linkage); case dwarf::DW_TAG_constant: case dwarf::DW_TAG_variable: return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_VARIABLE, Linkage); case dwarf::DW_TAG_enumerator: return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_VARIABLE, dwarf::GIEL_STATIC); default: return dwarf::GIEK_NONE; } } /// emitDebugPubNames - Emit visible names into a debug pubnames section. /// void DwarfDebug::emitDebugPubNames(bool GnuStyle) { const MCSection *ISec = Asm->getObjFileLowering().getDwarfInfoSection(); const MCSection *PSec = GnuStyle ? Asm->getObjFileLowering().getDwarfGnuPubNamesSection() : Asm->getObjFileLowering().getDwarfPubNamesSection(); typedef DenseMap CUMapType; for (CUMapType::iterator I = CUMap.begin(), E = CUMap.end(); I != E; ++I) { CompileUnit *TheCU = I->second; unsigned ID = TheCU->getUniqueID(); // Start the dwarf pubnames section. Asm->OutStreamer.SwitchSection(PSec); // Emit a label so we can reference the beginning of this pubname section. if (GnuStyle) Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("gnu_pubnames", TheCU->getUniqueID())); // Emit the header. Asm->OutStreamer.AddComment("Length of Public Names Info"); Asm->EmitLabelDifference(Asm->GetTempSymbol("pubnames_end", ID), Asm->GetTempSymbol("pubnames_begin", ID), 4); Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubnames_begin", ID)); Asm->OutStreamer.AddComment("DWARF Version"); Asm->EmitInt16(dwarf::DW_PUBNAMES_VERSION); Asm->OutStreamer.AddComment("Offset of Compilation Unit Info"); Asm->EmitSectionOffset(Asm->GetTempSymbol(ISec->getLabelBeginName(), ID), DwarfInfoSectionSym); Asm->OutStreamer.AddComment("Compilation Unit Length"); Asm->EmitLabelDifference(Asm->GetTempSymbol(ISec->getLabelEndName(), ID), Asm->GetTempSymbol(ISec->getLabelBeginName(), ID), 4); // Emit the pubnames for this compilation unit. const StringMap &Globals = TheCU->getGlobalNames(); for (StringMap::const_iterator GI = Globals.begin(), GE = Globals.end(); GI != GE; ++GI) { const char *Name = GI->getKeyData(); DIE *Entity = GI->second; Asm->OutStreamer.AddComment("DIE offset"); Asm->EmitInt32(Entity->getOffset()); if (GnuStyle) { dwarf::PubIndexEntryDescriptor Desc = computeIndexValue(TheCU, Entity); Asm->OutStreamer.AddComment( Twine("Kind: ") + dwarf::GDBIndexEntryKindString(Desc.Kind) + ", " + dwarf::GDBIndexEntryLinkageString(Desc.Linkage)); Asm->EmitInt8(Desc.toBits()); } if (Asm->isVerbose()) Asm->OutStreamer.AddComment("External Name"); Asm->OutStreamer.EmitBytes(StringRef(Name, GI->getKeyLength()+1)); } Asm->OutStreamer.AddComment("End Mark"); Asm->EmitInt32(0); Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubnames_end", ID)); } } void DwarfDebug::emitDebugPubTypes(bool GnuStyle) { const MCSection *ISec = Asm->getObjFileLowering().getDwarfInfoSection(); const MCSection *PSec = GnuStyle ? Asm->getObjFileLowering().getDwarfGnuPubTypesSection() : Asm->getObjFileLowering().getDwarfPubTypesSection(); for (DenseMap::iterator I = CUMap.begin(), E = CUMap.end(); I != E; ++I) { CompileUnit *TheCU = I->second; // Start the dwarf pubtypes section. Asm->OutStreamer.SwitchSection(PSec); // Emit a label so we can reference the beginning of this pubtype section. if (GnuStyle) Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("gnu_pubtypes", TheCU->getUniqueID())); // Emit the header. Asm->OutStreamer.AddComment("Length of Public Types Info"); Asm->EmitLabelDifference( Asm->GetTempSymbol("pubtypes_end", TheCU->getUniqueID()), Asm->GetTempSymbol("pubtypes_begin", TheCU->getUniqueID()), 4); Asm->OutStreamer.EmitLabel( Asm->GetTempSymbol("pubtypes_begin", TheCU->getUniqueID())); if (Asm->isVerbose()) Asm->OutStreamer.AddComment("DWARF Version"); Asm->EmitInt16(dwarf::DW_PUBTYPES_VERSION); Asm->OutStreamer.AddComment("Offset of Compilation Unit Info"); Asm->EmitSectionOffset( Asm->GetTempSymbol(ISec->getLabelBeginName(), TheCU->getUniqueID()), DwarfInfoSectionSym); Asm->OutStreamer.AddComment("Compilation Unit Length"); Asm->EmitLabelDifference( Asm->GetTempSymbol(ISec->getLabelEndName(), TheCU->getUniqueID()), Asm->GetTempSymbol(ISec->getLabelBeginName(), TheCU->getUniqueID()), 4); // Emit the pubtypes. const StringMap &Globals = TheCU->getGlobalTypes(); for (StringMap::const_iterator GI = Globals.begin(), GE = Globals.end(); GI != GE; ++GI) { const char *Name = GI->getKeyData(); DIE *Entity = GI->second; if (Asm->isVerbose()) Asm->OutStreamer.AddComment("DIE offset"); Asm->EmitInt32(Entity->getOffset()); if (GnuStyle) { dwarf::PubIndexEntryDescriptor Desc = computeIndexValue(TheCU, Entity); Asm->OutStreamer.AddComment( Twine("Kind: ") + dwarf::GDBIndexEntryKindString(Desc.Kind) + ", " + dwarf::GDBIndexEntryLinkageString(Desc.Linkage)); Asm->EmitInt8(Desc.toBits()); } if (Asm->isVerbose()) Asm->OutStreamer.AddComment("External Name"); // Emit the name with a terminating null byte. Asm->OutStreamer.EmitBytes(StringRef(Name, GI->getKeyLength() + 1)); } Asm->OutStreamer.AddComment("End Mark"); Asm->EmitInt32(0); Asm->OutStreamer.EmitLabel( Asm->GetTempSymbol("pubtypes_end", TheCU->getUniqueID())); } } // Emit strings into a string section. void DwarfUnits::emitStrings(const MCSection *StrSection, const MCSection *OffsetSection = NULL, const MCSymbol *StrSecSym = NULL) { if (StringPool.empty()) return; // Start the dwarf str section. Asm->OutStreamer.SwitchSection(StrSection); // Get all of the string pool entries and put them in an array by their ID so // we can sort them. SmallVector >*>, 64> Entries; for (StringMap >::iterator I = StringPool.begin(), E = StringPool.end(); I != E; ++I) Entries.push_back(std::make_pair(I->second.second, &*I)); array_pod_sort(Entries.begin(), Entries.end()); for (unsigned i = 0, e = Entries.size(); i != e; ++i) { // Emit a label for reference from debug information entries. Asm->OutStreamer.EmitLabel(Entries[i].second->getValue().first); // Emit the string itself with a terminating null byte. Asm->OutStreamer.EmitBytes(StringRef(Entries[i].second->getKeyData(), Entries[i].second->getKeyLength()+1)); } // If we've got an offset section go ahead and emit that now as well. if (OffsetSection) { Asm->OutStreamer.SwitchSection(OffsetSection); unsigned offset = 0; unsigned size = 4; // FIXME: DWARF64 is 8. for (unsigned i = 0, e = Entries.size(); i != e; ++i) { Asm->OutStreamer.EmitIntValue(offset, size); offset += Entries[i].second->getKeyLength() + 1; } } } // Emit strings into a string section. void DwarfUnits::emitAddresses(const MCSection *AddrSection) { if (AddressPool.empty()) return; // Start the dwarf addr section. Asm->OutStreamer.SwitchSection(AddrSection); // Order the address pool entries by ID SmallVector Entries(AddressPool.size()); for (DenseMap::iterator I = AddressPool.begin(), E = AddressPool.end(); I != E; ++I) Entries[I->second] = I->first; for (unsigned i = 0, e = Entries.size(); i != e; ++i) { // Emit an expression for reference from debug information entries. if (const MCExpr *Expr = Entries[i]) Asm->OutStreamer.EmitValue(Expr, Asm->getDataLayout().getPointerSize()); else Asm->OutStreamer.EmitIntValue(0, Asm->getDataLayout().getPointerSize()); } } // Emit visible names into a debug str section. void DwarfDebug::emitDebugStr() { DwarfUnits &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; Holder.emitStrings(Asm->getObjFileLowering().getDwarfStrSection()); } // Emit locations into the debug loc section. void DwarfDebug::emitDebugLoc() { if (DotDebugLocEntries.empty()) return; for (SmallVectorImpl::iterator I = DotDebugLocEntries.begin(), E = DotDebugLocEntries.end(); I != E; ++I) { DotDebugLocEntry &Entry = *I; if (I + 1 != DotDebugLocEntries.end()) Entry.Merge(I+1); } // Start the dwarf loc section. Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfLocSection()); unsigned char Size = Asm->getDataLayout().getPointerSize(); Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", 0)); unsigned index = 1; for (SmallVectorImpl::iterator I = DotDebugLocEntries.begin(), E = DotDebugLocEntries.end(); I != E; ++I, ++index) { DotDebugLocEntry &Entry = *I; if (Entry.isMerged()) continue; if (Entry.isEmpty()) { Asm->OutStreamer.EmitIntValue(0, Size); Asm->OutStreamer.EmitIntValue(0, Size); Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", index)); } else { Asm->OutStreamer.EmitSymbolValue(Entry.getBeginSym(), Size); Asm->OutStreamer.EmitSymbolValue(Entry.getEndSym(), Size); DIVariable DV(Entry.getVariable()); Asm->OutStreamer.AddComment("Loc expr size"); MCSymbol *begin = Asm->OutStreamer.getContext().CreateTempSymbol(); MCSymbol *end = Asm->OutStreamer.getContext().CreateTempSymbol(); Asm->EmitLabelDifference(end, begin, 2); Asm->OutStreamer.EmitLabel(begin); if (Entry.isInt()) { DIBasicType BTy(DV.getType()); if (BTy.Verify() && (BTy.getEncoding() == dwarf::DW_ATE_signed || BTy.getEncoding() == dwarf::DW_ATE_signed_char)) { Asm->OutStreamer.AddComment("DW_OP_consts"); Asm->EmitInt8(dwarf::DW_OP_consts); Asm->EmitSLEB128(Entry.getInt()); } else { Asm->OutStreamer.AddComment("DW_OP_constu"); Asm->EmitInt8(dwarf::DW_OP_constu); Asm->EmitULEB128(Entry.getInt()); } } else if (Entry.isLocation()) { MachineLocation Loc = Entry.getLoc(); if (!DV.hasComplexAddress()) // Regular entry. Asm->EmitDwarfRegOp(Loc, DV.isIndirect()); else { // Complex address entry. unsigned N = DV.getNumAddrElements(); unsigned i = 0; if (N >= 2 && DV.getAddrElement(0) == DIBuilder::OpPlus) { if (Loc.getOffset()) { i = 2; Asm->EmitDwarfRegOp(Loc, DV.isIndirect()); Asm->OutStreamer.AddComment("DW_OP_deref"); Asm->EmitInt8(dwarf::DW_OP_deref); Asm->OutStreamer.AddComment("DW_OP_plus_uconst"); Asm->EmitInt8(dwarf::DW_OP_plus_uconst); Asm->EmitSLEB128(DV.getAddrElement(1)); } else { // If first address element is OpPlus then emit // DW_OP_breg + Offset instead of DW_OP_reg + Offset. MachineLocation TLoc(Loc.getReg(), DV.getAddrElement(1)); Asm->EmitDwarfRegOp(TLoc, DV.isIndirect()); i = 2; } } else { Asm->EmitDwarfRegOp(Loc, DV.isIndirect()); } // Emit remaining complex address elements. for (; i < N; ++i) { uint64_t Element = DV.getAddrElement(i); if (Element == DIBuilder::OpPlus) { Asm->EmitInt8(dwarf::DW_OP_plus_uconst); Asm->EmitULEB128(DV.getAddrElement(++i)); } else if (Element == DIBuilder::OpDeref) { if (!Loc.isReg()) Asm->EmitInt8(dwarf::DW_OP_deref); } else llvm_unreachable("unknown Opcode found in complex address"); } } } // else ... ignore constant fp. There is not any good way to // to represent them here in dwarf. Asm->OutStreamer.EmitLabel(end); } } } struct SymbolCUSorter { SymbolCUSorter(const MCStreamer &s) : Streamer(s) {} const MCStreamer &Streamer; bool operator() (const SymbolCU &A, const SymbolCU &B) { unsigned IA = A.Sym ? Streamer.GetSymbolOrder(A.Sym) : 0; unsigned IB = B.Sym ? Streamer.GetSymbolOrder(B.Sym) : 0; // Symbols with no order assigned should be placed at the end. // (e.g. section end labels) if (IA == 0) IA = (unsigned)(-1); if (IB == 0) IB = (unsigned)(-1); return IA < IB; } }; static bool CUSort(const CompileUnit *A, const CompileUnit *B) { return (A->getUniqueID() < B->getUniqueID()); } struct ArangeSpan { const MCSymbol *Start, *End; }; // Emit a debug aranges section, containing a CU lookup for any // address we can tie back to a CU. void DwarfDebug::emitDebugARanges() { // Start the dwarf aranges section. Asm->OutStreamer .SwitchSection(Asm->getObjFileLowering().getDwarfARangesSection()); typedef DenseMap > SpansType; SpansType Spans; // Build a list of sections used. std::vector Sections; for (SectionMapType::iterator it = SectionMap.begin(); it != SectionMap.end(); it++) { const MCSection *Section = it->first; Sections.push_back(Section); } // Sort the sections into order. // This is only done to ensure consistent output order across different runs. std::sort(Sections.begin(), Sections.end(), SectionSort); // Build a set of address spans, sorted by CU. for (size_t SecIdx=0;SecIdx &List = SectionMap[Section]; if (List.size() < 2) continue; // Sort the symbols by offset within the section. SymbolCUSorter sorter(Asm->OutStreamer); std::sort(List.begin(), List.end(), sorter); // If we have no section (e.g. common), just write out // individual spans for each symbol. if (Section == NULL) { for (size_t n = 0; n < List.size(); n++) { const SymbolCU &Cur = List[n]; ArangeSpan Span; Span.Start = Cur.Sym; Span.End = NULL; if (Cur.CU) Spans[Cur.CU].push_back(Span); } } else { // Build spans between each label. const MCSymbol *StartSym = List[0].Sym; for (size_t n = 1; n < List.size(); n++) { const SymbolCU &Prev = List[n - 1]; const SymbolCU &Cur = List[n]; // Try and build the longest span we can within the same CU. if (Cur.CU != Prev.CU) { ArangeSpan Span; Span.Start = StartSym; Span.End = Cur.Sym; Spans[Prev.CU].push_back(Span); StartSym = Cur.Sym; } } } } const MCSection *ISec = Asm->getObjFileLowering().getDwarfInfoSection(); unsigned PtrSize = Asm->getDataLayout().getPointerSize(); // Build a list of CUs used. std::vector CUs; for (SpansType::iterator it = Spans.begin(); it != Spans.end(); it++) { CompileUnit *CU = it->first; CUs.push_back(CU); } // Sort the CU list (again, to ensure consistent output order). std::sort(CUs.begin(), CUs.end(), CUSort); // Emit an arange table for each CU we used. for (size_t CUIdx=0;CUIdx &List = Spans[CU]; // Emit size of content not including length itself. unsigned ContentSize = sizeof(int16_t) // DWARF ARange version number + sizeof(int32_t) // Offset of CU in the .debug_info section + sizeof(int8_t) // Pointer Size (in bytes) + sizeof(int8_t); // Segment Size (in bytes) unsigned TupleSize = PtrSize * 2; // 7.20 in the Dwarf specs requires the table to be aligned to a tuple. unsigned Padding = 0; while (((sizeof(int32_t) + ContentSize + Padding) % TupleSize) != 0) Padding++; ContentSize += Padding; ContentSize += (List.size() + 1) * TupleSize; // For each compile unit, write the list of spans it covers. Asm->OutStreamer.AddComment("Length of ARange Set"); Asm->EmitInt32(ContentSize); Asm->OutStreamer.AddComment("DWARF Arange version number"); Asm->EmitInt16(dwarf::DW_ARANGES_VERSION); Asm->OutStreamer.AddComment("Offset Into Debug Info Section"); Asm->EmitSectionOffset( Asm->GetTempSymbol(ISec->getLabelBeginName(), CU->getUniqueID()), DwarfInfoSectionSym); Asm->OutStreamer.AddComment("Address Size (in bytes)"); Asm->EmitInt8(PtrSize); Asm->OutStreamer.AddComment("Segment Size (in bytes)"); Asm->EmitInt8(0); for (unsigned n = 0; n < Padding; n++) Asm->EmitInt8(0xff); for (unsigned n = 0; n < List.size(); n++) { const ArangeSpan &Span = List[n]; Asm->EmitLabelReference(Span.Start, PtrSize); // Calculate the size as being from the span start to it's end. if (Span.End) { Asm->EmitLabelDifference(Span.End, Span.Start, PtrSize); } else { // For symbols without an end marker (e.g. common), we // write a single arange entry containing just that one symbol. uint64_t Size = SymSize[Span.Start]; if (Size == 0) Size = 1; Asm->OutStreamer.EmitIntValue(Size, PtrSize); } } Asm->OutStreamer.AddComment("ARange terminator"); Asm->OutStreamer.EmitIntValue(0, PtrSize); Asm->OutStreamer.EmitIntValue(0, PtrSize); } } // Emit visible names into a debug ranges section. void DwarfDebug::emitDebugRanges() { // Start the dwarf ranges section. Asm->OutStreamer .SwitchSection(Asm->getObjFileLowering().getDwarfRangesSection()); unsigned char Size = Asm->getDataLayout().getPointerSize(); for (SmallVectorImpl::iterator I = DebugRangeSymbols.begin(), E = DebugRangeSymbols.end(); I != E; ++I) { if (*I) Asm->OutStreamer.EmitSymbolValue(const_cast(*I), Size); else Asm->OutStreamer.EmitIntValue(0, Size); } } // Emit visible names into a debug macinfo section. void DwarfDebug::emitDebugMacInfo() { if (const MCSection *LineInfo = Asm->getObjFileLowering().getDwarfMacroInfoSection()) { // Start the dwarf macinfo section. Asm->OutStreamer.SwitchSection(LineInfo); } } // DWARF5 Experimental Separate Dwarf emitters. // This DIE has the following attributes: DW_AT_comp_dir, DW_AT_stmt_list, // DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_dwo_name, DW_AT_dwo_id, // DW_AT_ranges_base, DW_AT_addr_base. CompileUnit *DwarfDebug::constructSkeletonCU(const CompileUnit *CU) { DIE *Die = new DIE(dwarf::DW_TAG_compile_unit); CompileUnit *NewCU = new CompileUnit(CU->getUniqueID(), Die, CU->getNode(), Asm, this, &SkeletonHolder); NewCU->addLocalString(Die, dwarf::DW_AT_GNU_dwo_name, CU->getNode().getSplitDebugFilename()); // Relocate to the beginning of the addr_base section, else 0 for the // beginning of the one for this compile unit. if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) NewCU->addSectionLabel(Die, dwarf::DW_AT_GNU_addr_base, DwarfAddrSectionSym); else NewCU->addSectionOffset(Die, dwarf::DW_AT_GNU_addr_base, 0); // 2.17.1 requires that we use DW_AT_low_pc for a single entry point // into an entity. We're using 0, or a NULL label for this. NewCU->addUInt(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, 0); // DW_AT_stmt_list is a offset of line number information for this // compile unit in debug_line section. // FIXME: Should handle multiple compile units. if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) NewCU->addSectionLabel(Die, dwarf::DW_AT_stmt_list, DwarfLineSectionSym); else NewCU->addSectionOffset(Die, dwarf::DW_AT_stmt_list, 0); if (!CompilationDir.empty()) NewCU->addLocalString(Die, dwarf::DW_AT_comp_dir, CompilationDir); // Flags to let the linker know we have emitted new style pubnames. if (GenerateGnuPubSections) { if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) NewCU->addSectionLabel( Die, dwarf::DW_AT_GNU_pubnames, Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID())); else NewCU->addSectionDelta( Die, dwarf::DW_AT_GNU_pubnames, Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID()), DwarfGnuPubNamesSectionSym); if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) NewCU->addSectionLabel( Die, dwarf::DW_AT_GNU_pubtypes, Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID())); else NewCU->addSectionDelta( Die, dwarf::DW_AT_GNU_pubtypes, Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID()), DwarfGnuPubTypesSectionSym); } // Flag if we've emitted any ranges and their location for the compile unit. if (DebugRangeSymbols.size()) { if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) NewCU->addSectionLabel(Die, dwarf::DW_AT_GNU_ranges_base, DwarfDebugRangeSectionSym); else NewCU->addUInt(Die, dwarf::DW_AT_GNU_ranges_base, dwarf::DW_FORM_data4, 0); } SkeletonHolder.addUnit(NewCU); SkeletonCUs.push_back(NewCU); return NewCU; } void DwarfDebug::emitSkeletonAbbrevs(const MCSection *Section) { assert(useSplitDwarf() && "No split dwarf debug info?"); emitAbbrevs(Section, &SkeletonAbbrevs); } // Emit the .debug_info.dwo section for separated dwarf. This contains the // compile units that would normally be in debug_info. void DwarfDebug::emitDebugInfoDWO() { assert(useSplitDwarf() && "No split dwarf debug info?"); InfoHolder.emitUnits(this, Asm->getObjFileLowering().getDwarfInfoDWOSection(), Asm->getObjFileLowering().getDwarfAbbrevDWOSection(), DwarfAbbrevDWOSectionSym); } // Emit the .debug_abbrev.dwo section for separated dwarf. This contains the // abbreviations for the .debug_info.dwo section. void DwarfDebug::emitDebugAbbrevDWO() { assert(useSplitDwarf() && "No split dwarf?"); emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevDWOSection(), &Abbreviations); } // Emit the .debug_str.dwo section for separated dwarf. This contains the // string section and is identical in format to traditional .debug_str // sections. void DwarfDebug::emitDebugStrDWO() { assert(useSplitDwarf() && "No split dwarf?"); const MCSection *OffSec = Asm->getObjFileLowering() .getDwarfStrOffDWOSection(); const MCSymbol *StrSym = DwarfStrSectionSym; InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(), OffSec, StrSym); } Index: stable/9/contrib/llvm/lib/Target/ARM/ARMFrameLowering.h =================================================================== --- stable/9/contrib/llvm/lib/Target/ARM/ARMFrameLowering.h (revision 283018) +++ stable/9/contrib/llvm/lib/Target/ARM/ARMFrameLowering.h (revision 283019) @@ -1,82 +1,82 @@ //==-- ARMTargetFrameLowering.h - Define frame lowering for ARM --*- C++ -*-==// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // // //===----------------------------------------------------------------------===// #ifndef ARM_FRAMEINFO_H #define ARM_FRAMEINFO_H #include "ARM.h" #include "ARMSubtarget.h" #include "llvm/Target/TargetFrameLowering.h" namespace llvm { class ARMSubtarget; class ARMFrameLowering : public TargetFrameLowering { protected: const ARMSubtarget &STI; public: explicit ARMFrameLowering(const ARMSubtarget &sti) - : TargetFrameLowering(StackGrowsDown, sti.getStackAlignment(), 0, 4), + : TargetFrameLowering(StackGrowsDown, sti.getStackAlignment(), 0, 8), STI(sti) { } /// emitProlog/emitEpilog - These methods insert prolog and epilog code into /// the function. void emitPrologue(MachineFunction &MF) const; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const std::vector &CSI, const TargetRegisterInfo *TRI) const; bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const std::vector &CSI, const TargetRegisterInfo *TRI) const; bool hasFP(const MachineFunction &MF) const; bool hasReservedCallFrame(const MachineFunction &MF) const; bool canSimplifyCallFramePseudos(const MachineFunction &MF) const; int getFrameIndexReference(const MachineFunction &MF, int FI, unsigned &FrameReg) const; int ResolveFrameIndexReference(const MachineFunction &MF, int FI, unsigned &FrameReg, int SPAdj) const; int getFrameIndexOffset(const MachineFunction &MF, int FI) const; void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, RegScavenger *RS) const; private: void emitPushInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const std::vector &CSI, unsigned StmOpc, unsigned StrOpc, bool NoGap, bool(*Func)(unsigned, bool), unsigned NumAlignedDPRCS2Regs, unsigned MIFlags = 0) const; void emitPopInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const std::vector &CSI, unsigned LdmOpc, unsigned LdrOpc, bool isVarArg, bool NoGap, bool(*Func)(unsigned, bool), unsigned NumAlignedDPRCS2Regs) const; virtual void eliminateCallFramePseudoInstr( MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const; }; } // End llvm namespace #endif Index: stable/9/contrib/llvm/tools/clang/include/clang/Driver/Options.td =================================================================== --- stable/9/contrib/llvm/tools/clang/include/clang/Driver/Options.td (revision 283018) +++ stable/9/contrib/llvm/tools/clang/include/clang/Driver/Options.td (revision 283019) @@ -1,1578 +1,1580 @@ //===--- Options.td - Options for clang -----------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines the options accepted by clang. // //===----------------------------------------------------------------------===// // Include the common option parsing interfaces. include "llvm/Option/OptParser.td" ///////// // Flags // DriverOption - The option is a "driver" option, and should not be forwarded // to other tools. def DriverOption : OptionFlag; // LinkerInput - The option is a linker input. def LinkerInput : OptionFlag; // NoArgumentUnused - Don't report argument unused warnings for this option; this // is useful for options like -static or -dynamic which a user may always end up // passing, even if the platform defaults to (or only supports) that option. def NoArgumentUnused : OptionFlag; // Unsupported - The option is unsupported, and the driver will reject command // lines that use it. def Unsupported : OptionFlag; // CoreOption - This is considered a "core" Clang option, available in both // clang and clang-cl modes. def CoreOption : OptionFlag; // CLOption - This is a cl.exe compatibility option. Options with this flag // are made available when the driver is running in CL compatibility mode. def CLOption : OptionFlag; // CC1Option - This option should be accepted by clang -cc1. def CC1Option : OptionFlag; // NoDriverOption - This option should not be accepted by the driver. def NoDriverOption : OptionFlag; ///////// // Groups // Meta-group for options which are only used for compilation, // and not linking etc. def CompileOnly_Group : OptionGroup<"">; def Action_Group : OptionGroup<"">; def I_Group : OptionGroup<"">, Group; def M_Group : OptionGroup<"">, Group; def T_Group : OptionGroup<"">; def O_Group : OptionGroup<"">, Group; def W_Group : OptionGroup<"">, Group; def d_Group : OptionGroup<"">; def f_Group : OptionGroup<"">, Group; def f_clang_Group : OptionGroup<"">, Group; def g_Group : OptionGroup<"">; def g_flags_Group : OptionGroup<"">; def i_Group : OptionGroup<"">, Group; def clang_i_Group : OptionGroup<"">, Group; def m_Group : OptionGroup<"">, Group; def m_x86_Features_Group : OptionGroup<"">, Group; def m_hexagon_Features_Group : OptionGroup<"">, Group; def m_arm_Features_Group : OptionGroup<"">, Group; def m_ppc_Features_Group : OptionGroup<"">, Group; def opencl_Group : OptionGroup<"">; def u_Group : OptionGroup<"">; def pedantic_Group : OptionGroup<"">, Group; def reserved_lib_Group : OptionGroup<"">; // Temporary groups for clang options which we know we don't support, // but don't want to verbosely warn the user about. def clang_ignored_f_Group : OptionGroup<"">, Group; def clang_ignored_m_Group : OptionGroup<"">, Group; ///////// // Options // The internal option ID must be a valid C++ identifier and results in a // clang::driver::options::OPT_XX enum constant for XX. // // We want to unambiguously be able to refer to options from the driver source // code, for this reason the option name is mangled into an ID. This mangling // isn't guaranteed to have an inverse, but for practical purposes it does. // // The mangling scheme is to ignore the leading '-', and perform the following // substitutions: // _ => __ // - => _ // / => _SLASH // # => _HASH // ? => _QUESTION // , => _COMMA // = => _EQ // C++ => CXX // . => _ // Developer Driver Options def internal_Group : OptionGroup<"">; def internal_driver_Group : OptionGroup<"">, Group, HelpText<"DRIVER OPTIONS">; def internal_debug_Group : OptionGroup<"">, Group, HelpText<"DEBUG/DEVELOPMENT OPTIONS">; class InternalDriverOpt : Group, Flags<[DriverOption, HelpHidden]>; def driver_mode : Joined<["--"], "driver-mode=">, Group, Flags<[CoreOption, DriverOption, HelpHidden]>, HelpText<"Set the driver mode to either 'gcc', 'g++', 'cpp', or 'cl'">; def ccc_gcc_name : Separate<["-"], "ccc-gcc-name">, InternalDriverOpt, HelpText<"Name for native GCC compiler">, MetaVarName<"">; def ccc_pch_is_pch : Flag<["-"], "ccc-pch-is-pch">, InternalDriverOpt, HelpText<"Use lazy PCH for precompiled headers">; def ccc_pch_is_pth : Flag<["-"], "ccc-pch-is-pth">, InternalDriverOpt, HelpText<"Use pretokenized headers for precompiled headers">; class InternalDebugOpt : Group, Flags<[DriverOption, HelpHidden]>; def ccc_install_dir : Separate<["-"], "ccc-install-dir">, InternalDebugOpt, HelpText<"Simulate installation in the given directory">; def ccc_print_phases : Flag<["-"], "ccc-print-phases">, InternalDebugOpt, HelpText<"Dump list of actions to perform">; def ccc_print_bindings : Flag<["-"], "ccc-print-bindings">, InternalDebugOpt, HelpText<"Show bindings of tools to actions">; def ccc_arcmt_check : Flag<["-"], "ccc-arcmt-check">, InternalDriverOpt, HelpText<"Check for ARC migration issues that need manual handling">; def ccc_arcmt_modify : Flag<["-"], "ccc-arcmt-modify">, InternalDriverOpt, HelpText<"Apply modifications to files to conform to ARC">; def ccc_arcmt_migrate : Separate<["-"], "ccc-arcmt-migrate">, InternalDriverOpt, HelpText<"Apply modifications and produces temporary files that conform to ARC">; def arcmt_migrate_report_output : Separate<["-"], "arcmt-migrate-report-output">, HelpText<"Output path for the plist report">, Flags<[CC1Option]>; def arcmt_migrate_emit_arc_errors : Flag<["-"], "arcmt-migrate-emit-errors">, HelpText<"Emit ARC errors even if the migrator can fix them">, Flags<[CC1Option]>; def _migrate : Flag<["--"], "migrate">, Flags<[DriverOption]>, HelpText<"Run the migrator">; def ccc_objcmt_migrate : Separate<["-"], "ccc-objcmt-migrate">, InternalDriverOpt, HelpText<"Apply modifications and produces temporary files to migrate to " "modern ObjC syntax">; def objcmt_migrate_literals : Flag<["-"], "objcmt-migrate-literals">, Flags<[CC1Option]>, HelpText<"Enable migration to modern ObjC literals">; def objcmt_migrate_subscripting : Flag<["-"], "objcmt-migrate-subscripting">, Flags<[CC1Option]>, HelpText<"Enable migration to modern ObjC subscripting">; def objcmt_migrate_property : Flag<["-"], "objcmt-migrate-property">, Flags<[CC1Option]>, HelpText<"Enable migration to modern ObjC property">; def objcmt_migrate_all : Flag<["-"], "objcmt-migrate-all">, Flags<[CC1Option]>, HelpText<"Enable migration to modern ObjC">; def objcmt_migrate_readonly_property : Flag<["-"], "objcmt-migrate-readonly-property">, Flags<[CC1Option]>, HelpText<"Enable migration to modern ObjC readonly property">; def objcmt_migrate_readwrite_property : Flag<["-"], "objcmt-migrate-readwrite-property">, Flags<[CC1Option]>, HelpText<"Enable migration to modern ObjC readwrite property">; def objcmt_migrate_annotation : Flag<["-"], "objcmt-migrate-annotation">, Flags<[CC1Option]>, HelpText<"Enable migration to property and method annotations">; def objcmt_migrate_instancetype : Flag<["-"], "objcmt-migrate-instancetype">, Flags<[CC1Option]>, HelpText<"Enable migration to infer instancetype for method result type">; def objcmt_migrate_nsmacros : Flag<["-"], "objcmt-migrate-ns-macros">, Flags<[CC1Option]>, HelpText<"Enable migration to NS_ENUM/NS_OPTIONS macros">; def objcmt_migrate_protocol_conformance : Flag<["-"], "objcmt-migrate-protocol-conformance">, Flags<[CC1Option]>, HelpText<"Enable migration to add protocol conformance on classes">; def objcmt_atomic_property : Flag<["-"], "objcmt-atomic-property">, Flags<[CC1Option]>, HelpText<"Make migration to 'atomic' properties">; def objcmt_returns_innerpointer_property : Flag<["-"], "objcmt-returns-innerpointer-property">, Flags<[CC1Option]>, HelpText<"Enable migration to annotate property with NS_RETURNS_INNER_POINTER">; def objcmt_ns_nonatomic_iosonly: Flag<["-"], "objcmt-ns-nonatomic-iosonly">, Flags<[CC1Option]>, HelpText<"Enable migration to use NS_NONATOMIC_IOSONLY macro for setting property's 'atomic' attribute">; def objcmt_white_list_dir_path: Joined<["-"], "objcmt-white-list-dir-path=">, Flags<[CC1Option]>, HelpText<"Only modify files with a filename contained in the provided directory path">; // Make sure all other -ccc- options are rejected. def ccc_ : Joined<["-"], "ccc-">, Group, Flags<[Unsupported]>; // Standard Options def _HASH_HASH_HASH : Flag<["-"], "###">, Flags<[DriverOption, CoreOption]>, HelpText<"Print the commands to run for this compilation">; def _DASH_DASH : Option<["--"], "", KIND_REMAINING_ARGS>, Flags<[DriverOption, CoreOption]>; def A : JoinedOrSeparate<["-"], "A">, Flags<[RenderJoined]>; def B : JoinedOrSeparate<["-"], "B">; def CC : Flag<["-"], "CC">, Flags<[CC1Option]>; def C : Flag<["-"], "C">, Flags<[CC1Option]>; def D : JoinedOrSeparate<["-"], "D">, Group, Flags<[CC1Option]>; def E : Flag<["-"], "E">, Flags<[DriverOption,CC1Option]>, Group, HelpText<"Only run the preprocessor">; def F : JoinedOrSeparate<["-"], "F">, Flags<[RenderJoined,CC1Option]>, HelpText<"Add directory to framework include search path">; def G : JoinedOrSeparate<["-"], "G">, Flags<[DriverOption]>; def G_EQ : Joined<["-"], "G=">, Flags<[DriverOption]>; def H : Flag<["-"], "H">, Flags<[CC1Option]>, HelpText<"Show header includes and nesting depth">; def I_ : Flag<["-"], "I-">, Group; def I : JoinedOrSeparate<["-"], "I">, Group, Flags<[CC1Option]>, HelpText<"Add directory to include search path">; def L : JoinedOrSeparate<["-"], "L">, Flags<[RenderJoined]>; def MD : Flag<["-"], "MD">, Group; def MF : JoinedOrSeparate<["-"], "MF">, Group; def MG : Flag<["-"], "MG">, Group, Flags<[CC1Option]>, HelpText<"Add missing headers to dependency list">; def MMD : Flag<["-"], "MMD">, Group; def MM : Flag<["-"], "MM">, Group; def MP : Flag<["-"], "MP">, Group, Flags<[CC1Option]>, HelpText<"Create phony target for each dependency (other than main file)">; def MQ : JoinedOrSeparate<["-"], "MQ">, Group, Flags<[CC1Option]>, HelpText<"Specify target to quote for dependency">; def MT : JoinedOrSeparate<["-"], "MT">, Group, Flags<[CC1Option]>, HelpText<"Specify target for dependency">; def Mach : Flag<["-"], "Mach">; def M : Flag<["-"], "M">, Group; def O0 : Flag<["-"], "O0">, Group, Flags<[CC1Option]>; def O4 : Flag<["-"], "O4">, Group, Flags<[CC1Option]>; def ObjCXX : Flag<["-"], "ObjC++">, Flags<[DriverOption]>, HelpText<"Treat source input files as Objective-C++ inputs">; def ObjC : Flag<["-"], "ObjC">, Flags<[DriverOption]>, HelpText<"Treat source input files as Objective-C inputs">; def O : Joined<["-"], "O">, Group, Flags<[CC1Option]>; def O_flag : Flag<["-"], "O">, Flags<[CC1Option]>, Alias, AliasArgs<["2"]>; def Ofast : Joined<["-"], "Ofast">, Group, Flags<[CC1Option]>; def P : Flag<["-"], "P">, Flags<[CC1Option]>, HelpText<"Disable linemarker output in -E mode">; def Qn : Flag<["-"], "Qn">; def Qunused_arguments : Flag<["-"], "Qunused-arguments">, Flags<[DriverOption, CoreOption]>, HelpText<"Don't emit warning for unused driver arguments">; def Q : Flag<["-"], "Q">; def R : Flag<["-"], "R">; def S : Flag<["-"], "S">, Flags<[DriverOption,CC1Option]>, Group, HelpText<"Only run preprocess and compilation steps">; def Tbss : JoinedOrSeparate<["-"], "Tbss">, Group; def Tdata : JoinedOrSeparate<["-"], "Tdata">, Group; def Ttext : JoinedOrSeparate<["-"], "Ttext">, Group; def T : JoinedOrSeparate<["-"], "T">, Group; def U : JoinedOrSeparate<["-"], "U">, Group, Flags<[CC1Option]>; def V : JoinedOrSeparate<["-"], "V">, Flags<[DriverOption, Unsupported]>; def Wa_COMMA : CommaJoined<["-"], "Wa,">, HelpText<"Pass the comma separated arguments in to the assembler">, MetaVarName<"">; def Wall : Flag<["-"], "Wall">, Group, Flags<[CC1Option]>; def Wdeprecated : Flag<["-"], "Wdeprecated">, Group, Flags<[CC1Option]>; def Wno_deprecated : Flag<["-"], "Wno-deprecated">, Group, Flags<[CC1Option]>; def Wextra : Flag<["-"], "Wextra">, Group, Flags<[CC1Option]>; def Wl_COMMA : CommaJoined<["-"], "Wl,">, Flags<[LinkerInput, RenderAsInput]>, HelpText<"Pass the comma separated arguments in to the linker">, MetaVarName<"">; def Wno_nonportable_cfstrings : Joined<["-"], "Wno-nonportable-cfstrings">, Group, Flags<[CC1Option]>; def Wnonportable_cfstrings : Joined<["-"], "Wnonportable-cfstrings">, Group, Flags<[CC1Option]>; def Wp_COMMA : CommaJoined<["-"], "Wp,">, HelpText<"Pass the comma separated arguments in to the preprocessor">, MetaVarName<"">; def W_Joined : Joined<["-"], "W">, Group, Flags<[CC1Option, CoreOption]>, MetaVarName<"">, HelpText<"Enable the specified warning">; def Xanalyzer : Separate<["-"], "Xanalyzer">, HelpText<"Pass to the static analyzer">, MetaVarName<"">; def Xarch__ : JoinedAndSeparate<["-"], "Xarch_">, Flags<[DriverOption]>; def Xassembler : Separate<["-"], "Xassembler">, HelpText<"Pass to the assembler">, MetaVarName<"">; def Xclang : Separate<["-"], "Xclang">, HelpText<"Pass to the clang compiler">, MetaVarName<"">, Flags<[DriverOption, CoreOption]>; def Xlinker : Separate<["-"], "Xlinker">, Flags<[LinkerInput, RenderAsInput]>, HelpText<"Pass to the linker">, MetaVarName<"">; def Xpreprocessor : Separate<["-"], "Xpreprocessor">, HelpText<"Pass to the preprocessor">, MetaVarName<"">; def X_Flag : Flag<["-"], "X">; def X_Joined : Joined<["-"], "X">; def Z_Flag : Flag<["-"], "Z">; def Z_Joined : Joined<["-"], "Z">; def all__load : Flag<["-"], "all_load">; def allowable__client : Separate<["-"], "allowable_client">; def ansi : Flag<["-", "--"], "ansi">; def arch__errors__fatal : Flag<["-"], "arch_errors_fatal">; def arch : Separate<["-"], "arch">, Flags<[DriverOption]>; def arch__only : Separate<["-"], "arch_only">; def a : Joined<["-"], "a">; def bind__at__load : Flag<["-"], "bind_at_load">; def bundle__loader : Separate<["-"], "bundle_loader">; def bundle : Flag<["-"], "bundle">; def b : JoinedOrSeparate<["-"], "b">, Flags<[Unsupported]>; def cl_kernel_arg_info : Flag<["-"], "cl-kernel-arg-info">, Flags<[CC1Option]>, Group, HelpText<"OpenCL only. This option allows the compiler to store information about the arguments of a kernel(s)"> ; def client__name : JoinedOrSeparate<["-"], "client_name">; def combine : Flag<["-", "--"], "combine">, Flags<[DriverOption, Unsupported]>; def compatibility__version : JoinedOrSeparate<["-"], "compatibility_version">; def coverage : Flag<["-", "--"], "coverage">; def cpp_precomp : Flag<["-"], "cpp-precomp">, Group; def current__version : JoinedOrSeparate<["-"], "current_version">; def cxx_isystem : JoinedOrSeparate<["-"], "cxx-isystem">, Group, HelpText<"Add directory to the C++ SYSTEM include search path">, Flags<[CC1Option]>, MetaVarName<"">; def c : Flag<["-"], "c">, Flags<[DriverOption]>, HelpText<"Only run preprocess, compile, and assemble steps">; def dA : Flag<["-"], "dA">, Group; def dD : Flag<["-"], "dD">, Group, Flags<[CC1Option]>, HelpText<"Print macro definitions in -E mode in addition to normal output">; def dM : Flag<["-"], "dM">, Group, Flags<[CC1Option]>, HelpText<"Print macro definitions in -E mode instead of normal output">; def dead__strip : Flag<["-"], "dead_strip">; def dependency_file : Separate<["-"], "dependency-file">, Flags<[CC1Option]>, HelpText<"Filename (or -) to write dependency output to">; def dependency_dot : Separate<["-"], "dependency-dot">, Flags<[CC1Option]>, HelpText<"Filename to write DOT-formatted header dependencies to">; def dumpmachine : Flag<["-"], "dumpmachine">; def dumpspecs : Flag<["-"], "dumpspecs">, Flags<[Unsupported]>; def dumpversion : Flag<["-"], "dumpversion">; def dylib__file : Separate<["-"], "dylib_file">; def dylinker__install__name : JoinedOrSeparate<["-"], "dylinker_install_name">; def dylinker : Flag<["-"], "dylinker">; def dynamiclib : Flag<["-"], "dynamiclib">; def dynamic : Flag<["-"], "dynamic">, Flags<[NoArgumentUnused]>; def d_Flag : Flag<["-"], "d">, Group; def d_Joined : Joined<["-"], "d">, Group; def emit_ast : Flag<["-"], "emit-ast">, HelpText<"Emit Clang AST files for source inputs">; def emit_llvm : Flag<["-"], "emit-llvm">, Flags<[CC1Option]>, Group, HelpText<"Use the LLVM representation for assembler and object files">; def exported__symbols__list : Separate<["-"], "exported_symbols_list">; def e : JoinedOrSeparate<["-"], "e">; def fPIC : Flag<["-"], "fPIC">, Group; def fno_PIC : Flag<["-"], "fno-PIC">, Group; def fPIE : Flag<["-"], "fPIE">, Group; def fno_PIE : Flag<["-"], "fno-PIE">, Group; def faccess_control : Flag<["-"], "faccess-control">, Group; def fallow_unsupported : Flag<["-"], "fallow-unsupported">, Group; def fapple_kext : Flag<["-"], "fapple-kext">, Group, Flags<[CC1Option]>, HelpText<"Use Apple's kernel extensions ABI">; def fapple_pragma_pack : Flag<["-"], "fapple-pragma-pack">, Group, Flags<[CC1Option]>, HelpText<"Enable Apple gcc-compatible #pragma pack handling">; def faddress_sanitizer : Flag<["-"], "faddress-sanitizer">, Group; def fno_address_sanitizer : Flag<["-"], "fno-address-sanitizer">, Group; def fthread_sanitizer : Flag<["-"], "fthread-sanitizer">, Group; def fno_thread_sanitizer : Flag<["-"], "fno-thread-sanitizer">, Group; def fasm : Flag<["-"], "fasm">, Group; def fasm_blocks : Flag<["-"], "fasm-blocks">, Group, Flags<[CC1Option]>; def fno_asm_blocks : Flag<["-"], "fno-asm-blocks">, Group; def fassume_sane_operator_new : Flag<["-"], "fassume-sane-operator-new">, Group; def fastcp : Flag<["-"], "fastcp">, Group; def fastf : Flag<["-"], "fastf">, Group; def fast : Flag<["-"], "fast">, Group; def fasynchronous_unwind_tables : Flag<["-"], "fasynchronous-unwind-tables">, Group; def fautolink : Flag <["-"], "fautolink">, Group; def fno_autolink : Flag <["-"], "fno-autolink">, Group, Flags<[DriverOption, CC1Option]>, HelpText<"Disable generation of linker directives for automatic library linking">; def fprofile_sample_use_EQ : Joined<["-"], "fprofile-sample-use=">, Group, Flags<[DriverOption, CC1Option]>, HelpText<"Enable sample-based profile guided optimizations">; def fblocks : Flag<["-"], "fblocks">, Group, Flags<[CC1Option]>, HelpText<"Enable the 'blocks' language feature">; def fbootclasspath_EQ : Joined<["-"], "fbootclasspath=">, Group; def fborland_extensions : Flag<["-"], "fborland-extensions">, Group, Flags<[CC1Option]>, HelpText<"Accept non-standard constructs supported by the Borland compiler">; def fbounds_checking : Flag<["-"], "fbounds-checking">, Group, HelpText<"Enable run-time bounds checks">; def fbounds_checking_EQ : Joined<["-"], "fbounds-checking=">, Flags<[CC1Option]>, Group; def fbuiltin : Flag<["-"], "fbuiltin">, Group; def fcaret_diagnostics : Flag<["-"], "fcaret-diagnostics">, Group; def fcatch_undefined_behavior : Flag<["-"], "fcatch-undefined-behavior">, Group; def fclasspath_EQ : Joined<["-"], "fclasspath=">, Group; def fcolor_diagnostics : Flag<["-"], "fcolor-diagnostics">, Group, Flags<[CC1Option]>, HelpText<"Use colors in diagnostics">; def fdiagnostics_color : Flag<["-"], "fdiagnostics-color">, Group; def fdiagnostics_color_EQ : Joined<["-"], "fdiagnostics-color=">, Group; def fansi_escape_codes : Flag<["-"], "fansi-escape-codes">, Group, Flags<[CC1Option]>, HelpText<"Use ANSI escape codes for diagnostics">; def fcomment_block_commands : CommaJoined<["-"], "fcomment-block-commands=">, Group, Flags<[CC1Option]>, HelpText<"Treat each comma separated argument in as a documentation comment block command">, MetaVarName<"">; def fparse_all_comments : Flag<["-"], "fparse-all-comments">, Group, Flags<[CC1Option]>; def fcommon : Flag<["-"], "fcommon">, Group; def fcompile_resource_EQ : Joined<["-"], "fcompile-resource=">, Group; def fconstant_cfstrings : Flag<["-"], "fconstant-cfstrings">, Group; def fconstant_string_class_EQ : Joined<["-"], "fconstant-string-class=">, Group; def fconstexpr_depth_EQ : Joined<["-"], "fconstexpr-depth=">, Group; def fconstexpr_steps_EQ : Joined<["-"], "fconstexpr-steps=">, Group; def fconstexpr_backtrace_limit_EQ : Joined<["-"], "fconstexpr-backtrace-limit=">, Group; def fno_crash_diagnostics : Flag<["-"], "fno-crash-diagnostics">, Group, Flags<[NoArgumentUnused]>; def fcreate_profile : Flag<["-"], "fcreate-profile">, Group; def fcxx_exceptions: Flag<["-"], "fcxx-exceptions">, Group, HelpText<"Enable C++ exceptions">, Flags<[CC1Option]>; def fcxx_modules : Flag <["-"], "fcxx-modules">, Group, Flags<[DriverOption]>; def fdebug_pass_arguments : Flag<["-"], "fdebug-pass-arguments">, Group; def fdebug_pass_structure : Flag<["-"], "fdebug-pass-structure">, Group; def fdiagnostics_fixit_info : Flag<["-"], "fdiagnostics-fixit-info">, Group; def fdiagnostics_parseable_fixits : Flag<["-"], "fdiagnostics-parseable-fixits">, Group, Flags<[CC1Option]>, HelpText<"Print fix-its in machine parseable form">; def fdiagnostics_print_source_range_info : Flag<["-"], "fdiagnostics-print-source-range-info">, Group, Flags<[CC1Option]>, HelpText<"Print source range spans in numeric form">; def fdiagnostics_show_option : Flag<["-"], "fdiagnostics-show-option">, Group, Flags<[CC1Option]>, HelpText<"Print option name with mappable diagnostics">; def fdiagnostics_show_name : Flag<["-"], "fdiagnostics-show-name">, Group, Flags<[CC1Option]>, HelpText<"Print diagnostic name">; def fdiagnostics_show_note_include_stack : Flag<["-"], "fdiagnostics-show-note-include-stack">, Group, Flags<[CC1Option]>, HelpText<"Display include stacks for diagnostic notes">; def fdiagnostics_format_EQ : Joined<["-"], "fdiagnostics-format=">, Group; def fdiagnostics_show_category_EQ : Joined<["-"], "fdiagnostics-show-category=">, Group; def fdiagnostics_show_template_tree : Flag<["-"], "fdiagnostics-show-template-tree">, Group, Flags<[CC1Option]>, HelpText<"Print a template comparison tree for differing templates">; def fdollars_in_identifiers : Flag<["-"], "fdollars-in-identifiers">, Group, HelpText<"Allow '$' in identifiers">, Flags<[CC1Option]>; def fdwarf2_cfi_asm : Flag<["-"], "fdwarf2-cfi-asm">, Group; def fno_dwarf2_cfi_asm : Flag<["-"], "fno-dwarf2-cfi-asm">, Group, Flags<[CC1Option]>; def fdwarf_directory_asm : Flag<["-"], "fdwarf-directory-asm">, Group; def fno_dwarf_directory_asm : Flag<["-"], "fno-dwarf-directory-asm">, Group, Flags<[CC1Option]>; def felide_constructors : Flag<["-"], "felide-constructors">, Group; def fno_elide_type : Flag<["-"], "fno-elide-type">, Group, Flags<[CC1Option]>, HelpText<"Do not elide types when printing diagnostics">; def feliminate_unused_debug_symbols : Flag<["-"], "feliminate-unused-debug-symbols">, Group; def femit_all_decls : Flag<["-"], "femit-all-decls">, Group, Flags<[CC1Option]>, HelpText<"Emit all declarations, even if unused">; def fencoding_EQ : Joined<["-"], "fencoding=">, Group; def ferror_limit_EQ : Joined<["-"], "ferror-limit=">, Group; def fexceptions : Flag<["-"], "fexceptions">, Group, Flags<[CC1Option]>, HelpText<"Enable support for exception handling">; def fexpensive_optimizations : Flag<["-"], "fexpensive-optimizations">, Group; def fno_expensive_optimizations : Flag<["-"], "fno-expensive-optimizations">, Group; def fextdirs_EQ : Joined<["-"], "fextdirs=">, Group; def fextended_identifiers : Flag<["-"], "fextended-identifiers">, Group; def fno_extended_identifiers : Flag<["-"], "fno-extended-identifiers">, Group, Flags<[Unsupported]>; def fhosted : Flag<["-"], "fhosted">, Group; def ffast_math : Flag<["-"], "ffast-math">, Group, Flags<[CC1Option]>, HelpText<"Enable the *frontend*'s 'fast-math' mode. This has no effect on " "optimizations, but provides a preprocessor macro __FAST_MATH__ the " "same as GCC's -ffast-math flag">; def fno_fast_math : Flag<["-"], "fno-fast-math">, Group; def fmath_errno : Flag<["-"], "fmath-errno">, Group, Flags<[CC1Option]>, HelpText<"Require math functions to indicate errors by setting errno">; def fno_math_errno : Flag<["-"], "fno-math-errno">, Group; def fbracket_depth_EQ : Joined<["-"], "fbracket-depth=">, Group; def fsignaling_math : Flag<["-"], "fsignaling-math">, Group; def fno_signaling_math : Flag<["-"], "fno-signaling-math">, Group; def fsanitize_EQ : CommaJoined<["-"], "fsanitize=">, Group, Flags<[CC1Option, CoreOption]>, MetaVarName<"">, HelpText<"Enable runtime instrumentation for bug detection: " "address (memory errors) | thread (race detection) | " "undefined (miscellaneous undefined behavior)">; def fno_sanitize_EQ : CommaJoined<["-"], "fno-sanitize=">, Group; def fsanitize_address_zero_base_shadow : Flag<["-"], "fsanitize-address-zero-base-shadow">, Group, Flags<[CC1Option]>, HelpText<"Make AddressSanitizer map shadow memory " "at zero offset">; def fno_sanitize_address_zero_base_shadow : Flag<["-"], "fno-sanitize-address-zero-base-shadow">, Group; def fsanitize_blacklist : Joined<["-"], "fsanitize-blacklist=">, Group, Flags<[CC1Option]>, HelpText<"Path to blacklist file for sanitizers">; def fno_sanitize_blacklist : Flag<["-"], "fno-sanitize-blacklist">, Group, HelpText<"Don't use blacklist file for sanitizers">; def fsanitize_memory_track_origins : Flag<["-"], "fsanitize-memory-track-origins">, Group, Flags<[CC1Option]>, HelpText<"Enable origins tracking in MemorySanitizer">; def fno_sanitize_memory_track_origins : Flag<["-"], "fno-sanitize-memory-track-origins">, Group; def fsanitize_recover : Flag<["-"], "fsanitize-recover">, Group; def fno_sanitize_recover : Flag<["-"], "fno-sanitize-recover">, Group, Flags<[CC1Option]>, HelpText<"Disable sanitizer check recovery">; def fsanitize_undefined_trap_on_error : Flag<["-"], "fsanitize-undefined-trap-on-error">, Group, Flags<[CC1Option]>; def fno_sanitize_undefined_trap_on_error : Flag<["-"], "fno-sanitize-undefined-trap-on-error">, Group; def funsafe_math_optimizations : Flag<["-"], "funsafe-math-optimizations">, Group; def fno_unsafe_math_optimizations : Flag<["-"], "fno-unsafe-math-optimizations">, Group; def fassociative_math : Flag<["-"], "fassociative-math">, Group; def fno_associative_math : Flag<["-"], "fno-associative-math">, Group; def freciprocal_math : Flag<["-"], "freciprocal-math">, Group; def fno_reciprocal_math : Flag<["-"], "fno-reciprocal-math">, Group; def ffinite_math_only : Flag<["-"], "ffinite-math-only">, Group, Flags<[CC1Option]>; def fno_finite_math_only : Flag<["-"], "fno-finite-math-only">, Group; def fsigned_zeros : Flag<["-"], "fsigned-zeros">, Group; def fno_signed_zeros : Flag<["-"], "fno-signed-zeros">, Group; def fhonor_nans : Flag<["-"], "fhonor-nans">, Group; def fno_honor_nans : Flag<["-"], "fno-honor-nans">, Group; def fhonor_infinities : Flag<["-"], "fhonor-infinities">, Group; def fno_honor_infinities : Flag<["-"], "fno-honor-infinities">, Group; // Sic. This option was misspelled originally. def fhonor_infinites : Flag<["-"], "fhonor-infinites">, Alias; def fno_honor_infinites : Flag<["-"], "fno-honor-infinites">, Alias; def ftrapping_math : Flag<["-"], "ftrapping-math">, Group; def fno_trapping_math : Flag<["-"], "fno-trapping-math">, Group; def ffp_contract : Joined<["-"], "ffp-contract=">, Group, Flags<[CC1Option]>, HelpText<"Form fused FP ops (e.g. FMAs): fast (everywhere)" " | on (according to FP_CONTRACT pragma, default) | off (never fuse)">; def ffor_scope : Flag<["-"], "ffor-scope">, Group; def fno_for_scope : Flag<["-"], "fno-for-scope">, Group; def frewrite_includes : Flag<["-"], "frewrite-includes">, Group, Flags<[CC1Option]>; def fno_rewrite_includes : Flag<["-"], "fno-rewrite-includes">, Group; def ffreestanding : Flag<["-"], "ffreestanding">, Group, Flags<[CC1Option]>, HelpText<"Assert that the compilation takes place in a freestanding environment">; def fformat_extensions: Flag<["-"], "fformat-extensions">, Group, Flags<[CC1Option]>, HelpText<"Enable FreeBSD kernel specific format string extensions">; def fgnu_keywords : Flag<["-"], "fgnu-keywords">, Group, Flags<[CC1Option]>, HelpText<"Allow GNU-extension keywords regardless of language standard">; def fgnu89_inline : Flag<["-"], "fgnu89-inline">, Group, Flags<[CC1Option]>, HelpText<"Use the gnu89 inline semantics">; def fno_gnu89_inline : Flag<["-"], "fno-gnu89-inline">, Group; def fgnu_runtime : Flag<["-"], "fgnu-runtime">, Group, HelpText<"Generate output compatible with the standard GNU Objective-C runtime">; def fheinous_gnu_extensions : Flag<["-"], "fheinous-gnu-extensions">, Flags<[CC1Option]>; def filelist : Separate<["-"], "filelist">, Flags<[LinkerInput]>; def findirect_virtual_calls : Flag<["-"], "findirect-virtual-calls">, Alias; def finline_functions : Flag<["-"], "finline-functions">, Group; def finline : Flag<["-"], "finline">, Group; def finstrument_functions : Flag<["-"], "finstrument-functions">, Group, Flags<[CC1Option]>, HelpText<"Generate calls to instrument function entry and exit">; def fkeep_inline_functions : Flag<["-"], "fkeep-inline-functions">, Group; def flat__namespace : Flag<["-"], "flat_namespace">; def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group; -def flimit_debug_info : Flag<["-"], "flimit-debug-info">, Group, Flags<[CC1Option]>, - HelpText<"Limit debug information produced to reduce size of debug binary">; def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group; def flto : Flag<["-"], "flto">, Group; def fno_lto : Flag<["-"], "fno-lto">, Group; def fmacro_backtrace_limit_EQ : Joined<["-"], "fmacro-backtrace-limit=">, Group; def fmerge_all_constants : Flag<["-"], "fmerge-all-constants">, Group; def fmessage_length_EQ : Joined<["-"], "fmessage-length=">, Group; def fms_extensions : Flag<["-"], "fms-extensions">, Group, Flags<[CC1Option]>, HelpText<"Accept some non-standard constructs supported by the Microsoft compiler">; def fms_compatibility : Flag<["-"], "fms-compatibility">, Group, Flags<[CC1Option]>, HelpText<"Enable Microsoft compatibility mode">; def fmsc_version : Joined<["-"], "fmsc-version=">, Group, Flags<[CC1Option, CoreOption]>, HelpText<"Version of the Microsoft C/C++ compiler to report in _MSC_VER (0 = don't define it (default))">; def fdelayed_template_parsing : Flag<["-"], "fdelayed-template-parsing">, Group, HelpText<"Parse templated function definitions at the end of the " "translation unit ">, Flags<[CC1Option]>; def fmodules_cache_path : Joined<["-"], "fmodules-cache-path=">, Group, Flags<[DriverOption, CC1Option]>, MetaVarName<"">, HelpText<"Specify the module cache path">; def fmodules_prune_interval : Joined<["-"], "fmodules-prune-interval=">, Group, Flags<[CC1Option]>, MetaVarName<"">, HelpText<"Specify the interval (in seconds) between attempts to prune the module cache">; def fmodules_prune_after : Joined<["-"], "fmodules-prune-after=">, Group, Flags<[CC1Option]>, MetaVarName<"">, HelpText<"Specify the interval (in seconds) after which a module file will be considered unused">; def fmodules : Flag <["-"], "fmodules">, Group, Flags<[DriverOption, CC1Option]>, HelpText<"Enable the 'modules' language feature">; def fmodule_maps : Flag <["-"], "fmodule-maps">, Group, Flags<[DriverOption,CC1Option]>, HelpText<"Read module maps to understand the structure of library headers">; def fmodule_name : JoinedOrSeparate<["-"], "fmodule-name=">, Group, Flags<[DriverOption,CC1Option]>, MetaVarName<"">, HelpText<"Specify the name of the module to build">; def fmodule_map_file : JoinedOrSeparate<["-"], "fmodule-map-file=">, Group, Flags<[DriverOption,CC1Option]>, MetaVarName<"">, HelpText<"Load this module map file">; def fmodules_ignore_macro : Joined<["-"], "fmodules-ignore-macro=">, Group, Flags<[CC1Option]>, HelpText<"Ignore the definition of the given macro when building and loading modules">; def fmodules_decluse : Flag <["-"], "fmodules-decluse">, Group, Flags<[DriverOption,CC1Option]>, HelpText<"Require declaration of modules used within a module">; def fretain_comments_from_system_headers : Flag<["-"], "fretain-comments-from-system-headers">, Group, Flags<[CC1Option]>; def fmudflapth : Flag<["-"], "fmudflapth">, Group; def fmudflap : Flag<["-"], "fmudflap">, Group; def fnested_functions : Flag<["-"], "fnested-functions">, Group; def fnext_runtime : Flag<["-"], "fnext-runtime">, Group; def fno_access_control : Flag<["-"], "fno-access-control">, Group, Flags<[CC1Option]>, HelpText<"Disable C++ access control">; def fno_apple_pragma_pack : Flag<["-"], "fno-apple-pragma-pack">, Group; def fno_asm : Flag<["-"], "fno-asm">, Group; def fno_asynchronous_unwind_tables : Flag<["-"], "fno-asynchronous-unwind-tables">, Group; def fno_assume_sane_operator_new : Flag<["-"], "fno-assume-sane-operator-new">, Group, HelpText<"Don't assume that C++'s global operator new can't alias any pointer">, Flags<[CC1Option]>; def fno_blocks : Flag<["-"], "fno-blocks">, Group; def fno_borland_extensions : Flag<["-"], "fno-borland-extensions">, Group; def fno_builtin : Flag<["-"], "fno-builtin">, Group, Flags<[CC1Option]>, HelpText<"Disable implicit builtin knowledge of functions">; def fno_builtin_ : Joined<["-"], "fno-builtin-">, Group, HelpText<"Disable implicit builtin knowledge of a specific function">; def fno_math_builtin : Flag<["-"], "fno-math-builtin">, Group, Flags<[CC1Option]>, HelpText<"Disable implicit builtin knowledge of math functions">; def fno_caret_diagnostics : Flag<["-"], "fno-caret-diagnostics">, Group, Flags<[CC1Option]>; def fno_color_diagnostics : Flag<["-"], "fno-color-diagnostics">, Group; def fno_diagnostics_color : Flag<["-"], "fno-diagnostics-color">, Group; def fno_common : Flag<["-"], "fno-common">, Group, Flags<[CC1Option]>, HelpText<"Compile common globals like normal definitions">; def fno_constant_cfstrings : Flag<["-"], "fno-constant-cfstrings">, Group, Flags<[CC1Option]>, HelpText<"Disable creation of CodeFoundation-type constant strings">; def fno_cxx_exceptions: Flag<["-"], "fno-cxx-exceptions">, Group; def fno_cxx_modules : Flag <["-"], "fno-cxx-modules">, Group, Flags<[DriverOption]>; def fno_diagnostics_fixit_info : Flag<["-"], "fno-diagnostics-fixit-info">, Group, Flags<[CC1Option]>, HelpText<"Do not include fixit information in diagnostics">; def fno_diagnostics_show_name : Flag<["-"], "fno-diagnostics-show-name">, Group; def fno_diagnostics_show_option : Flag<["-"], "fno-diagnostics-show-option">, Group; def fno_diagnostics_show_note_include_stack : Flag<["-"], "fno-diagnostics-show-note-include-stack">, Flags<[CC1Option]>, Group; def fno_dollars_in_identifiers : Flag<["-"], "fno-dollars-in-identifiers">, Group, HelpText<"Disallow '$' in identifiers">, Flags<[CC1Option]>; def fno_elide_constructors : Flag<["-"], "fno-elide-constructors">, Group, HelpText<"Disable C++ copy constructor elision">, Flags<[CC1Option]>; def fno_eliminate_unused_debug_symbols : Flag<["-"], "fno-eliminate-unused-debug-symbols">, Group; def fno_exceptions : Flag<["-"], "fno-exceptions">, Group; def fno_gnu_keywords : Flag<["-"], "fno-gnu-keywords">, Group, Flags<[CC1Option]>; def fno_inline_functions : Flag<["-"], "fno-inline-functions">, Group, Flags<[CC1Option]>; def fno_inline : Flag<["-"], "fno-inline">, Group, Flags<[CC1Option]>; def fno_keep_inline_functions : Flag<["-"], "fno-keep-inline-functions">, Group; def fno_lax_vector_conversions : Flag<["-"], "fno-lax-vector-conversions">, Group, HelpText<"Disallow implicit conversions between vectors with a different number of elements or different element types">, Flags<[CC1Option]>; -def fno_limit_debug_info : Flag<["-"], "fno-limit-debug-info">, Group, Flags<[CC1Option]>, - HelpText<"Do not limit debug information produced to reduce size of debug binary">; def fno_merge_all_constants : Flag<["-"], "fno-merge-all-constants">, Group, Flags<[CC1Option]>, HelpText<"Disallow merging of constants">; def fno_modules : Flag <["-"], "fno-modules">, Group, Flags<[DriverOption]>; def fno_module_maps : Flag <["-"], "fno-module-maps">, Group, Flags<[DriverOption]>; def fno_modules_decluse : Flag <["-"], "fno-modules-decluse">, Group, Flags<[DriverOption]>; def fno_ms_extensions : Flag<["-"], "fno-ms-extensions">, Group; def fno_ms_compatibility : Flag<["-"], "fno-ms-compatibility">, Group; def fno_delayed_template_parsing : Flag<["-"], "fno-delayed-template-parsing">, Group; def fno_objc_exceptions: Flag<["-"], "fno-objc-exceptions">, Group; def fno_objc_legacy_dispatch : Flag<["-"], "fno-objc-legacy-dispatch">, Group; def fno_omit_frame_pointer : Flag<["-"], "fno-omit-frame-pointer">, Group; def fno_operator_names : Flag<["-"], "fno-operator-names">, Group, HelpText<"Do not treat C++ operator name keywords as synonyms for operators">, Flags<[CC1Option]>; def fno_pascal_strings : Flag<["-"], "fno-pascal-strings">, Group; def fno_rtti : Flag<["-"], "fno-rtti">, Group, Flags<[CC1Option]>, HelpText<"Disable generation of rtti information">; def fno_short_enums : Flag<["-"], "fno-short-enums">, Group; def fno_show_column : Flag<["-"], "fno-show-column">, Group, Flags<[CC1Option]>, HelpText<"Do not include column number on diagnostics">; def fno_show_source_location : Flag<["-"], "fno-show-source-location">, Group, Flags<[CC1Option]>, HelpText<"Do not include source location information with diagnostics">; def fno_spell_checking : Flag<["-"], "fno-spell-checking">, Group, Flags<[CC1Option]>, HelpText<"Disable spell-checking">; def fno_stack_protector : Flag<["-"], "fno-stack-protector">, Group; def fno_strict_aliasing : Flag<["-"], "fno-strict-aliasing">, Group; def fstruct_path_tbaa : Flag<["-"], "fstruct-path-tbaa">, Group; def fno_struct_path_tbaa : Flag<["-"], "fno-struct-path-tbaa">, Group; def fno_strict_enums : Flag<["-"], "fno-strict-enums">, Group; def fno_strict_overflow : Flag<["-"], "fno-strict-overflow">, Group; def fno_threadsafe_statics : Flag<["-"], "fno-threadsafe-statics">, Group, Flags<[CC1Option]>, HelpText<"Do not emit code to make initialization of local statics thread safe">; def fno_use_cxa_atexit : Flag<["-"], "fno-use-cxa-atexit">, Group, Flags<[CC1Option]>, HelpText<"Don't use __cxa_atexit for calling destructors">; def fno_use_init_array : Flag<["-"], "fno-use-init-array">, Group, Flags<[CC1Option]>, HelpText<"Don't use .init_array instead of .ctors">; def fno_unit_at_a_time : Flag<["-"], "fno-unit-at-a-time">, Group; def fno_unwind_tables : Flag<["-"], "fno-unwind-tables">, Group; def fno_verbose_asm : Flag<["-"], "fno-verbose-asm">, Group; def fno_working_directory : Flag<["-"], "fno-working-directory">, Group; def fno_wrapv : Flag<["-"], "fno-wrapv">, Group; def fno_zero_initialized_in_bss : Flag<["-"], "fno-zero-initialized-in-bss">, Group; def fobjc_arc : Flag<["-"], "fobjc-arc">, Group, Flags<[CC1Option]>, HelpText<"Synthesize retain and release calls for Objective-C pointers">; def fno_objc_arc : Flag<["-"], "fno-objc-arc">, Group; def fobjc_arc_exceptions : Flag<["-"], "fobjc-arc-exceptions">, Group, Flags<[CC1Option]>, HelpText<"Use EH-safe code when synthesizing retains and releases in -fobjc-arc">; def fno_objc_arc_exceptions : Flag<["-"], "fno-objc-arc-exceptions">, Group; def fobjc_atdefs : Flag<["-"], "fobjc-atdefs">, Group; def fobjc_call_cxx_cdtors : Flag<["-"], "fobjc-call-cxx-cdtors">, Group; def fobjc_exceptions: Flag<["-"], "fobjc-exceptions">, Group, HelpText<"Enable Objective-C exceptions">, Flags<[CC1Option]>; def fobjc_gc_only : Flag<["-"], "fobjc-gc-only">, Group, Flags<[CC1Option]>, HelpText<"Use GC exclusively for Objective-C related memory management">; def fobjc_gc : Flag<["-"], "fobjc-gc">, Group, Flags<[CC1Option]>, HelpText<"Enable Objective-C garbage collection">; def fobjc_legacy_dispatch : Flag<["-"], "fobjc-legacy-dispatch">, Group; def fobjc_new_property : Flag<["-"], "fobjc-new-property">, Group; def fobjc_infer_related_result_type : Flag<["-"], "fobjc-infer-related-result-type">, Group; def fno_objc_infer_related_result_type : Flag<["-"], "fno-objc-infer-related-result-type">, Group, HelpText< "do not infer Objective-C related result type based on method family">, Flags<[CC1Option]>; def fobjc_link_runtime: Flag<["-"], "fobjc-link-runtime">, Group; // Objective-C ABI options. def fobjc_runtime_EQ : Joined<["-"], "fobjc-runtime=">, Group, Flags<[CC1Option]>, HelpText<"Specify the target Objective-C runtime kind and version">; def fobjc_abi_version_EQ : Joined<["-"], "fobjc-abi-version=">, Group; def fobjc_nonfragile_abi_version_EQ : Joined<["-"], "fobjc-nonfragile-abi-version=">, Group; def fobjc_nonfragile_abi : Flag<["-"], "fobjc-nonfragile-abi">, Group; def fno_objc_nonfragile_abi : Flag<["-"], "fno-objc-nonfragile-abi">, Group; def fobjc_sender_dependent_dispatch : Flag<["-"], "fobjc-sender-dependent-dispatch">, Group; def fomit_frame_pointer : Flag<["-"], "fomit-frame-pointer">, Group; def fopenmp : Flag<["-"], "fopenmp">, Group, Flags<[CC1Option]>; def fno_optimize_sibling_calls : Flag<["-"], "fno-optimize-sibling-calls">, Group; def foptimize_sibling_calls : Flag<["-"], "foptimize-sibling-calls">, Group; def force__cpusubtype__ALL : Flag<["-"], "force_cpusubtype_ALL">; def force__flat__namespace : Flag<["-"], "force_flat_namespace">; def force__load : Separate<["-"], "force_load">; def foutput_class_dir_EQ : Joined<["-"], "foutput-class-dir=">, Group; def fpack_struct : Flag<["-"], "fpack-struct">, Group; def fno_pack_struct : Flag<["-"], "fno-pack-struct">, Group; def fpack_struct_EQ : Joined<["-"], "fpack-struct=">, Group, Flags<[CC1Option]>, HelpText<"Specify the default maximum struct packing alignment">; def fpascal_strings : Flag<["-"], "fpascal-strings">, Group, Flags<[CC1Option]>, HelpText<"Recognize and construct Pascal-style string literals">; def fpcc_struct_return : Flag<["-"], "fpcc-struct-return">, Group, Flags<[CC1Option]>, HelpText<"Override the default ABI to return all structs on the stack">; def fpch_preprocess : Flag<["-"], "fpch-preprocess">, Group; def fpic : Flag<["-"], "fpic">, Group; def fno_pic : Flag<["-"], "fno-pic">, Group; def fpie : Flag<["-"], "fpie">, Group; def fno_pie : Flag<["-"], "fno-pie">, Group; def fprofile_arcs : Flag<["-"], "fprofile-arcs">, Group; def fprofile_generate : Flag<["-"], "fprofile-generate">, Group; def framework : Separate<["-"], "framework">, Flags<[LinkerInput]>; def frandom_seed_EQ : Joined<["-"], "frandom-seed=">, Group; def freg_struct_return : Flag<["-"], "freg-struct-return">, Group, Flags<[CC1Option]>, HelpText<"Override the default ABI to return small structs in registers">; def frtti : Flag<["-"], "frtti">, Group; def fsched_interblock : Flag<["-"], "fsched-interblock">, Group; def fshort_enums : Flag<["-"], "fshort-enums">, Group, Flags<[CC1Option]>, HelpText<"Allocate to an enum type only as many bytes as it needs for the declared range of possible values">; def freorder_blocks : Flag<["-"], "freorder-blocks">, Group; def fshort_wchar : Flag<["-"], "fshort-wchar">, Group, Flags<[CC1Option]>, HelpText<"Force wchar_t to be a short unsigned int">; def fshow_overloads_EQ : Joined<["-"], "fshow-overloads=">, Group, Flags<[CC1Option]>, HelpText<"Which overload candidates to show when overload resolution fails: " "best|all; defaults to all">; def fshow_column : Flag<["-"], "fshow-column">, Group, Flags<[CC1Option]>; def fshow_source_location : Flag<["-"], "fshow-source-location">, Group; def fspell_checking : Flag<["-"], "fspell-checking">, Group; def fsigned_bitfields : Flag<["-"], "fsigned-bitfields">, Group; def fsigned_char : Flag<["-"], "fsigned-char">, Group; def fno_signed_char : Flag<["-"], "fno-signed-char">, Flags<[CC1Option]>, Group, HelpText<"Char is unsigned">; def fsplit_stack : Flag<["-"], "fsplit-stack">, Group; def fstack_protector_all : Flag<["-"], "fstack-protector-all">, Group; def fstack_protector : Flag<["-"], "fstack-protector">, Group; +def fstandalone_debug : Flag<["-"], "fstandalone-debug">, Group, Flags<[CC1Option]>, + HelpText<"Emit full debug info for all types used by the program">; +def fno_standalone_debug : Flag<["-"], "fno-standalone-debug">, Group, Flags<[CC1Option]>, + HelpText<"Limit debug information produced to reduce size of debug binary">; +def flimit_debug_info : Flag<["-"], "flimit-debug-info">, Alias; +def fno_limit_debug_info : Flag<["-"], "fno-limit-debug-info">, Alias; def fstrict_aliasing : Flag<["-"], "fstrict-aliasing">, Group; def fstrict_enums : Flag<["-"], "fstrict-enums">, Group, Flags<[CC1Option]>, HelpText<"Enable optimizations based on the strict definition of an enum's " "value range">; def fstrict_overflow : Flag<["-"], "fstrict-overflow">, Group; def fsyntax_only : Flag<["-"], "fsyntax-only">, Flags<[DriverOption,CC1Option]>, Group; def ftabstop_EQ : Joined<["-"], "ftabstop=">, Group; def ftemplate_depth_EQ : Joined<["-"], "ftemplate-depth=">, Group; def ftemplate_depth_ : Joined<["-"], "ftemplate-depth-">, Group; def ftemplate_backtrace_limit_EQ : Joined<["-"], "ftemplate-backtrace-limit=">, Group; def foperator_arrow_depth_EQ : Joined<["-"], "foperator-arrow-depth=">, Group; def ftest_coverage : Flag<["-"], "ftest-coverage">, Group; def fvectorize : Flag<["-"], "fvectorize">, Group, HelpText<"Enable the loop vectorization passes">; def fno_vectorize : Flag<["-"], "fno-vectorize">, Group; def ftree_vectorize : Flag<["-"], "ftree-vectorize">, Alias; def fno_tree_vectorize : Flag<["-"], "fno-tree-vectorize">, Alias; def fslp_vectorize : Flag<["-"], "fslp-vectorize">, Group, HelpText<"Enable the superword-level parallelism vectorization passes">; def fno_slp_vectorize : Flag<["-"], "fno-slp-vectorize">, Group; def fslp_vectorize_aggressive : Flag<["-"], "fslp-vectorize-aggressive">, Group, HelpText<"Enable the BB vectorization passes">; def fno_slp_vectorize_aggressive : Flag<["-"], "fno-slp-vectorize-aggressive">, Group; def ftree_slp_vectorize : Flag<["-"], "ftree-slp-vectorize">, Alias; def fno_tree_slp_vectorize : Flag<["-"], "fno-tree-slp-vectorize">, Alias; def Wlarge_by_value_copy_def : Flag<["-"], "Wlarge-by-value-copy">, HelpText<"Warn if a function definition returns or accepts an object larger " "in bytes than a given value">, Flags<[HelpHidden]>; def Wlarge_by_value_copy_EQ : Joined<["-"], "Wlarge-by-value-copy=">, Flags<[CC1Option]>; // Just silence warnings about -Wlarger-than, -Wframe-larger-than for now. def Wlarger_than : Separate<["-"], "Wlarger-than">, Group; def Wlarger_than_EQ : Joined<["-"], "Wlarger-than=">, Alias; def Wlarger_than_ : Joined<["-"], "Wlarger-than-">, Alias; def Wframe_larger_than : Separate<["-"], "Wframe-larger-than">, Group; def Wframe_larger_than_EQ : Joined<["-"], "Wframe-larger-than=">, Alias; def fterminated_vtables : Flag<["-"], "fterminated-vtables">, Alias; def fthreadsafe_statics : Flag<["-"], "fthreadsafe-statics">, Group; def ftime_report : Flag<["-"], "ftime-report">, Group, Flags<[CC1Option]>; def ftlsmodel_EQ : Joined<["-"], "ftls-model=">, Group, Flags<[CC1Option]>; def ftrapv : Flag<["-"], "ftrapv">, Group, Flags<[CC1Option]>, HelpText<"Trap on integer overflow">; def ftrapv_handler_EQ : Joined<["-"], "ftrapv-handler=">, Group, MetaVarName<"">, HelpText<"Specify the function to be called on overflow">; def ftrapv_handler : Separate<["-"], "ftrapv-handler">, Group, Flags<[CC1Option]>; def ftrap_function_EQ : Joined<["-"], "ftrap-function=">, Group, Flags<[CC1Option]>, HelpText<"Issue call to specified function rather than a trap instruction">; def funit_at_a_time : Flag<["-"], "funit-at-a-time">, Group; def funroll_loops : Flag<["-"], "funroll-loops">, Group, HelpText<"Turn on loop unroller">, Flags<[CC1Option]>; def fno_unroll_loops : Flag<["-"], "fno-unroll-loops">, Group, HelpText<"Turn off loop unroller">, Flags<[CC1Option]>; def freroll_loops : Flag<["-"], "freroll-loops">, Group, HelpText<"Turn on loop reroller">, Flags<[CC1Option]>; def fno_reroll_loops : Flag<["-"], "fno-reroll-loops">, Group, HelpText<"Turn off loop reroller">; def funsigned_bitfields : Flag<["-"], "funsigned-bitfields">, Group; def funsigned_char : Flag<["-"], "funsigned-char">, Group; def fno_unsigned_char : Flag<["-"], "fno-unsigned-char">, Group; def funwind_tables : Flag<["-"], "funwind-tables">, Group; def fuse_cxa_atexit : Flag<["-"], "fuse-cxa-atexit">, Group; def fuse_init_array : Flag<["-"], "fuse-init-array">, Group, Flags<[CC1Option]>, HelpText<"Use .init_array instead of .ctors">; def fno_var_tracking : Flag<["-"], "fno-var-tracking">, Group; def fverbose_asm : Flag<["-"], "fverbose-asm">, Group; def fvisibility_EQ : Joined<["-"], "fvisibility=">, Group, HelpText<"Set the default symbol visibility for all global declarations">; def fvisibility_inlines_hidden : Flag<["-"], "fvisibility-inlines-hidden">, Group, HelpText<"Give inline C++ member functions default visibility by default">, Flags<[CC1Option]>; def fvisibility_ms_compat : Flag<["-"], "fvisibility-ms-compat">, Group, HelpText<"Give global types 'default' visibility and global functions and " "variables 'hidden' visibility by default">; def fwrapv : Flag<["-"], "fwrapv">, Group, Flags<[CC1Option]>, HelpText<"Treat signed integer overflow as two's complement">; def fwritable_strings : Flag<["-"], "fwritable-strings">, Group, Flags<[CC1Option]>, HelpText<"Store string literals as writable data">; def fzero_initialized_in_bss : Flag<["-"], "fzero-initialized-in-bss">, Group; def ffunction_sections : Flag<["-"], "ffunction-sections">, Group, Flags<[CC1Option]>, HelpText<"Place each function in its own section (ELF Only)">; def fno_function_sections : Flag<["-"], "fno-function-sections">, Group, Flags<[CC1Option]>; def fdata_sections : Flag <["-"], "fdata-sections">, Group, Flags<[CC1Option]>, HelpText<"Place each data in its own section (ELF Only)">; def fno_data_sections : Flag <["-"], "fno-data-sections">, Group, Flags<[CC1Option]>; def fdebug_types_section: Flag <["-"], "fdebug-types-section">, Group, Flags<[CC1Option]>, HelpText<"Place debug types in their own section (ELF Only)">; def g_Flag : Flag<["-"], "g">, Group, HelpText<"Generate source level debug information">, Flags<[CC1Option]>; def gline_tables_only : Flag<["-"], "gline-tables-only">, Group, HelpText<"Emit debug line number tables only">, Flags<[CC1Option]>; def g0 : Flag<["-"], "g0">, Group; def g1 : Flag<["-"], "g1">, Group; def g2 : Flag<["-"], "g2">, Group; def g3 : Flag<["-"], "g3">, Group; def ggdb : Flag<["-"], "ggdb">, Group; def ggdb0 : Flag<["-"], "ggdb0">, Group; def ggdb1 : Flag<["-"], "ggdb1">, Group; def ggdb2 : Flag<["-"], "ggdb2">, Group; def ggdb3 : Flag<["-"], "ggdb3">, Group; def gdwarf_2 : Flag<["-"], "gdwarf-2">, Group, HelpText<"Generate source level debug information with dwarf version 2">, Flags<[CC1Option]>; def gdwarf_3 : Flag<["-"], "gdwarf-3">, Group, HelpText<"Generate source level debug information with dwarf version 3">, Flags<[CC1Option]>; def gdwarf_4 : Flag<["-"], "gdwarf-4">, Group, HelpText<"Generate source level debug information with dwarf version 4">, Flags<[CC1Option]>; def gfull : Flag<["-"], "gfull">, Group; def gused : Flag<["-"], "gused">, Group; def gstabs : Joined<["-"], "gstabs">, Group, Flags<[Unsupported]>; def gcoff : Joined<["-"], "gcoff">, Group, Flags<[Unsupported]>; def gxcoff : Joined<["-"], "gxcoff">, Group, Flags<[Unsupported]>; def gvms : Joined<["-"], "gvms">, Group, Flags<[Unsupported]>; def gtoggle : Flag<["-"], "gtoggle">, Group, Flags<[Unsupported]>; def grecord_gcc_switches : Flag<["-"], "grecord-gcc-switches">, Group; def gno_record_gcc_switches : Flag<["-"], "gno-record-gcc-switches">, Group; def gstrict_dwarf : Flag<["-"], "gstrict-dwarf">, Group; def gno_strict_dwarf : Flag<["-"], "gno-strict-dwarf">, Group; def gcolumn_info : Flag<["-"], "gcolumn-info">, Group; def gsplit_dwarf : Flag<["-"], "gsplit-dwarf">, Group; def ggnu_pubnames : Flag<["-"], "ggnu-pubnames">, Group; def headerpad__max__install__names : Joined<["-"], "headerpad_max_install_names">; def help : Flag<["-", "--"], "help">, Flags<[CC1Option]>, HelpText<"Display available options">; def index_header_map : Flag<["-"], "index-header-map">, Flags<[CC1Option]>, HelpText<"Make the next included directory (-I or -F) an indexer header map">; def idirafter : JoinedOrSeparate<["-"], "idirafter">, Group, Flags<[CC1Option]>, HelpText<"Add directory to AFTER include search path">; def iframework : JoinedOrSeparate<["-"], "iframework">, Group, Flags<[CC1Option]>, HelpText<"Add directory to SYSTEM framework search path">; def imacros : JoinedOrSeparate<["-", "--"], "imacros">, Group, Flags<[CC1Option]>, HelpText<"Include macros from file before parsing">, MetaVarName<"">; def image__base : Separate<["-"], "image_base">; def include_ : JoinedOrSeparate<["-", "--"], "include">, Group, EnumName<"include">, MetaVarName<"">, HelpText<"Include file before parsing">, Flags<[CC1Option]>; def include_pch : Separate<["-"], "include-pch">, Group, Flags<[CC1Option]>, HelpText<"Include precompiled header file">, MetaVarName<"">; def relocatable_pch : Flag<["-", "--"], "relocatable-pch">, Flags<[CC1Option]>, HelpText<"Whether to build a relocatable precompiled header">; def init : Separate<["-"], "init">; def install__name : Separate<["-"], "install_name">; def integrated_as : Flag<["-"], "integrated-as">, Flags<[DriverOption]>; def iprefix : JoinedOrSeparate<["-"], "iprefix">, Group, Flags<[CC1Option]>, HelpText<"Set the -iwithprefix/-iwithprefixbefore prefix">, MetaVarName<"">; def iquote : JoinedOrSeparate<["-"], "iquote">, Group, Flags<[CC1Option]>, HelpText<"Add directory to QUOTE include search path">, MetaVarName<"">; def isysroot : JoinedOrSeparate<["-"], "isysroot">, Group, Flags<[CC1Option]>, HelpText<"Set the system root directory (usually /)">, MetaVarName<"">; def isystem : JoinedOrSeparate<["-"], "isystem">, Group, Flags<[CC1Option]>, HelpText<"Add directory to SYSTEM include search path">, MetaVarName<"">; def iwithprefixbefore : JoinedOrSeparate<["-"], "iwithprefixbefore">, Group, HelpText<"Set directory to include search path with prefix">, MetaVarName<"">, Flags<[CC1Option]>; def iwithprefix : JoinedOrSeparate<["-"], "iwithprefix">, Group, Flags<[CC1Option]>, HelpText<"Set directory to SYSTEM include search path with prefix">, MetaVarName<"">; def iwithsysroot : JoinedOrSeparate<["-"], "iwithsysroot">, Group, HelpText<"Add directory to SYSTEM include search path, " "absolute paths are relative to -isysroot">, MetaVarName<"">, Flags<[CC1Option]>; def i : Joined<["-"], "i">, Group; def keep__private__externs : Flag<["-"], "keep_private_externs">; def l : JoinedOrSeparate<["-"], "l">, Flags<[LinkerInput, RenderJoined]>; def lazy__framework : Separate<["-"], "lazy_framework">, Flags<[LinkerInput]>; def lazy__library : Separate<["-"], "lazy_library">, Flags<[LinkerInput]>; def EL : Flag<["-"], "EL">, Flags<[DriverOption]>; def EB : Flag<["-"], "EB">, Flags<[DriverOption]>; def m32 : Flag<["-"], "m32">, Group, Flags<[DriverOption, CoreOption]>; def mqdsp6_compat : Flag<["-"], "mqdsp6-compat">, Group, Flags<[DriverOption,CC1Option]>, HelpText<"Enable hexagon-qdsp6 backward compatibility">; def m3dnowa : Flag<["-"], "m3dnowa">, Group; def m3dnow : Flag<["-"], "m3dnow">, Group; def m64 : Flag<["-"], "m64">, Group, Flags<[DriverOption, CoreOption]>; def mabi_EQ : Joined<["-"], "mabi=">, Group; def march_EQ : Joined<["-"], "march=">, Group; def mcmodel_EQ : Joined<["-"], "mcmodel=">, Group; def mconstant_cfstrings : Flag<["-"], "mconstant-cfstrings">, Group; def mcpu_EQ : Joined<["-"], "mcpu=">, Group; def mdynamic_no_pic : Joined<["-"], "mdynamic-no-pic">, Group; def mfix_and_continue : Flag<["-"], "mfix-and-continue">, Group; def mieee_fp : Flag<["-"], "mieee-fp">, Group; def minline_all_stringops : Flag<["-"], "minline-all-stringops">, Group; def mno_inline_all_stringops : Flag<["-"], "mno-inline-all-stringops">, Group; def mfloat_abi_EQ : Joined<["-"], "mfloat-abi=">, Group; def mfpmath_EQ : Joined<["-"], "mfpmath=">, Group; def mfpu_EQ : Joined<["-"], "mfpu=">, Group; def mhwdiv_EQ : Joined<["-"], "mhwdiv=">, Group; def mglobal_merge : Flag<["-"], "mglobal-merge">, Group; def mhard_float : Flag<["-"], "mhard-float">, Group; def miphoneos_version_min_EQ : Joined<["-"], "miphoneos-version-min=">, Group; def mios_version_min_EQ : Joined<["-"], "mios-version-min=">, Alias; def mios_simulator_version_min_EQ : Joined<["-"], "mios-simulator-version-min=">, Group; def mkernel : Flag<["-"], "mkernel">, Group; def mlinker_version_EQ : Joined<["-"], "mlinker-version=">, Flags<[DriverOption]>; def mllvm : Separate<["-"], "mllvm">, Flags<[CC1Option]>, HelpText<"Additional arguments to forward to LLVM's option processing">; def mmacosx_version_min_EQ : Joined<["-"], "mmacosx-version-min=">, Group; def mms_bitfields : Flag<["-"], "mms-bitfields">, Group, Flags<[CC1Option]>, HelpText<"Set the default structure layout to be compatible with the Microsoft compiler standard">; def mstackrealign : Flag<["-"], "mstackrealign">, Group, Flags<[CC1Option]>, HelpText<"Force realign the stack at entry to every function">; def mstack_alignment : Joined<["-"], "mstack-alignment=">, Group, Flags<[CC1Option]>, HelpText<"Set the stack alignment">; def mmmx : Flag<["-"], "mmmx">, Group; def mno_3dnowa : Flag<["-"], "mno-3dnowa">, Group; def mno_3dnow : Flag<["-"], "mno-3dnow">, Group; def mno_constant_cfstrings : Flag<["-"], "mno-constant-cfstrings">, Group; def mno_global_merge : Flag<["-"], "mno-global-merge">, Group, Flags<[CC1Option]>, HelpText<"Disable merging of globals">; def mno_mmx : Flag<["-"], "mno-mmx">, Group; def mno_pascal_strings : Flag<["-"], "mno-pascal-strings">, Alias; def mno_red_zone : Flag<["-"], "mno-red-zone">, Group; def mno_relax_all : Flag<["-"], "mno-relax-all">, Group; def mno_rtd: Flag<["-"], "mno-rtd">, Group; def mno_soft_float : Flag<["-"], "mno-soft-float">, Group; def mno_stackrealign : Flag<["-"], "mno-stackrealign">, Group; def mno_sse2 : Flag<["-"], "mno-sse2">, Group; def mno_sse3 : Flag<["-"], "mno-sse3">, Group; def mno_sse4a : Flag<["-"], "mno-sse4a">, Group; def mno_sse4 : Flag<["-"], "mno-sse4">, Group; def mno_sse4_1 : Flag<["-"], "mno-sse4.1">, Group; def mno_sse4_2 : Flag<["-"], "mno-sse4.2">, Group; def mno_sse : Flag<["-"], "mno-sse">, Group; def mno_ssse3 : Flag<["-"], "mno-ssse3">, Group; def mno_aes : Flag<["-"], "mno-aes">, Group; def mno_avx : Flag<["-"], "mno-avx">, Group; def mno_avx2 : Flag<["-"], "mno-avx2">, Group; def mno_avx512f : Flag<["-"], "mno-avx512f">, Group; def mno_avx512cd : Flag<["-"], "mno-avx512cd">, Group; def mno_avx512er : Flag<["-"], "mno-avx512er">, Group; def mno_avx512pf : Flag<["-"], "mno-avx512pf">, Group; def mno_pclmul : Flag<["-"], "mno-pclmul">, Group; def mno_lzcnt : Flag<["-"], "mno-lzcnt">, Group; def mno_rdrnd : Flag<["-"], "mno-rdrnd">, Group; def mno_bmi : Flag<["-"], "mno-bmi">, Group; def mno_bmi2 : Flag<["-"], "mno-bmi2">, Group; def mno_popcnt : Flag<["-"], "mno-popcnt">, Group; def mno_tbm : Flag<["-"], "mno-tbm">, Group; def mno_fma4 : Flag<["-"], "mno-fma4">, Group; def mno_fma : Flag<["-"], "mno-fma">, Group; def mno_xop : Flag<["-"], "mno-xop">, Group; def mno_f16c : Flag<["-"], "mno-f16c">, Group; def mno_rtm : Flag<["-"], "mno-rtm">, Group; def mno_prfchw : Flag<["-"], "mno-prfchw">, Group; def mno_rdseed : Flag<["-"], "mno-rdseed">, Group; def mno_sha : Flag<["-"], "mno-sha">, Group; def munaligned_access : Flag<["-"], "munaligned-access">, Group, HelpText<"Allow memory accesses to be unaligned (ARM only)">; def mno_unaligned_access : Flag<["-"], "mno-unaligned-access">, Group, HelpText<"Force all memory accesses to be aligned (ARM only)">; def mstrict_align : Flag<["-"], "mstrict-align">, Alias, Flags<[CC1Option,HelpHidden]>, HelpText<"Force all memory accesses to be aligned (ARM only, same as mno-unaligned-access)">; def mno_thumb : Flag<["-"], "mno-thumb">, Group; def mrestrict_it: Flag<["-"], "mrestrict-it">, Group, HelpText<"Disallow generation of deprecated IT blocks for ARMv8. It is on by default for ARMv8 Thumb mode.">; def mno_restrict_it: Flag<["-"], "mno-restrict-it">, Group, HelpText<"Allow generation of deprecated IT blocks for ARMv8. It is off by default for ARMv8 Thumb mode">; def marm : Flag<["-"], "marm">, Alias; def ffixed_r9 : Flag<["-"], "ffixed-r9">, Group, HelpText<"Reserve the r9 register (ARM only)">; def mcrc : Flag<["-"], "mcrc">, Group, HelpText<"Allow use of CRC instructions (ARM only)">; def mnocrc : Flag<["-"], "mnocrc">, Group, HelpText<"Disallow use of CRC instructions (ARM only)">; def mvsx : Flag<["-"], "mvsx">, Group; def mno_vsx : Flag<["-"], "mno-vsx">, Group; def mfprnd : Flag<["-"], "mfprnd">, Group; def mno_fprnd : Flag<["-"], "mno-fprnd">, Group; def mmfcrf : Flag<["-"], "mmfcrf">, Group; def mno_mfcrf : Flag<["-"], "mno-mfcrf">, Group; def mpopcntd : Flag<["-"], "mpopcntd">, Group; def mno_popcntd : Flag<["-"], "mno-popcntd">, Group; def mqpx : Flag<["-"], "mqpx">, Group; def mno_qpx : Flag<["-"], "mno-qpx">, Group; def faltivec : Flag<["-"], "faltivec">, Group, Flags<[CC1Option]>, HelpText<"Enable AltiVec vector initializer syntax">; def fno_altivec : Flag<["-"], "fno-altivec">, Group, Flags<[CC1Option]>; def maltivec : Flag<["-"], "maltivec">, Alias; def mno_altivec : Flag<["-"], "mno-altivec">, Alias; def mno_warn_nonportable_cfstrings : Flag<["-"], "mno-warn-nonportable-cfstrings">, Group; def mno_omit_leaf_frame_pointer : Flag<["-"], "mno-omit-leaf-frame-pointer">, Group; def momit_leaf_frame_pointer : Flag<["-"], "momit-leaf-frame-pointer">, Group, HelpText<"Omit frame pointer setup for leaf functions">, Flags<[CC1Option]>; def moslib_EQ : Joined<["-"], "moslib=">, Group; def mpascal_strings : Flag<["-"], "mpascal-strings">, Alias; def mred_zone : Flag<["-"], "mred-zone">, Group; def mregparm_EQ : Joined<["-"], "mregparm=">, Group; def mrelax_all : Flag<["-"], "mrelax-all">, Group, Flags<[CC1Option]>, HelpText<"(integrated-as) Relax all machine instructions">; def mrtd : Flag<["-"], "mrtd">, Group, Flags<[CC1Option]>, HelpText<"Make StdCall calling convention the default">; def msmall_data_threshold_EQ : Joined <["-"], "msmall-data-threshold=">, Group; def msoft_float : Flag<["-"], "msoft-float">, Group, Flags<[CC1Option]>, HelpText<"Use software floating point">; def mno_implicit_float : Flag<["-"], "mno-implicit-float">, Group, HelpText<"Don't generate implicit floating point instructions">; def mimplicit_float : Flag<["-"], "mimplicit-float">, Group; def msse2 : Flag<["-"], "msse2">, Group; def msse3 : Flag<["-"], "msse3">, Group; def msse4a : Flag<["-"], "msse4a">, Group; def msse4 : Flag<["-"], "msse4">, Group; def msse4_1 : Flag<["-"], "msse4.1">, Group; def msse4_2 : Flag<["-"], "msse4.2">, Group; def msse : Flag<["-"], "msse">, Group; def mssse3 : Flag<["-"], "mssse3">, Group; def maes : Flag<["-"], "maes">, Group; def mavx : Flag<["-"], "mavx">, Group; def mavx2 : Flag<["-"], "mavx2">, Group; def mavx512f : Flag<["-"], "mavx512f">, Group; def mavx512cd : Flag<["-"], "mavx512cd">, Group; def mavx512er : Flag<["-"], "mavx512er">, Group; def mavx512pf : Flag<["-"], "mavx512pf">, Group; def mpclmul : Flag<["-"], "mpclmul">, Group; def mlzcnt : Flag<["-"], "mlzcnt">, Group; def mrdrnd : Flag<["-"], "mrdrnd">, Group; def mbmi : Flag<["-"], "mbmi">, Group; def mbmi2 : Flag<["-"], "mbmi2">, Group; def mpopcnt : Flag<["-"], "mpopcnt">, Group; def mtbm : Flag<["-"], "mtbm">, Group; def mfma4 : Flag<["-"], "mfma4">, Group; def mfma : Flag<["-"], "mfma">, Group; def mxop : Flag<["-"], "mxop">, Group; def mf16c : Flag<["-"], "mf16c">, Group; def mrtm : Flag<["-"], "mrtm">, Group; def mprfchw : Flag<["-"], "mprfchw">, Group; def mrdseed : Flag<["-"], "mrdseed">, Group; def msha : Flag<["-"], "msha">, Group; def mcx16 : Flag<["-"], "mcx16">, Group; def mips16 : Flag<["-"], "mips16">, Group; def mno_mips16 : Flag<["-"], "mno-mips16">, Group; def mmicromips : Flag<["-"], "mmicromips">, Group; def mno_micromips : Flag<["-"], "mno-micromips">, Group; def mxgot : Flag<["-"], "mxgot">, Group; def mno_xgot : Flag<["-"], "mno-xgot">, Group; def mldc1_sdc1 : Flag<["-"], "mldc1-sdc1">, Group; def mno_ldc1_sdc1 : Flag<["-"], "mno-ldc1-sdc1">, Group; def mcheck_zero_division : Flag<["-"], "mcheck-zero-division">, Group; def mno_check_zero_division : Flag<["-"], "mno-check-zero-division">, Group; def mdsp : Flag<["-"], "mdsp">, Group; def mno_dsp : Flag<["-"], "mno-dsp">, Group; def mdspr2 : Flag<["-"], "mdspr2">, Group; def mno_dspr2 : Flag<["-"], "mno-dspr2">, Group; def msingle_float : Flag<["-"], "msingle-float">, Group; def mdouble_float : Flag<["-"], "mdouble-float">, Group; def mmsa : Flag<["-"], "mmsa">, Group, HelpText<"Enable MSA ASE (MIPS only)">; def mno_msa : Flag<["-"], "mno-msa">, Group, HelpText<"Disable MSA ASE (MIPS only)">; def mfp64 : Flag<["-"], "mfp64">, Group, HelpText<"Use 64-bit floating point registers (MIPS only)">; def mfp32 : Flag<["-"], "mfp32">, Group, HelpText<"Use 32-bit floating point registers (MIPS only)">; def mnan_EQ : Joined<["-"], "mnan=">, Group; def mips32 : Flag<["-"], "mips32">, Alias, AliasArgs<["mips32"]>, HelpText<"Equivalent to -march=mips32">, Flags<[HelpHidden]>; def mips32r2 : Flag<["-"], "mips32r2">, Alias, AliasArgs<["mips32r2"]>, HelpText<"Equivalent to -march=mips32r2">, Flags<[HelpHidden]>; def mips64 : Flag<["-"], "mips64">, Alias, AliasArgs<["mips64"]>, HelpText<"Equivalent to -march=mips64">, Flags<[HelpHidden]>; def mips64r2 : Flag<["-"], "mips64r2">, Alias, AliasArgs<["mips64r2"]>, HelpText<"Equivalent to -march=mips64r2">, Flags<[HelpHidden]>; def module_file_info : Flag<["-"], "module-file-info">, Flags<[DriverOption,CC1Option]>, Group; def mthumb : Flag<["-"], "mthumb">, Group; def mtune_EQ : Joined<["-"], "mtune=">, Group; def multi__module : Flag<["-"], "multi_module">; def multiply__defined__unused : Separate<["-"], "multiply_defined_unused">; def multiply__defined : Separate<["-"], "multiply_defined">; def mwarn_nonportable_cfstrings : Flag<["-"], "mwarn-nonportable-cfstrings">, Group; def no_canonical_prefixes : Flag<["-"], "no-canonical-prefixes">, Flags<[HelpHidden]>, HelpText<"Use relative instead of canonical paths">; def no_cpp_precomp : Flag<["-"], "no-cpp-precomp">, Group; def no_integrated_as : Flag<["-"], "no-integrated-as">, Flags<[DriverOption]>; def no_integrated_cpp : Flag<["-", "--"], "no-integrated-cpp">, Flags<[DriverOption]>; def no_pedantic : Flag<["-", "--"], "no-pedantic">, Group; def no__dead__strip__inits__and__terms : Flag<["-"], "no_dead_strip_inits_and_terms">; def nobuiltininc : Flag<["-"], "nobuiltininc">, Flags<[CC1Option]>, HelpText<"Disable builtin #include directories">; def nodefaultlibs : Flag<["-"], "nodefaultlibs">; def nofixprebinding : Flag<["-"], "nofixprebinding">; def nolibc : Flag<["-"], "nolibc">; def nomultidefs : Flag<["-"], "nomultidefs">; def nopie : Flag<["-"], "nopie">; def noprebind : Flag<["-"], "noprebind">; def noseglinkedit : Flag<["-"], "noseglinkedit">; def nostartfiles : Flag<["-"], "nostartfiles">; def nostdinc : Flag<["-"], "nostdinc">; def nostdlibinc : Flag<["-"], "nostdlibinc">; def nostdincxx : Flag<["-"], "nostdinc++">, Flags<[CC1Option]>, HelpText<"Disable standard #include directories for the C++ standard library">; def nostdlib : Flag<["-"], "nostdlib">; def object : Flag<["-"], "object">; def o : JoinedOrSeparate<["-"], "o">, Flags<[DriverOption, RenderAsInput, CC1Option]>, HelpText<"Write output to ">, MetaVarName<"">; def pagezero__size : JoinedOrSeparate<["-"], "pagezero_size">; def pass_exit_codes : Flag<["-", "--"], "pass-exit-codes">, Flags<[Unsupported]>; def pedantic_errors : Flag<["-", "--"], "pedantic-errors">, Group, Flags<[CC1Option]>; def pedantic : Flag<["-", "--"], "pedantic">, Group, Flags<[CC1Option]>; def pg : Flag<["-"], "pg">, HelpText<"Enable mcount instrumentation">, Flags<[CC1Option]>; def pipe : Flag<["-", "--"], "pipe">, HelpText<"Use pipes between commands, when possible">; def prebind__all__twolevel__modules : Flag<["-"], "prebind_all_twolevel_modules">; def prebind : Flag<["-"], "prebind">; def preload : Flag<["-"], "preload">; def print_file_name_EQ : Joined<["-", "--"], "print-file-name=">, HelpText<"Print the full library path of ">, MetaVarName<"">; def print_ivar_layout : Flag<["-"], "print-ivar-layout">, Flags<[CC1Option]>, HelpText<"Enable Objective-C Ivar layout bitmap print trace">; def print_libgcc_file_name : Flag<["-", "--"], "print-libgcc-file-name">, HelpText<"Print the library path for \"libgcc.a\"">; def print_multi_directory : Flag<["-", "--"], "print-multi-directory">; def print_multi_lib : Flag<["-", "--"], "print-multi-lib">; def print_multi_os_directory : Flag<["-", "--"], "print-multi-os-directory">; def print_prog_name_EQ : Joined<["-", "--"], "print-prog-name=">, HelpText<"Print the full program path of ">, MetaVarName<"">; def print_search_dirs : Flag<["-", "--"], "print-search-dirs">, HelpText<"Print the paths used for finding libraries and programs">; def private__bundle : Flag<["-"], "private_bundle">; def pthreads : Flag<["-"], "pthreads">; def pthread : Flag<["-"], "pthread">, Flags<[CC1Option]>, HelpText<"Support POSIX threads in generated code">; def p : Flag<["-"], "p">; def pie : Flag<["-"], "pie">; def read__only__relocs : Separate<["-"], "read_only_relocs">; def remap : Flag<["-"], "remap">; def rewrite_objc : Flag<["-"], "rewrite-objc">, Flags<[DriverOption,CC1Option]>, HelpText<"Rewrite Objective-C source to C++">, Group; def rewrite_legacy_objc : Flag<["-"], "rewrite-legacy-objc">, Flags<[DriverOption]>, HelpText<"Rewrite Legacy Objective-C source to C++">; def rdynamic : Flag<["-"], "rdynamic">; def resource_dir : Separate<["-"], "resource-dir">, Flags<[DriverOption, CC1Option, HelpHidden]>, HelpText<"The directory which holds the compiler resource files">; def resource_dir_EQ : Joined<["-"], "resource-dir=">, Flags<[DriverOption]>, Alias; def rpath : Separate<["-"], "rpath">, Flags<[LinkerInput]>; def rtlib_EQ : Joined<["-", "--"], "rtlib=">; def r : Flag<["-"], "r">; def save_temps : Flag<["-", "--"], "save-temps">, Flags<[DriverOption]>, HelpText<"Save intermediate compilation results">; def sectalign : MultiArg<["-"], "sectalign", 3>; def sectcreate : MultiArg<["-"], "sectcreate", 3>; def sectobjectsymbols : MultiArg<["-"], "sectobjectsymbols", 2>; def sectorder : MultiArg<["-"], "sectorder", 3>; def seg1addr : JoinedOrSeparate<["-"], "seg1addr">; def seg__addr__table__filename : Separate<["-"], "seg_addr_table_filename">; def seg__addr__table : Separate<["-"], "seg_addr_table">; def segaddr : MultiArg<["-"], "segaddr", 2>; def segcreate : MultiArg<["-"], "segcreate", 3>; def seglinkedit : Flag<["-"], "seglinkedit">; def segprot : MultiArg<["-"], "segprot", 3>; def segs__read__only__addr : Separate<["-"], "segs_read_only_addr">; def segs__read__write__addr : Separate<["-"], "segs_read_write_addr">; def segs__read__ : Joined<["-"], "segs_read_">; def shared_libgcc : Flag<["-"], "shared-libgcc">; def shared : Flag<["-", "--"], "shared">; def single__module : Flag<["-"], "single_module">; def specs_EQ : Joined<["-", "--"], "specs=">; def specs : Separate<["-", "--"], "specs">, Flags<[Unsupported]>; def static_libgcc : Flag<["-"], "static-libgcc">; def static_libstdcxx : Flag<["-"], "static-libstdc++">; def static : Flag<["-", "--"], "static">, Flags<[NoArgumentUnused]>; def std_default_EQ : Joined<["-"], "std-default=">; def std_EQ : Joined<["-", "--"], "std=">, Flags<[CC1Option]>, Group, HelpText<"Language standard to compile for">; def stdlib_EQ : Joined<["-", "--"], "stdlib=">, Flags<[CC1Option]>, HelpText<"C++ standard library to use">; def sub__library : JoinedOrSeparate<["-"], "sub_library">; def sub__umbrella : JoinedOrSeparate<["-"], "sub_umbrella">; def s : Flag<["-"], "s">; def target : Joined<["--"], "target=">, Flags<[DriverOption]>, HelpText<"Generate code for the given target">; def gcc_toolchain : Joined<["--"], "gcc-toolchain=">, Flags<[DriverOption]>, HelpText<"Use the gcc toolchain at the given directory">; def time : Flag<["-"], "time">, HelpText<"Time individual commands">; def traditional_cpp : Flag<["-", "--"], "traditional-cpp">, Flags<[CC1Option]>, HelpText<"Enable some traditional CPP emulation">; def traditional : Flag<["-", "--"], "traditional">; def trigraphs : Flag<["-", "--"], "trigraphs">, Flags<[CC1Option]>, HelpText<"Process trigraph sequences">; def twolevel__namespace__hints : Flag<["-"], "twolevel_namespace_hints">; def twolevel__namespace : Flag<["-"], "twolevel_namespace">; def t : Flag<["-"], "t">; def umbrella : Separate<["-"], "umbrella">; def undefined : JoinedOrSeparate<["-"], "undefined">, Group; def undef : Flag<["-"], "undef">, Group, Flags<[CC1Option]>, HelpText<"undef all system defines">; def unexported__symbols__list : Separate<["-"], "unexported_symbols_list">; def u : JoinedOrSeparate<["-"], "u">, Group; def v : Flag<["-"], "v">, Flags<[CC1Option]>, HelpText<"Show commands to run and use verbose output">; def verify : Flag<["-"], "verify">, Flags<[DriverOption,CC1Option]>, HelpText<"Verify output using a verifier">; def weak_l : Joined<["-"], "weak-l">, Flags<[LinkerInput]>; def weak__framework : Separate<["-"], "weak_framework">, Flags<[LinkerInput]>; def weak__library : Separate<["-"], "weak_library">, Flags<[LinkerInput]>; def weak__reference__mismatches : Separate<["-"], "weak_reference_mismatches">; def whatsloaded : Flag<["-"], "whatsloaded">; def whyload : Flag<["-"], "whyload">; def w : Flag<["-"], "w">, HelpText<"Suppress all warnings">, Flags<[CC1Option]>; def x : JoinedOrSeparate<["-"], "x">, Flags<[DriverOption,CC1Option]>, HelpText<"Treat subsequent input files as having type ">, MetaVarName<"">; def y : Joined<["-"], "y">; def working_directory : JoinedOrSeparate<["-"], "working-directory">, Flags<[CC1Option]>, HelpText<"Resolve file paths relative to the specified directory">; def working_directory_EQ : Joined<["-"], "working-directory=">, Flags<[CC1Option]>, Alias; // Double dash options, which are usually an alias for one of the previous // options. def _mhwdiv_EQ : Separate<["--"], "mhwdiv">, Alias; def _CLASSPATH_EQ : Joined<["--"], "CLASSPATH=">, Alias; def _CLASSPATH : Separate<["--"], "CLASSPATH">, Alias; def _all_warnings : Flag<["--"], "all-warnings">, Alias; def _analyze_auto : Flag<["--"], "analyze-auto">, Flags<[DriverOption]>; def _analyzer_no_default_checks : Flag<["--"], "analyzer-no-default-checks">, Flags<[DriverOption]>; def _analyzer_output : JoinedOrSeparate<["--"], "analyzer-output">, Flags<[DriverOption]>; def _analyze : Flag<["--"], "analyze">, Flags<[DriverOption]>, HelpText<"Run the static analyzer">; def _assemble : Flag<["--"], "assemble">, Alias; def _assert_EQ : Joined<["--"], "assert=">, Alias; def _assert : Separate<["--"], "assert">, Alias; def _bootclasspath_EQ : Joined<["--"], "bootclasspath=">, Alias; def _bootclasspath : Separate<["--"], "bootclasspath">, Alias; def _classpath_EQ : Joined<["--"], "classpath=">, Alias; def _classpath : Separate<["--"], "classpath">, Alias; def _comments_in_macros : Flag<["--"], "comments-in-macros">, Alias; def _comments : Flag<["--"], "comments">, Alias; def _compile : Flag<["--"], "compile">, Alias; def _constant_cfstrings : Flag<["--"], "constant-cfstrings">; def _debug_EQ : Joined<["--"], "debug=">, Alias; def _debug : Flag<["--"], "debug">, Alias; def _define_macro_EQ : Joined<["--"], "define-macro=">, Alias; def _define_macro : Separate<["--"], "define-macro">, Alias; def _dependencies : Flag<["--"], "dependencies">, Alias; def _dyld_prefix_EQ : Joined<["--"], "dyld-prefix=">; def _dyld_prefix : Separate<["--"], "dyld-prefix">, Alias<_dyld_prefix_EQ>; def _encoding_EQ : Joined<["--"], "encoding=">, Alias; def _encoding : Separate<["--"], "encoding">, Alias; def _entry : Flag<["--"], "entry">, Alias; def _extdirs_EQ : Joined<["--"], "extdirs=">, Alias; def _extdirs : Separate<["--"], "extdirs">, Alias; def _extra_warnings : Flag<["--"], "extra-warnings">, Alias; def _for_linker_EQ : Joined<["--"], "for-linker=">, Alias; def _for_linker : Separate<["--"], "for-linker">, Alias; def _force_link_EQ : Joined<["--"], "force-link=">, Alias; def _force_link : Separate<["--"], "force-link">, Alias; def _help_hidden : Flag<["--"], "help-hidden">; def _imacros_EQ : Joined<["--"], "imacros=">, Alias; def _include_barrier : Flag<["--"], "include-barrier">, Alias; def _include_directory_after_EQ : Joined<["--"], "include-directory-after=">, Alias; def _include_directory_after : Separate<["--"], "include-directory-after">, Alias; def _include_directory_EQ : Joined<["--"], "include-directory=">, Alias; def _include_directory : Separate<["--"], "include-directory">, Alias; def _include_prefix_EQ : Joined<["--"], "include-prefix=">, Alias; def _include_prefix : Separate<["--"], "include-prefix">, Alias; def _include_with_prefix_after_EQ : Joined<["--"], "include-with-prefix-after=">, Alias; def _include_with_prefix_after : Separate<["--"], "include-with-prefix-after">, Alias; def _include_with_prefix_before_EQ : Joined<["--"], "include-with-prefix-before=">, Alias; def _include_with_prefix_before : Separate<["--"], "include-with-prefix-before">, Alias; def _include_with_prefix_EQ : Joined<["--"], "include-with-prefix=">, Alias; def _include_with_prefix : Separate<["--"], "include-with-prefix">, Alias; def _include_EQ : Joined<["--"], "include=">, Alias; def _language_EQ : Joined<["--"], "language=">, Alias; def _language : Separate<["--"], "language">, Alias; def _library_directory_EQ : Joined<["--"], "library-directory=">, Alias; def _library_directory : Separate<["--"], "library-directory">, Alias; def _no_line_commands : Flag<["--"], "no-line-commands">, Alias

; def _resource_EQ : Joined<["--"], "resource=">, Alias; def _resource : Separate<["--"], "resource">, Alias; def _rtlib : Separate<["--"], "rtlib">, Alias; def _serialize_diags : Separate<["-", "--"], "serialize-diagnostics">, Flags<[DriverOption]>, HelpText<"Serialize compiler diagnostics to a file">; // We give --version different semantics from -version. def _version : Flag<["--"], "version">, Flags<[CC1Option]>; def _signed_char : Flag<["--"], "signed-char">, Alias; def _std : Separate<["--"], "std">, Alias; def _stdlib : Separate<["--"], "stdlib">, Alias; def _sysroot_EQ : Joined<["--"], "sysroot=">; def _sysroot : Separate<["--"], "sysroot">, Alias<_sysroot_EQ>; def _target_help : Flag<["--"], "target-help">; def _trace_includes : Flag<["--"], "trace-includes">, Alias; def _undefine_macro_EQ : Joined<["--"], "undefine-macro=">, Alias; def _undefine_macro : Separate<["--"], "undefine-macro">, Alias; def _unsigned_char : Flag<["--"], "unsigned-char">, Alias; def _user_dependencies : Flag<["--"], "user-dependencies">, Alias; def _verbose : Flag<["--"], "verbose">, Alias; def _warn__EQ : Joined<["--"], "warn-=">, Alias; def _warn_ : Joined<["--"], "warn-">, Alias; def _write_dependencies : Flag<["--"], "write-dependencies">, Alias; def _write_user_dependencies : Flag<["--"], "write-user-dependencies">, Alias; def _ : Joined<["--"], "">, Flags<[Unsupported]>; def mieee_rnd_near : Flag<["-"], "mieee-rnd-near">, Group; def mv1 : Flag<["-"], "mv1">, Group, Alias, AliasArgs<["v1"]>; def mv2 : Flag<["-"], "mv2">, Group, Alias, AliasArgs<["v2"]>; def mv3 : Flag<["-"], "mv3">, Group, Alias, AliasArgs<["v3"]>; def mv4 : Flag<["-"], "mv4">, Group, Alias, AliasArgs<["v4"]>; def mv5 : Flag<["-"], "mv5">, Group, Alias, AliasArgs<["v5"]>; // These are legacy user-facing driver-level option spellings. They are always // aliases for options that are spelled using the more common Unix / GNU flag // style of double-dash and equals-joined flags. def gcc_toolchain_legacy_spelling : Separate<["-"], "gcc-toolchain">, Alias; def target_legacy_spelling : Separate<["-"], "target">, Alias; // Special internal option to handle -Xlinker --no-demangle. def Z_Xlinker__no_demangle : Flag<["-"], "Z-Xlinker-no-demangle">, Flags<[Unsupported, NoArgumentUnused]>; // Special internal option to allow forwarding arbitrary arguments to linker. def Zlinker_input : Separate<["-"], "Zlinker-input">, Flags<[Unsupported, NoArgumentUnused]>; // Reserved library options. def Z_reserved_lib_stdcxx : Flag<["-"], "Z-reserved-lib-stdc++">, Flags<[LinkerInput, NoArgumentUnused, Unsupported]>, Group; def Z_reserved_lib_cckext : Flag<["-"], "Z-reserved-lib-cckext">, Flags<[LinkerInput, NoArgumentUnused, Unsupported]>, Group; // Ignored options // FIXME: multiclasess produce suffixes, not prefixes. This is fine for now // since it is only used in ignored options. multiclass BooleanFFlag { def _f : Flag<["-"], "f"#name>; def _fno : Flag<["-"], "fno-"#name>; } def fprofile_dir : Joined<["-"], "fprofile-dir=">, Group; defm profile_use : BooleanFFlag<"profile-use">, Group; def fprofile_use_EQ : Joined<["-"], "fprofile-use=">, Group; def fuse_ld_EQ : Joined<["-"], "fuse-ld=">, Group; defm align_functions : BooleanFFlag<"align-functions">, Group; def falign_functions_EQ : Joined<["-"], "falign-functions=">, Group; // FIXME: This option should be supported and wired up to our diognostics, but // ignore it for now to avoid breaking builds that use it. def fdiagnostics_show_location_EQ : Joined<["-"], "fdiagnostics-show-location=">, Group; defm eliminate_unused_debug_types : BooleanFFlag<"eliminate-unused-debug-types">, Group; defm float_store : BooleanFFlag<"float-store">, Group; defm function_attribute_list : BooleanFFlag<"function-attribute-list">, Group; defm gcse : BooleanFFlag<"gcse">, Group; defm gnu : BooleanFFlag<"gnu">, Group; defm ident : BooleanFFlag<"ident">, Group; defm implicit_templates : BooleanFFlag<"implicit-templates">, Group; defm inline_limit : BooleanFFlag<"inline-limit">, Group; defm ivopts : BooleanFFlag<"ivopts">, Group; defm non_call_exceptions : BooleanFFlag<"non-call-exceptions">, Group; defm permissive : BooleanFFlag<"permissive">, Group; defm prefetch_loop_arrays : BooleanFFlag<"prefetch-loop-arrays">, Group; defm printf : BooleanFFlag<"printf">, Group; defm profile : BooleanFFlag<"profile">, Group; defm profile_correction : BooleanFFlag<"profile-correction">, Group; defm profile_generate_sampling : BooleanFFlag<"profile-generate-sampling">, Group; defm profile_reusedist : BooleanFFlag<"profile-reusedist">, Group; defm profile_values : BooleanFFlag<"profile-values">, Group; defm regs_graph : BooleanFFlag<"regs-graph">, Group; defm ripa : BooleanFFlag<"ripa">, Group; defm rounding_math : BooleanFFlag<"rounding-math">, Group; defm schedule_insns : BooleanFFlag<"schedule-insns">, Group; defm see : BooleanFFlag<"see">, Group; defm signaling_nans : BooleanFFlag<"signaling-nans">, Group; defm spec_constr_count : BooleanFFlag<"spec-constr-count">, Group; defm strength_reduce : BooleanFFlag<"strength-reduce">, Group; defm tls_model : BooleanFFlag<"tls-model">, Group; defm tracer : BooleanFFlag<"tracer">, Group; defm tree_salias : BooleanFFlag<"tree-salias">, Group; defm tree_vectorizer_verbose : BooleanFFlag<"tree-vectorizer-verbose">, Group; defm unroll_all_loops : BooleanFFlag<"unroll-all-loops">, Group; defm unswitch_loops : BooleanFFlag<"unswitch-loops">, Group; // gfortran options that we recognize in the driver and pass along when // invoking GCC to compile Fortran code. def gfortran_Group : OptionGroup<"gfortran Group">; // Generic gfortran options. def A_DASH : Joined<["-"], "A-">, Group; def J : JoinedOrSeparate<["-"], "J">, Flags<[RenderJoined]>, Group; def cpp : Flag<["-"], "cpp">, Group; def nocpp : Flag<["-"], "nocpp">, Group; def static_libgfortran : Flag<["-"], "static-libgfortran">, Group; // "f" options with values for gfortran. def fblas_matmul_limit_EQ : Joined<["-"], "fblas-matmul-limit=">, Group; def fcheck_EQ : Joined<["-"], "fcheck=">, Group; def fcoarray_EQ : Joined<["-"], "fcoarray=">, Group; def fconvert_EQ : Joined<["-"], "fconvert=">, Group; def ffixed_line_length_VALUE : Joined<["-"], "ffixed-line-length-">, Group; def ffpe_trap_EQ : Joined<["-"], "ffpe-trap=">, Group; def ffree_line_length_VALUE : Joined<["-"], "ffree-line-length-">, Group; def finit_character_EQ : Joined<["-"], "finit-character=">, Group; def finit_integer_EQ : Joined<["-"], "finit-integer=">, Group; def finit_logical_EQ : Joined<["-"], "finit-logical=">, Group; def finit_real_EQ : Joined<["-"], "finit-real=">, Group; def fmax_array_constructor_EQ : Joined<["-"], "fmax-array-constructor=">, Group; def fmax_errors_EQ : Joined<["-"], "fmax-errors=">, Group; def fmax_stack_var_size_EQ : Joined<["-"], "fmax-stack-var-size=">, Group; def fmax_subrecord_length_EQ : Joined<["-"], "fmax-subrecord-length=">, Group; def frecord_marker_EQ : Joined<["-"], "frecord-marker=">, Group; // "f" flags for gfortran. defm aggressive_function_elimination : BooleanFFlag<"aggressive-function-elimination">, Group; defm align_commons : BooleanFFlag<"align-commons">, Group; defm all_intrinsics : BooleanFFlag<"all-intrinsics">, Group; defm automatic : BooleanFFlag<"automatic">, Group; defm backslash : BooleanFFlag<"backslash">, Group; defm backtrace : BooleanFFlag<"backtrace">, Group; defm bounds_check : BooleanFFlag<"bounds-check">, Group; defm check_array_temporaries : BooleanFFlag<"check-array-temporaries">, Group; defm cray_pointer : BooleanFFlag<"cray-pointer">, Group; defm d_lines_as_code : BooleanFFlag<"d-lines-as-code">, Group; defm d_lines_as_comments : BooleanFFlag<"d-lines-as-comments">, Group; defm default_double_8 : BooleanFFlag<"default-double-8">, Group; defm default_integer_8 : BooleanFFlag<"default-integer-8">, Group; defm default_real_8 : BooleanFFlag<"default-real-8">, Group; defm dollar_ok : BooleanFFlag<"dollar-ok">, Group; defm dump_fortran_optimized : BooleanFFlag<"dump-fortran-optimized">, Group; defm dump_fortran_original : BooleanFFlag<"dump-fortran-original">, Group; defm dump_parse_tree : BooleanFFlag<"dump-parse-tree">, Group; defm external_blas : BooleanFFlag<"external-blas">, Group; defm f2c : BooleanFFlag<"f2c">, Group; defm fixed_form : BooleanFFlag<"fixed-form">, Group; defm free_form : BooleanFFlag<"free-form">, Group; defm frontend_optimize : BooleanFFlag<"frontend-optimize">, Group; defm implicit_none : BooleanFFlag<"implicit-none">, Group; defm init_local_zero : BooleanFFlag<"init-local-zero">, Group; defm integer_4_integer_8 : BooleanFFlag<"integer-4-integer-8">, Group; defm intrinsic_modules_path : BooleanFFlag<"intrinsic-modules-path">, Group; defm max_identifier_length : BooleanFFlag<"max-identifier-length">, Group; defm module_private : BooleanFFlag<"module-private">, Group; defm pack_derived : BooleanFFlag<"pack-derived">, Group; defm protect_parens : BooleanFFlag<"protect-parens">, Group; defm range_check : BooleanFFlag<"range-check">, Group; defm real_4_real_10 : BooleanFFlag<"real-4-real-10">, Group; defm real_4_real_16 : BooleanFFlag<"real-4-real-16">, Group; defm real_4_real_8 : BooleanFFlag<"real-4-real-8">, Group; defm real_8_real_10 : BooleanFFlag<"real-8-real-10">, Group; defm real_8_real_16 : BooleanFFlag<"real-8-real-16">, Group; defm real_8_real_4 : BooleanFFlag<"real-8-real-4">, Group; defm realloc_lhs : BooleanFFlag<"realloc-lhs">, Group; defm recursive : BooleanFFlag<"recursive">, Group; defm repack_arrays : BooleanFFlag<"repack-arrays">, Group; defm second_underscore : BooleanFFlag<"second-underscore">, Group; defm sign_zero : BooleanFFlag<"sign-zero">, Group; defm stack_arrays : BooleanFFlag<"stack-arrays">, Group; defm underscoring : BooleanFFlag<"underscoring">, Group; defm whole_file : BooleanFFlag<"whole-file">, Group; include "CC1Options.td" include "CLCompatOptions.td" Index: stable/9/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h =================================================================== --- stable/9/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h (revision 283018) +++ stable/9/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h (revision 283019) @@ -1,158 +1,166 @@ //===--- CodeGenOptions.h ---------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines the CodeGenOptions interface. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_FRONTEND_CODEGENOPTIONS_H #define LLVM_CLANG_FRONTEND_CODEGENOPTIONS_H #include #include namespace clang { /// \brief Bitfields of CodeGenOptions, split out from CodeGenOptions to ensure /// that this large collection of bitfields is a trivial class type. class CodeGenOptionsBase { public: #define CODEGENOPT(Name, Bits, Default) unsigned Name : Bits; #define ENUM_CODEGENOPT(Name, Type, Bits, Default) #include "clang/Frontend/CodeGenOptions.def" protected: #define CODEGENOPT(Name, Bits, Default) #define ENUM_CODEGENOPT(Name, Type, Bits, Default) unsigned Name : Bits; #include "clang/Frontend/CodeGenOptions.def" }; /// CodeGenOptions - Track various options which control how the code /// is optimized and passed to the backend. class CodeGenOptions : public CodeGenOptionsBase { public: enum InliningMethod { NoInlining, // Perform no inlining whatsoever. NormalInlining, // Use the standard function inlining pass. OnlyAlwaysInlining // Only run the always inlining pass. }; enum ObjCDispatchMethodKind { Legacy = 0, NonLegacy = 1, Mixed = 2 }; enum DebugInfoKind { - NoDebugInfo, // Don't generate debug info. - DebugLineTablesOnly, // Emit only debug info necessary for generating - // line number tables (-gline-tables-only). - LimitedDebugInfo, // Limit generated debug info to reduce size - // (-flimit-debug-info). - FullDebugInfo // Generate complete debug info. + NoDebugInfo, /// Don't generate debug info. + + DebugLineTablesOnly, /// Emit only debug info necessary for generating + /// line number tables (-gline-tables-only). + + LimitedDebugInfo, /// Limit generated debug info to reduce size + /// (-fno-standalone-debug). This emits + /// forward decls for types that could be + /// replaced with forward decls in the source + /// code. For dynamic C++ classes type info + /// is only emitted int the module that + /// contains the classe's vtable. + + FullDebugInfo /// Generate complete debug info. }; enum TLSModel { GeneralDynamicTLSModel, LocalDynamicTLSModel, InitialExecTLSModel, LocalExecTLSModel }; enum FPContractModeKind { FPC_Off, // Form fused FP ops only where result will not be affected. FPC_On, // Form fused FP ops according to FP_CONTRACT rules. FPC_Fast // Aggressively fuse FP ops (E.g. FMA). }; enum StructReturnConventionKind { SRCK_Default, // No special option was passed. SRCK_OnStack, // Small structs on the stack (-fpcc-struct-return). SRCK_InRegs // Small structs in registers (-freg-struct-return). }; /// The code model to use (-mcmodel). std::string CodeModel; /// The filename with path we use for coverage files. The extension will be /// replaced. std::string CoverageFile; /// The version string to put into coverage files. char CoverageVersion[4]; /// Enable additional debugging information. std::string DebugPass; /// The string to embed in debug information as the current working directory. std::string DebugCompilationDir; /// The string to embed in the debug information for the compile unit, if /// non-empty. std::string DwarfDebugFlags; /// The ABI to use for passing floating point arguments. std::string FloatABI; /// The float precision limit to use, if non-empty. std::string LimitFloatPrecision; /// The name of the bitcode file to link before optzns. std::string LinkBitcodeFile; /// The user provided name for the "main file", if non-empty. This is useful /// in situations where the input file name does not match the original input /// file, for example with -save-temps. std::string MainFileName; /// The name for the split debug info file that we'll break out. This is used /// in the backend for setting the name in the skeleton cu. std::string SplitDwarfFile; /// The name of the relocation model to use. std::string RelocationModel; /// Path to blacklist file for sanitizers. std::string SanitizerBlacklistFile; /// If not an empty string, trap intrinsics are lowered to calls to this /// function instead of to trap instructions. std::string TrapFuncName; /// A list of command-line options to forward to the LLVM backend. std::vector BackendOptions; /// A list of dependent libraries. std::vector DependentLibraries; /// Name of the profile file to use with -fprofile-sample-use. std::string SampleProfileFile; public: // Define accessors/mutators for code generation options of enumeration type. #define CODEGENOPT(Name, Bits, Default) #define ENUM_CODEGENOPT(Name, Type, Bits, Default) \ Type get##Name() const { return static_cast(Name); } \ void set##Name(Type Value) { Name = static_cast(Value); } #include "clang/Frontend/CodeGenOptions.def" CodeGenOptions() { #define CODEGENOPT(Name, Bits, Default) Name = Default; #define ENUM_CODEGENOPT(Name, Type, Bits, Default) \ set##Name(Default); #include "clang/Frontend/CodeGenOptions.def" RelocationModel = "pic"; memcpy(CoverageVersion, "402*", 4); } }; } // end namespace clang #endif Index: stable/9/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp =================================================================== --- stable/9/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp (revision 283018) +++ stable/9/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp (revision 283019) @@ -1,3278 +1,3294 @@ //===--- CGDebugInfo.cpp - Emit Debug Information for a Module ------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This coordinates the debug information generation while generating code. // //===----------------------------------------------------------------------===// #include "CGDebugInfo.h" #include "CGBlocks.h" #include "CGCXXABI.h" #include "CGObjCRuntime.h" #include "CodeGenFunction.h" #include "CodeGenModule.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/RecordLayout.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/Version.h" #include "clang/Frontend/CodeGenOptions.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/Module.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/FileSystem.h" -#include "llvm/Support/Path.h" +#include "llvm/Support/Path.h" using namespace clang; using namespace clang::CodeGen; CGDebugInfo::CGDebugInfo(CodeGenModule &CGM) : CGM(CGM), DebugKind(CGM.getCodeGenOpts().getDebugInfo()), DBuilder(CGM.getModule()) { CreateCompileUnit(); } CGDebugInfo::~CGDebugInfo() { assert(LexicalBlockStack.empty() && "Region stack mismatch, stack not empty!"); } NoLocation::NoLocation(CodeGenFunction &CGF, CGBuilderTy &B) : DI(CGF.getDebugInfo()), Builder(B) { if (DI) { SavedLoc = DI->getLocation(); DI->CurLoc = SourceLocation(); Builder.SetCurrentDebugLocation(llvm::DebugLoc()); } } NoLocation::~NoLocation() { if (DI) { assert(Builder.getCurrentDebugLocation().isUnknown()); DI->CurLoc = SavedLoc; } } ArtificialLocation::ArtificialLocation(CodeGenFunction &CGF, CGBuilderTy &B) : DI(CGF.getDebugInfo()), Builder(B) { if (DI) { SavedLoc = DI->getLocation(); DI->CurLoc = SourceLocation(); Builder.SetCurrentDebugLocation(llvm::DebugLoc()); } } void ArtificialLocation::Emit() { if (DI) { // Sync the Builder. DI->EmitLocation(Builder, SavedLoc); DI->CurLoc = SourceLocation(); // Construct a location that has a valid scope, but no line info. assert(!DI->LexicalBlockStack.empty()); llvm::DIDescriptor Scope(DI->LexicalBlockStack.back()); Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(0, 0, Scope)); } } ArtificialLocation::~ArtificialLocation() { if (DI) { assert(Builder.getCurrentDebugLocation().getLine() == 0); DI->CurLoc = SavedLoc; } } void CGDebugInfo::setLocation(SourceLocation Loc) { // If the new location isn't valid return. if (Loc.isInvalid()) return; CurLoc = CGM.getContext().getSourceManager().getExpansionLoc(Loc); // If we've changed files in the middle of a lexical scope go ahead // and create a new lexical scope with file node if it's different // from the one in the scope. if (LexicalBlockStack.empty()) return; SourceManager &SM = CGM.getContext().getSourceManager(); PresumedLoc PCLoc = SM.getPresumedLoc(CurLoc); PresumedLoc PPLoc = SM.getPresumedLoc(PrevLoc); if (PCLoc.isInvalid() || PPLoc.isInvalid() || !strcmp(PPLoc.getFilename(), PCLoc.getFilename())) return; llvm::MDNode *LB = LexicalBlockStack.back(); llvm::DIScope Scope = llvm::DIScope(LB); if (Scope.isLexicalBlockFile()) { llvm::DILexicalBlockFile LBF = llvm::DILexicalBlockFile(LB); llvm::DIDescriptor D = DBuilder.createLexicalBlockFile(LBF.getScope(), getOrCreateFile(CurLoc)); llvm::MDNode *N = D; LexicalBlockStack.pop_back(); LexicalBlockStack.push_back(N); } else if (Scope.isLexicalBlock() || Scope.isSubprogram()) { llvm::DIDescriptor D = DBuilder.createLexicalBlockFile(Scope, getOrCreateFile(CurLoc)); llvm::MDNode *N = D; LexicalBlockStack.pop_back(); LexicalBlockStack.push_back(N); } } /// getContextDescriptor - Get context info for the decl. llvm::DIScope CGDebugInfo::getContextDescriptor(const Decl *Context) { if (!Context) return TheCU; llvm::DenseMap::iterator I = RegionMap.find(Context); if (I != RegionMap.end()) { llvm::Value *V = I->second; return llvm::DIScope(dyn_cast_or_null(V)); } // Check namespace. if (const NamespaceDecl *NSDecl = dyn_cast(Context)) return getOrCreateNameSpace(NSDecl); if (const RecordDecl *RDecl = dyn_cast(Context)) if (!RDecl->isDependentType()) return getOrCreateType(CGM.getContext().getTypeDeclType(RDecl), getOrCreateMainFile()); return TheCU; } /// getFunctionName - Get function name for the given FunctionDecl. If the /// name is constructed on demand (e.g. C++ destructor) then the name /// is stored on the side. StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) { assert (FD && "Invalid FunctionDecl!"); IdentifierInfo *FII = FD->getIdentifier(); FunctionTemplateSpecializationInfo *Info = FD->getTemplateSpecializationInfo(); if (!Info && FII) return FII->getName(); // Otherwise construct human readable name for debug info. SmallString<128> NS; llvm::raw_svector_ostream OS(NS); FD->printName(OS); // Add any template specialization args. if (Info) { const TemplateArgumentList *TArgs = Info->TemplateArguments; const TemplateArgument *Args = TArgs->data(); unsigned NumArgs = TArgs->size(); PrintingPolicy Policy(CGM.getLangOpts()); TemplateSpecializationType::PrintTemplateArgumentList(OS, Args, NumArgs, Policy); } // Copy this name on the side and use its reference. return internString(OS.str()); } StringRef CGDebugInfo::getObjCMethodName(const ObjCMethodDecl *OMD) { SmallString<256> MethodName; llvm::raw_svector_ostream OS(MethodName); OS << (OMD->isInstanceMethod() ? '-' : '+') << '['; const DeclContext *DC = OMD->getDeclContext(); if (const ObjCImplementationDecl *OID = dyn_cast(DC)) { OS << OID->getName(); } else if (const ObjCInterfaceDecl *OID = dyn_cast(DC)) { OS << OID->getName(); } else if (const ObjCCategoryImplDecl *OCD = dyn_cast(DC)){ OS << ((const NamedDecl *)OCD)->getIdentifier()->getNameStart() << '(' << OCD->getIdentifier()->getNameStart() << ')'; } else if (isa(DC)) { // We can extract the type of the class from the self pointer. if (ImplicitParamDecl* SelfDecl = OMD->getSelfDecl()) { QualType ClassTy = cast(SelfDecl->getType())->getPointeeType(); ClassTy.print(OS, PrintingPolicy(LangOptions())); } } OS << ' ' << OMD->getSelector().getAsString() << ']'; return internString(OS.str()); } /// getSelectorName - Return selector name. This is used for debugging /// info. StringRef CGDebugInfo::getSelectorName(Selector S) { return internString(S.getAsString()); } /// getClassName - Get class name including template argument list. StringRef CGDebugInfo::getClassName(const RecordDecl *RD) { const ClassTemplateSpecializationDecl *Spec = dyn_cast(RD); if (!Spec) return RD->getName(); const TemplateArgument *Args; unsigned NumArgs; if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) { const TemplateSpecializationType *TST = cast(TAW->getType()); Args = TST->getArgs(); NumArgs = TST->getNumArgs(); } else { const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); Args = TemplateArgs.data(); NumArgs = TemplateArgs.size(); } StringRef Name = RD->getIdentifier()->getName(); PrintingPolicy Policy(CGM.getLangOpts()); SmallString<128> TemplateArgList; { llvm::raw_svector_ostream OS(TemplateArgList); TemplateSpecializationType::PrintTemplateArgumentList(OS, Args, NumArgs, Policy); } // Copy this name on the side and use its reference. return internString(Name, TemplateArgList); } /// getOrCreateFile - Get the file debug info descriptor for the input location. llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) { if (!Loc.isValid()) // If Location is not valid then use main input file. return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory()); SourceManager &SM = CGM.getContext().getSourceManager(); PresumedLoc PLoc = SM.getPresumedLoc(Loc); if (PLoc.isInvalid() || StringRef(PLoc.getFilename()).empty()) // If the location is not valid then use main input file. return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory()); // Cache the results. const char *fname = PLoc.getFilename(); llvm::DenseMap::iterator it = DIFileCache.find(fname); if (it != DIFileCache.end()) { // Verify that the information still exists. if (llvm::Value *V = it->second) return llvm::DIFile(cast(V)); } llvm::DIFile F = DBuilder.createFile(PLoc.getFilename(), getCurrentDirname()); DIFileCache[fname] = F; return F; } /// getOrCreateMainFile - Get the file info for main compile unit. llvm::DIFile CGDebugInfo::getOrCreateMainFile() { return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory()); } /// getLineNumber - Get line number for the location. If location is invalid /// then use current location. unsigned CGDebugInfo::getLineNumber(SourceLocation Loc) { if (Loc.isInvalid() && CurLoc.isInvalid()) return 0; SourceManager &SM = CGM.getContext().getSourceManager(); PresumedLoc PLoc = SM.getPresumedLoc(Loc.isValid() ? Loc : CurLoc); return PLoc.isValid()? PLoc.getLine() : 0; } /// getColumnNumber - Get column number for the location. unsigned CGDebugInfo::getColumnNumber(SourceLocation Loc, bool Force) { // We may not want column information at all. if (!Force && !CGM.getCodeGenOpts().DebugColumnInfo) return 0; // If the location is invalid then use the current column. if (Loc.isInvalid() && CurLoc.isInvalid()) return 0; SourceManager &SM = CGM.getContext().getSourceManager(); PresumedLoc PLoc = SM.getPresumedLoc(Loc.isValid() ? Loc : CurLoc); return PLoc.isValid()? PLoc.getColumn() : 0; } StringRef CGDebugInfo::getCurrentDirname() { if (!CGM.getCodeGenOpts().DebugCompilationDir.empty()) return CGM.getCodeGenOpts().DebugCompilationDir; if (!CWDName.empty()) return CWDName; SmallString<256> CWD; llvm::sys::fs::current_path(CWD); return CWDName = internString(CWD); } /// CreateCompileUnit - Create new compile unit. void CGDebugInfo::CreateCompileUnit() { // Get absolute path name. SourceManager &SM = CGM.getContext().getSourceManager(); std::string MainFileName = CGM.getCodeGenOpts().MainFileName; if (MainFileName.empty()) MainFileName = ""; // The main file name provided via the "-main-file-name" option contains just // the file name itself with no path information. This file name may have had // a relative path, so we look into the actual file entry for the main // file to determine the real absolute path for the file. std::string MainFileDir; if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) { MainFileDir = MainFile->getDir()->getName(); if (MainFileDir != ".") { - llvm::SmallString<1024> MainFileDirSS(MainFileDir); - llvm::sys::path::append(MainFileDirSS, MainFileName); - MainFileName = MainFileDirSS.str(); + llvm::SmallString<1024> MainFileDirSS(MainFileDir); + llvm::sys::path::append(MainFileDirSS, MainFileName); + MainFileName = MainFileDirSS.str(); } } // Save filename string. StringRef Filename = internString(MainFileName); // Save split dwarf file string. std::string SplitDwarfFile = CGM.getCodeGenOpts().SplitDwarfFile; StringRef SplitDwarfFilename = internString(SplitDwarfFile); unsigned LangTag; const LangOptions &LO = CGM.getLangOpts(); if (LO.CPlusPlus) { if (LO.ObjC1) LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus; else LangTag = llvm::dwarf::DW_LANG_C_plus_plus; } else if (LO.ObjC1) { LangTag = llvm::dwarf::DW_LANG_ObjC; } else if (LO.C99) { LangTag = llvm::dwarf::DW_LANG_C99; } else { LangTag = llvm::dwarf::DW_LANG_C89; } std::string Producer = getClangFullVersion(); // Figure out which version of the ObjC runtime we have. unsigned RuntimeVers = 0; if (LO.ObjC1) RuntimeVers = LO.ObjCRuntime.isNonFragile() ? 2 : 1; // Create new compile unit. // FIXME - Eliminate TheCU. TheCU = DBuilder.createCompileUnit(LangTag, Filename, getCurrentDirname(), Producer, LO.Optimize, CGM.getCodeGenOpts().DwarfDebugFlags, RuntimeVers, SplitDwarfFilename); } /// CreateType - Get the Basic type from the cache or create a new /// one if necessary. llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) { unsigned Encoding = 0; StringRef BTName; switch (BT->getKind()) { #define BUILTIN_TYPE(Id, SingletonId) #define PLACEHOLDER_TYPE(Id, SingletonId) \ case BuiltinType::Id: #include "clang/AST/BuiltinTypes.def" case BuiltinType::Dependent: llvm_unreachable("Unexpected builtin type"); case BuiltinType::NullPtr: return DBuilder.createNullPtrType(); case BuiltinType::Void: return llvm::DIType(); case BuiltinType::ObjCClass: if (ClassTy) return ClassTy; ClassTy = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, "objc_class", TheCU, getOrCreateMainFile(), 0); return ClassTy; case BuiltinType::ObjCId: { // typedef struct objc_class *Class; // typedef struct objc_object { // Class isa; // } *id; if (ObjTy) return ObjTy; if (!ClassTy) ClassTy = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, "objc_class", TheCU, getOrCreateMainFile(), 0); unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy); llvm::DIType ISATy = DBuilder.createPointerType(ClassTy, Size); ObjTy = DBuilder.createStructType(TheCU, "objc_object", getOrCreateMainFile(), 0, 0, 0, 0, llvm::DIType(), llvm::DIArray()); ObjTy.setTypeArray(DBuilder.getOrCreateArray(&*DBuilder.createMemberType( ObjTy, "isa", getOrCreateMainFile(), 0, Size, 0, 0, 0, ISATy))); return ObjTy; } case BuiltinType::ObjCSel: { if (SelTy) return SelTy; SelTy = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, "objc_selector", TheCU, getOrCreateMainFile(), 0); return SelTy; } case BuiltinType::OCLImage1d: return getOrCreateStructPtrType("opencl_image1d_t", OCLImage1dDITy); case BuiltinType::OCLImage1dArray: return getOrCreateStructPtrType("opencl_image1d_array_t", OCLImage1dArrayDITy); case BuiltinType::OCLImage1dBuffer: return getOrCreateStructPtrType("opencl_image1d_buffer_t", OCLImage1dBufferDITy); case BuiltinType::OCLImage2d: return getOrCreateStructPtrType("opencl_image2d_t", OCLImage2dDITy); case BuiltinType::OCLImage2dArray: return getOrCreateStructPtrType("opencl_image2d_array_t", OCLImage2dArrayDITy); case BuiltinType::OCLImage3d: return getOrCreateStructPtrType("opencl_image3d_t", OCLImage3dDITy); case BuiltinType::OCLSampler: return DBuilder.createBasicType("opencl_sampler_t", CGM.getContext().getTypeSize(BT), CGM.getContext().getTypeAlign(BT), llvm::dwarf::DW_ATE_unsigned); case BuiltinType::OCLEvent: return getOrCreateStructPtrType("opencl_event_t", OCLEventDITy); case BuiltinType::UChar: case BuiltinType::Char_U: Encoding = llvm::dwarf::DW_ATE_unsigned_char; break; case BuiltinType::Char_S: case BuiltinType::SChar: Encoding = llvm::dwarf::DW_ATE_signed_char; break; case BuiltinType::Char16: case BuiltinType::Char32: Encoding = llvm::dwarf::DW_ATE_UTF; break; case BuiltinType::UShort: case BuiltinType::UInt: case BuiltinType::UInt128: case BuiltinType::ULong: case BuiltinType::WChar_U: case BuiltinType::ULongLong: Encoding = llvm::dwarf::DW_ATE_unsigned; break; case BuiltinType::Short: case BuiltinType::Int: case BuiltinType::Int128: case BuiltinType::Long: case BuiltinType::WChar_S: case BuiltinType::LongLong: Encoding = llvm::dwarf::DW_ATE_signed; break; case BuiltinType::Bool: Encoding = llvm::dwarf::DW_ATE_boolean; break; case BuiltinType::Half: case BuiltinType::Float: case BuiltinType::LongDouble: case BuiltinType::Double: Encoding = llvm::dwarf::DW_ATE_float; break; } switch (BT->getKind()) { case BuiltinType::Long: BTName = "long int"; break; case BuiltinType::LongLong: BTName = "long long int"; break; case BuiltinType::ULong: BTName = "long unsigned int"; break; case BuiltinType::ULongLong: BTName = "long long unsigned int"; break; default: BTName = BT->getName(CGM.getLangOpts()); break; } // Bit size, align and offset of the type. uint64_t Size = CGM.getContext().getTypeSize(BT); uint64_t Align = CGM.getContext().getTypeAlign(BT); llvm::DIType DbgTy = DBuilder.createBasicType(BTName, Size, Align, Encoding); return DbgTy; } llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty) { // Bit size, align and offset of the type. unsigned Encoding = llvm::dwarf::DW_ATE_complex_float; if (Ty->isComplexIntegerType()) Encoding = llvm::dwarf::DW_ATE_lo_user; uint64_t Size = CGM.getContext().getTypeSize(Ty); uint64_t Align = CGM.getContext().getTypeAlign(Ty); llvm::DIType DbgTy = DBuilder.createBasicType("complex", Size, Align, Encoding); return DbgTy; } /// CreateCVRType - Get the qualified type from the cache or create /// a new one if necessary. llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile Unit) { QualifierCollector Qc; const Type *T = Qc.strip(Ty); // Ignore these qualifiers for now. Qc.removeObjCGCAttr(); Qc.removeAddressSpace(); Qc.removeObjCLifetime(); // We will create one Derived type for one qualifier and recurse to handle any // additional ones. unsigned Tag; if (Qc.hasConst()) { Tag = llvm::dwarf::DW_TAG_const_type; Qc.removeConst(); } else if (Qc.hasVolatile()) { Tag = llvm::dwarf::DW_TAG_volatile_type; Qc.removeVolatile(); } else if (Qc.hasRestrict()) { Tag = llvm::dwarf::DW_TAG_restrict_type; Qc.removeRestrict(); } else { assert(Qc.empty() && "Unknown type qualifier for debug info"); return getOrCreateType(QualType(T, 0), Unit); } llvm::DIType FromTy = getOrCreateType(Qc.apply(CGM.getContext(), T), Unit); // No need to fill in the Name, Line, Size, Alignment, Offset in case of // CVR derived types. llvm::DIType DbgTy = DBuilder.createQualifiedType(Tag, FromTy); return DbgTy; } llvm::DIType CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty, llvm::DIFile Unit) { // The frontend treats 'id' as a typedef to an ObjCObjectType, // whereas 'id' is treated as an ObjCPointerType. For the // debug info, we want to emit 'id' in both cases. if (Ty->isObjCQualifiedIdType()) return getOrCreateType(CGM.getContext().getObjCIdType(), Unit); llvm::DIType DbgTy = CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty, Ty->getPointeeType(), Unit); return DbgTy; } llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty, llvm::DIFile Unit) { return CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty, Ty->getPointeeType(), Unit); } /// In C++ mode, types have linkage, so we can rely on the ODR and /// on their mangled names, if they're external. static SmallString<256> getUniqueTagTypeName(const TagType *Ty, CodeGenModule &CGM, llvm::DICompileUnit TheCU) { SmallString<256> FullName; // FIXME: ODR should apply to ObjC++ exactly the same wasy it does to C++. // For now, only apply ODR with C++. const TagDecl *TD = Ty->getDecl(); if (TheCU.getLanguage() != llvm::dwarf::DW_LANG_C_plus_plus || !TD->isExternallyVisible()) return FullName; // Microsoft Mangler does not have support for mangleCXXRTTIName yet. if (CGM.getTarget().getCXXABI().isMicrosoft()) return FullName; // TODO: This is using the RTTI name. Is there a better way to get // a unique string for a type? llvm::raw_svector_ostream Out(FullName); CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(QualType(Ty, 0), Out); Out.flush(); return FullName; } // Creates a forward declaration for a RecordDecl in the given context. llvm::DICompositeType CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty, llvm::DIDescriptor Ctx) { const RecordDecl *RD = Ty->getDecl(); if (llvm::DIType T = getTypeOrNull(CGM.getContext().getRecordType(RD))) return llvm::DICompositeType(T); llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation()); unsigned Line = getLineNumber(RD->getLocation()); StringRef RDName = getClassName(RD); unsigned Tag = 0; if (RD->isStruct() || RD->isInterface()) Tag = llvm::dwarf::DW_TAG_structure_type; else if (RD->isUnion()) Tag = llvm::dwarf::DW_TAG_union_type; else { assert(RD->isClass()); Tag = llvm::dwarf::DW_TAG_class_type; } // Create the type. SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU); return DBuilder.createForwardDecl(Tag, RDName, Ctx, DefUnit, Line, 0, 0, 0, FullName); } llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag, const Type *Ty, QualType PointeeTy, llvm::DIFile Unit) { if (Tag == llvm::dwarf::DW_TAG_reference_type || Tag == llvm::dwarf::DW_TAG_rvalue_reference_type) return DBuilder.createReferenceType(Tag, getOrCreateType(PointeeTy, Unit)); // Bit size, align and offset of the type. // Size is always the size of a pointer. We can't use getTypeSize here // because that does not return the correct value for references. unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy); uint64_t Size = CGM.getTarget().getPointerWidth(AS); uint64_t Align = CGM.getContext().getTypeAlign(Ty); return DBuilder.createPointerType(getOrCreateType(PointeeTy, Unit), Size, Align); } llvm::DIType CGDebugInfo::getOrCreateStructPtrType(StringRef Name, llvm::DIType &Cache) { if (Cache) return Cache; Cache = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, Name, TheCU, getOrCreateMainFile(), 0); unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy); Cache = DBuilder.createPointerType(Cache, Size); return Cache; } llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, llvm::DIFile Unit) { if (BlockLiteralGeneric) return BlockLiteralGeneric; SmallVector EltTys; llvm::DIType FieldTy; QualType FType; uint64_t FieldSize, FieldOffset; unsigned FieldAlign; llvm::DIArray Elements; llvm::DIType EltTy, DescTy; FieldOffset = 0; FType = CGM.getContext().UnsignedLongTy; EltTys.push_back(CreateMemberType(Unit, FType, "reserved", &FieldOffset)); EltTys.push_back(CreateMemberType(Unit, FType, "Size", &FieldOffset)); Elements = DBuilder.getOrCreateArray(EltTys); EltTys.clear(); unsigned Flags = llvm::DIDescriptor::FlagAppleBlock; unsigned LineNo = getLineNumber(CurLoc); EltTy = DBuilder.createStructType(Unit, "__block_descriptor", Unit, LineNo, FieldOffset, 0, Flags, llvm::DIType(), Elements); // Bit size, align and offset of the type. uint64_t Size = CGM.getContext().getTypeSize(Ty); DescTy = DBuilder.createPointerType(EltTy, Size); FieldOffset = 0; FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy); EltTys.push_back(CreateMemberType(Unit, FType, "__isa", &FieldOffset)); FType = CGM.getContext().IntTy; EltTys.push_back(CreateMemberType(Unit, FType, "__flags", &FieldOffset)); EltTys.push_back(CreateMemberType(Unit, FType, "__reserved", &FieldOffset)); FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy); EltTys.push_back(CreateMemberType(Unit, FType, "__FuncPtr", &FieldOffset)); FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy); FieldTy = DescTy; FieldSize = CGM.getContext().getTypeSize(Ty); FieldAlign = CGM.getContext().getTypeAlign(Ty); FieldTy = DBuilder.createMemberType(Unit, "__descriptor", Unit, LineNo, FieldSize, FieldAlign, FieldOffset, 0, FieldTy); EltTys.push_back(FieldTy); FieldOffset += FieldSize; Elements = DBuilder.getOrCreateArray(EltTys); EltTy = DBuilder.createStructType(Unit, "__block_literal_generic", Unit, LineNo, FieldOffset, 0, Flags, llvm::DIType(), Elements); BlockLiteralGeneric = DBuilder.createPointerType(EltTy, Size); return BlockLiteralGeneric; } llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty, llvm::DIFile Unit) { // Typedefs are derived from some other type. If we have a typedef of a // typedef, make sure to emit the whole chain. llvm::DIType Src = getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit); if (!Src) return llvm::DIType(); // We don't set size information, but do specify where the typedef was // declared. unsigned Line = getLineNumber(Ty->getDecl()->getLocation()); const TypedefNameDecl *TyDecl = Ty->getDecl(); llvm::DIDescriptor TypedefContext = getContextDescriptor(cast(Ty->getDecl()->getDeclContext())); return DBuilder.createTypedef(Src, TyDecl->getName(), Unit, Line, TypedefContext); } llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty, llvm::DIFile Unit) { SmallVector EltTys; // Add the result type at least. EltTys.push_back(getOrCreateType(Ty->getResultType(), Unit)); // Set up remainder of arguments if there is a prototype. // FIXME: IF NOT, HOW IS THIS REPRESENTED? llvm-gcc doesn't represent '...'! if (isa(Ty)) EltTys.push_back(DBuilder.createUnspecifiedParameter()); else if (const FunctionProtoType *FPT = dyn_cast(Ty)) { for (unsigned i = 0, e = FPT->getNumArgs(); i != e; ++i) EltTys.push_back(getOrCreateType(FPT->getArgType(i), Unit)); + if (FPT->isVariadic()) + EltTys.push_back(DBuilder.createUnspecifiedParameter()); } llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(EltTys); return DBuilder.createSubroutineType(Unit, EltTypeArray); } llvm::DIType CGDebugInfo::createFieldType(StringRef name, QualType type, uint64_t sizeInBitsOverride, SourceLocation loc, AccessSpecifier AS, uint64_t offsetInBits, llvm::DIFile tunit, llvm::DIScope scope) { llvm::DIType debugType = getOrCreateType(type, tunit); // Get the location for the field. llvm::DIFile file = getOrCreateFile(loc); unsigned line = getLineNumber(loc); uint64_t sizeInBits = 0; unsigned alignInBits = 0; if (!type->isIncompleteArrayType()) { llvm::tie(sizeInBits, alignInBits) = CGM.getContext().getTypeInfo(type); if (sizeInBitsOverride) sizeInBits = sizeInBitsOverride; } unsigned flags = 0; if (AS == clang::AS_private) flags |= llvm::DIDescriptor::FlagPrivate; else if (AS == clang::AS_protected) flags |= llvm::DIDescriptor::FlagProtected; return DBuilder.createMemberType(scope, name, file, line, sizeInBits, alignInBits, offsetInBits, flags, debugType); } /// CollectRecordLambdaFields - Helper for CollectRecordFields. void CGDebugInfo:: CollectRecordLambdaFields(const CXXRecordDecl *CXXDecl, SmallVectorImpl &elements, llvm::DIType RecordTy) { // For C++11 Lambdas a Field will be the same as a Capture, but the Capture // has the name and the location of the variable so we should iterate over // both concurrently. const ASTRecordLayout &layout = CGM.getContext().getASTRecordLayout(CXXDecl); RecordDecl::field_iterator Field = CXXDecl->field_begin(); unsigned fieldno = 0; for (CXXRecordDecl::capture_const_iterator I = CXXDecl->captures_begin(), E = CXXDecl->captures_end(); I != E; ++I, ++Field, ++fieldno) { const LambdaExpr::Capture C = *I; if (C.capturesVariable()) { VarDecl *V = C.getCapturedVar(); llvm::DIFile VUnit = getOrCreateFile(C.getLocation()); StringRef VName = V->getName(); uint64_t SizeInBitsOverride = 0; if (Field->isBitField()) { SizeInBitsOverride = Field->getBitWidthValue(CGM.getContext()); assert(SizeInBitsOverride && "found named 0-width bitfield"); } llvm::DIType fieldType = createFieldType(VName, Field->getType(), SizeInBitsOverride, C.getLocation(), Field->getAccess(), layout.getFieldOffset(fieldno), VUnit, RecordTy); elements.push_back(fieldType); } else { // TODO: Need to handle 'this' in some way by probably renaming the // this of the lambda class and having a field member of 'this' or // by using AT_object_pointer for the function and having that be // used as 'this' for semantic references. assert(C.capturesThis() && "Field that isn't captured and isn't this?"); FieldDecl *f = *Field; llvm::DIFile VUnit = getOrCreateFile(f->getLocation()); QualType type = f->getType(); llvm::DIType fieldType = createFieldType("this", type, 0, f->getLocation(), f->getAccess(), layout.getFieldOffset(fieldno), VUnit, RecordTy); elements.push_back(fieldType); } } } /// Helper for CollectRecordFields. llvm::DIDerivedType CGDebugInfo::CreateRecordStaticField(const VarDecl *Var, llvm::DIType RecordTy) { // Create the descriptor for the static variable, with or without // constant initializers. llvm::DIFile VUnit = getOrCreateFile(Var->getLocation()); llvm::DIType VTy = getOrCreateType(Var->getType(), VUnit); unsigned LineNumber = getLineNumber(Var->getLocation()); StringRef VName = Var->getName(); llvm::Constant *C = NULL; if (Var->getInit()) { const APValue *Value = Var->evaluateValue(); if (Value) { if (Value->isInt()) C = llvm::ConstantInt::get(CGM.getLLVMContext(), Value->getInt()); if (Value->isFloat()) C = llvm::ConstantFP::get(CGM.getLLVMContext(), Value->getFloat()); } } unsigned Flags = 0; AccessSpecifier Access = Var->getAccess(); if (Access == clang::AS_private) Flags |= llvm::DIDescriptor::FlagPrivate; else if (Access == clang::AS_protected) Flags |= llvm::DIDescriptor::FlagProtected; llvm::DIDerivedType GV = DBuilder.createStaticMemberType( RecordTy, VName, VUnit, LineNumber, VTy, Flags, C); StaticDataMemberCache[Var->getCanonicalDecl()] = llvm::WeakVH(GV); return GV; } /// CollectRecordNormalField - Helper for CollectRecordFields. void CGDebugInfo:: CollectRecordNormalField(const FieldDecl *field, uint64_t OffsetInBits, llvm::DIFile tunit, SmallVectorImpl &elements, llvm::DIType RecordTy) { StringRef name = field->getName(); QualType type = field->getType(); // Ignore unnamed fields unless they're anonymous structs/unions. if (name.empty() && !type->isRecordType()) return; uint64_t SizeInBitsOverride = 0; if (field->isBitField()) { SizeInBitsOverride = field->getBitWidthValue(CGM.getContext()); assert(SizeInBitsOverride && "found named 0-width bitfield"); } llvm::DIType fieldType = createFieldType(name, type, SizeInBitsOverride, field->getLocation(), field->getAccess(), OffsetInBits, tunit, RecordTy); elements.push_back(fieldType); } /// CollectRecordFields - A helper function to collect debug info for /// record fields. This is used while creating debug info entry for a Record. void CGDebugInfo::CollectRecordFields(const RecordDecl *record, llvm::DIFile tunit, SmallVectorImpl &elements, llvm::DICompositeType RecordTy) { const CXXRecordDecl *CXXDecl = dyn_cast(record); if (CXXDecl && CXXDecl->isLambda()) CollectRecordLambdaFields(CXXDecl, elements, RecordTy); else { const ASTRecordLayout &layout = CGM.getContext().getASTRecordLayout(record); // Field number for non-static fields. unsigned fieldNo = 0; // Static and non-static members should appear in the same order as // the corresponding declarations in the source program. for (RecordDecl::decl_iterator I = record->decls_begin(), E = record->decls_end(); I != E; ++I) if (const VarDecl *V = dyn_cast(*I)) { // Reuse the existing static member declaration if one exists llvm::DenseMap::iterator MI = StaticDataMemberCache.find(V->getCanonicalDecl()); if (MI != StaticDataMemberCache.end()) { assert(MI->second && "Static data member declaration should still exist"); elements.push_back( llvm::DIDerivedType(cast(MI->second))); } else elements.push_back(CreateRecordStaticField(V, RecordTy)); } else if (FieldDecl *field = dyn_cast(*I)) { CollectRecordNormalField(field, layout.getFieldOffset(fieldNo), tunit, elements, RecordTy); // Bump field number for next field. ++fieldNo; } } } /// getOrCreateMethodType - CXXMethodDecl's type is a FunctionType. This /// function type is not updated to include implicit "this" pointer. Use this /// routine to get a method type which includes "this" pointer. llvm::DICompositeType CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method, llvm::DIFile Unit) { const FunctionProtoType *Func = Method->getType()->getAs(); if (Method->isStatic()) return llvm::DICompositeType(getOrCreateType(QualType(Func, 0), Unit)); return getOrCreateInstanceMethodType(Method->getThisType(CGM.getContext()), Func, Unit); } llvm::DICompositeType CGDebugInfo::getOrCreateInstanceMethodType( QualType ThisPtr, const FunctionProtoType *Func, llvm::DIFile Unit) { // Add "this" pointer. llvm::DIArray Args = llvm::DICompositeType( getOrCreateType(QualType(Func, 0), Unit)).getTypeArray(); assert (Args.getNumElements() && "Invalid number of arguments!"); SmallVector Elts; // First element is always return type. For 'void' functions it is NULL. Elts.push_back(Args.getElement(0)); // "this" pointer is always first argument. const CXXRecordDecl *RD = ThisPtr->getPointeeCXXRecordDecl(); if (isa(RD)) { // Create pointer type directly in this case. const PointerType *ThisPtrTy = cast(ThisPtr); QualType PointeeTy = ThisPtrTy->getPointeeType(); unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy); uint64_t Size = CGM.getTarget().getPointerWidth(AS); uint64_t Align = CGM.getContext().getTypeAlign(ThisPtrTy); llvm::DIType PointeeType = getOrCreateType(PointeeTy, Unit); llvm::DIType ThisPtrType = DBuilder.createPointerType(PointeeType, Size, Align); TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType; // TODO: This and the artificial type below are misleading, the // types aren't artificial the argument is, but the current // metadata doesn't represent that. ThisPtrType = DBuilder.createObjectPointerType(ThisPtrType); Elts.push_back(ThisPtrType); } else { llvm::DIType ThisPtrType = getOrCreateType(ThisPtr, Unit); TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType; ThisPtrType = DBuilder.createObjectPointerType(ThisPtrType); Elts.push_back(ThisPtrType); } // Copy rest of the arguments. for (unsigned i = 1, e = Args.getNumElements(); i != e; ++i) Elts.push_back(Args.getElement(i)); llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(Elts); return DBuilder.createSubroutineType(Unit, EltTypeArray); } /// isFunctionLocalClass - Return true if CXXRecordDecl is defined /// inside a function. static bool isFunctionLocalClass(const CXXRecordDecl *RD) { if (const CXXRecordDecl *NRD = dyn_cast(RD->getDeclContext())) return isFunctionLocalClass(NRD); if (isa(RD->getDeclContext())) return true; return false; } /// CreateCXXMemberFunction - A helper function to create a DISubprogram for /// a single member function GlobalDecl. llvm::DISubprogram CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method, llvm::DIFile Unit, llvm::DIType RecordTy) { bool IsCtorOrDtor = isa(Method) || isa(Method); StringRef MethodName = getFunctionName(Method); llvm::DICompositeType MethodTy = getOrCreateMethodType(Method, Unit); // Since a single ctor/dtor corresponds to multiple functions, it doesn't // make sense to give a single ctor/dtor a linkage name. StringRef MethodLinkageName; if (!IsCtorOrDtor && !isFunctionLocalClass(Method->getParent())) MethodLinkageName = CGM.getMangledName(Method); // Get the location for the method. llvm::DIFile MethodDefUnit; unsigned MethodLine = 0; if (!Method->isImplicit()) { MethodDefUnit = getOrCreateFile(Method->getLocation()); MethodLine = getLineNumber(Method->getLocation()); } // Collect virtual method info. llvm::DIType ContainingType; unsigned Virtuality = 0; unsigned VIndex = 0; if (Method->isVirtual()) { if (Method->isPure()) Virtuality = llvm::dwarf::DW_VIRTUALITY_pure_virtual; else Virtuality = llvm::dwarf::DW_VIRTUALITY_virtual; // It doesn't make sense to give a virtual destructor a vtable index, // since a single destructor has two entries in the vtable. // FIXME: Add proper support for debug info for virtual calls in // the Microsoft ABI, where we may use multiple vptrs to make a vftable // lookup if we have multiple or virtual inheritance. if (!isa(Method) && !CGM.getTarget().getCXXABI().isMicrosoft()) VIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(Method); ContainingType = RecordTy; } unsigned Flags = 0; if (Method->isImplicit()) Flags |= llvm::DIDescriptor::FlagArtificial; AccessSpecifier Access = Method->getAccess(); if (Access == clang::AS_private) Flags |= llvm::DIDescriptor::FlagPrivate; else if (Access == clang::AS_protected) Flags |= llvm::DIDescriptor::FlagProtected; if (const CXXConstructorDecl *CXXC = dyn_cast(Method)) { if (CXXC->isExplicit()) Flags |= llvm::DIDescriptor::FlagExplicit; } else if (const CXXConversionDecl *CXXC = dyn_cast(Method)) { if (CXXC->isExplicit()) Flags |= llvm::DIDescriptor::FlagExplicit; } if (Method->hasPrototype()) Flags |= llvm::DIDescriptor::FlagPrototyped; llvm::DIArray TParamsArray = CollectFunctionTemplateParams(Method, Unit); llvm::DISubprogram SP = DBuilder.createMethod(RecordTy, MethodName, MethodLinkageName, MethodDefUnit, MethodLine, MethodTy, /*isLocalToUnit=*/false, /* isDefinition=*/ false, Virtuality, VIndex, ContainingType, Flags, CGM.getLangOpts().Optimize, NULL, TParamsArray); SPCache[Method->getCanonicalDecl()] = llvm::WeakVH(SP); return SP; } /// CollectCXXMemberFunctions - A helper function to collect debug info for /// C++ member functions. This is used while creating debug info entry for /// a Record. void CGDebugInfo:: CollectCXXMemberFunctions(const CXXRecordDecl *RD, llvm::DIFile Unit, SmallVectorImpl &EltTys, llvm::DIType RecordTy) { // Since we want more than just the individual member decls if we // have templated functions iterate over every declaration to gather // the functions. for(DeclContext::decl_iterator I = RD->decls_begin(), E = RD->decls_end(); I != E; ++I) { if (const CXXMethodDecl *Method = dyn_cast(*I)) { // Reuse the existing member function declaration if it exists. // It may be associated with the declaration of the type & should be // reused as we're building the definition. // // This situation can arise in the vtable-based debug info reduction where // implicit members are emitted in a non-vtable TU. llvm::DenseMap::iterator MI = SPCache.find(Method->getCanonicalDecl()); if (MI == SPCache.end()) { // If the member is implicit, lazily create it when we see the // definition, not before. (an ODR-used implicit default ctor that's // never actually code generated should not produce debug info) if (!Method->isImplicit()) EltTys.push_back(CreateCXXMemberFunction(Method, Unit, RecordTy)); } else EltTys.push_back(MI->second); } else if (const FunctionTemplateDecl *FTD = dyn_cast(*I)) { // Add any template specializations that have already been seen. Like // implicit member functions, these may have been added to a declaration // in the case of vtable-based debug info reduction. for (FunctionTemplateDecl::spec_iterator SI = FTD->spec_begin(), SE = FTD->spec_end(); SI != SE; ++SI) { llvm::DenseMap::iterator MI = SPCache.find(cast(*SI)->getCanonicalDecl()); if (MI != SPCache.end()) EltTys.push_back(MI->second); } } } } /// CollectCXXBases - A helper function to collect debug info for /// C++ base classes. This is used while creating debug info entry for /// a Record. void CGDebugInfo:: CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile Unit, SmallVectorImpl &EltTys, llvm::DIType RecordTy) { const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); for (CXXRecordDecl::base_class_const_iterator BI = RD->bases_begin(), BE = RD->bases_end(); BI != BE; ++BI) { unsigned BFlags = 0; uint64_t BaseOffset; const CXXRecordDecl *Base = cast(BI->getType()->getAs()->getDecl()); if (BI->isVirtual()) { // virtual base offset offset is -ve. The code generator emits dwarf // expression where it expects +ve number. BaseOffset = 0 - CGM.getItaniumVTableContext() .getVirtualBaseOffsetOffset(RD, Base).getQuantity(); BFlags = llvm::DIDescriptor::FlagVirtual; } else BaseOffset = CGM.getContext().toBits(RL.getBaseClassOffset(Base)); // FIXME: Inconsistent units for BaseOffset. It is in bytes when // BI->isVirtual() and bits when not. AccessSpecifier Access = BI->getAccessSpecifier(); if (Access == clang::AS_private) BFlags |= llvm::DIDescriptor::FlagPrivate; else if (Access == clang::AS_protected) BFlags |= llvm::DIDescriptor::FlagProtected; llvm::DIType DTy = DBuilder.createInheritance(RecordTy, getOrCreateType(BI->getType(), Unit), BaseOffset, BFlags); EltTys.push_back(DTy); } } /// CollectTemplateParams - A helper function to collect template parameters. llvm::DIArray CGDebugInfo:: CollectTemplateParams(const TemplateParameterList *TPList, ArrayRef TAList, llvm::DIFile Unit) { SmallVector TemplateParams; for (unsigned i = 0, e = TAList.size(); i != e; ++i) { const TemplateArgument &TA = TAList[i]; StringRef Name; if (TPList) Name = TPList->getParam(i)->getName(); switch (TA.getKind()) { case TemplateArgument::Type: { llvm::DIType TTy = getOrCreateType(TA.getAsType(), Unit); llvm::DITemplateTypeParameter TTP = DBuilder.createTemplateTypeParameter(TheCU, Name, TTy); TemplateParams.push_back(TTP); } break; case TemplateArgument::Integral: { llvm::DIType TTy = getOrCreateType(TA.getIntegralType(), Unit); llvm::DITemplateValueParameter TVP = DBuilder.createTemplateValueParameter( TheCU, Name, TTy, llvm::ConstantInt::get(CGM.getLLVMContext(), TA.getAsIntegral())); TemplateParams.push_back(TVP); } break; case TemplateArgument::Declaration: { const ValueDecl *D = TA.getAsDecl(); bool InstanceMember = D->isCXXInstanceMember(); QualType T = InstanceMember ? CGM.getContext().getMemberPointerType( D->getType(), cast(D->getDeclContext()) ->getTypeForDecl()) : CGM.getContext().getPointerType(D->getType()); llvm::DIType TTy = getOrCreateType(T, Unit); llvm::Value *V = 0; // Variable pointer template parameters have a value that is the address // of the variable. if (const VarDecl *VD = dyn_cast(D)) V = CGM.GetAddrOfGlobalVar(VD); // Member function pointers have special support for building them, though // this is currently unsupported in LLVM CodeGen. if (InstanceMember) { if (const CXXMethodDecl *method = dyn_cast(D)) V = CGM.getCXXABI().EmitMemberPointer(method); } else if (const FunctionDecl *FD = dyn_cast(D)) V = CGM.GetAddrOfFunction(FD); // Member data pointers have special handling too to compute the fixed // offset within the object. if (isa(D) || isa(D)) { // These five lines (& possibly the above member function pointer // handling) might be able to be refactored to use similar code in // CodeGenModule::getMemberPointerConstant uint64_t fieldOffset = CGM.getContext().getFieldOffset(D); CharUnits chars = CGM.getContext().toCharUnitsFromBits((int64_t) fieldOffset); V = CGM.getCXXABI().EmitMemberDataPointer( cast(T.getTypePtr()), chars); } llvm::DITemplateValueParameter TVP = DBuilder.createTemplateValueParameter(TheCU, Name, TTy, V->stripPointerCasts()); TemplateParams.push_back(TVP); } break; case TemplateArgument::NullPtr: { QualType T = TA.getNullPtrType(); llvm::DIType TTy = getOrCreateType(T, Unit); llvm::Value *V = 0; // Special case member data pointer null values since they're actually -1 // instead of zero. if (const MemberPointerType *MPT = dyn_cast(T.getTypePtr())) // But treat member function pointers as simple zero integers because // it's easier than having a special case in LLVM's CodeGen. If LLVM // CodeGen grows handling for values of non-null member function // pointers then perhaps we could remove this special case and rely on // EmitNullMemberPointer for member function pointers. if (MPT->isMemberDataPointer()) V = CGM.getCXXABI().EmitNullMemberPointer(MPT); if (!V) V = llvm::ConstantInt::get(CGM.Int8Ty, 0); llvm::DITemplateValueParameter TVP = DBuilder.createTemplateValueParameter(TheCU, Name, TTy, V); TemplateParams.push_back(TVP); } break; case TemplateArgument::Template: { llvm::DITemplateValueParameter TVP = DBuilder.createTemplateTemplateParameter( TheCU, Name, llvm::DIType(), TA.getAsTemplate().getAsTemplateDecl() ->getQualifiedNameAsString()); TemplateParams.push_back(TVP); } break; case TemplateArgument::Pack: { llvm::DITemplateValueParameter TVP = DBuilder.createTemplateParameterPack( TheCU, Name, llvm::DIType(), CollectTemplateParams(NULL, TA.getPackAsArray(), Unit)); TemplateParams.push_back(TVP); } break; case TemplateArgument::Expression: { const Expr *E = TA.getAsExpr(); QualType T = E->getType(); llvm::Value *V = CGM.EmitConstantExpr(E, T); assert(V && "Expression in template argument isn't constant"); llvm::DIType TTy = getOrCreateType(T, Unit); llvm::DITemplateValueParameter TVP = DBuilder.createTemplateValueParameter(TheCU, Name, TTy, V->stripPointerCasts()); TemplateParams.push_back(TVP); } break; // And the following should never occur: case TemplateArgument::TemplateExpansion: case TemplateArgument::Null: llvm_unreachable( "These argument types shouldn't exist in concrete types"); } } return DBuilder.getOrCreateArray(TemplateParams); } /// CollectFunctionTemplateParams - A helper function to collect debug /// info for function template parameters. llvm::DIArray CGDebugInfo:: CollectFunctionTemplateParams(const FunctionDecl *FD, llvm::DIFile Unit) { if (FD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplateSpecialization) { const TemplateParameterList *TList = FD->getTemplateSpecializationInfo()->getTemplate() ->getTemplateParameters(); return CollectTemplateParams( TList, FD->getTemplateSpecializationArgs()->asArray(), Unit); } return llvm::DIArray(); } /// CollectCXXTemplateParams - A helper function to collect debug info for /// template parameters. llvm::DIArray CGDebugInfo:: CollectCXXTemplateParams(const ClassTemplateSpecializationDecl *TSpecial, llvm::DIFile Unit) { llvm::PointerUnion PU = TSpecial->getSpecializedTemplateOrPartial(); TemplateParameterList *TPList = PU.is() ? PU.get()->getTemplateParameters() : PU.get()->getTemplateParameters(); const TemplateArgumentList &TAList = TSpecial->getTemplateInstantiationArgs(); return CollectTemplateParams(TPList, TAList.asArray(), Unit); } /// getOrCreateVTablePtrType - Return debug info descriptor for vtable. llvm::DIType CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile Unit) { if (VTablePtrType.isValid()) return VTablePtrType; ASTContext &Context = CGM.getContext(); /* Function type */ llvm::Value *STy = getOrCreateType(Context.IntTy, Unit); llvm::DIArray SElements = DBuilder.getOrCreateArray(STy); llvm::DIType SubTy = DBuilder.createSubroutineType(Unit, SElements); unsigned Size = Context.getTypeSize(Context.VoidPtrTy); llvm::DIType vtbl_ptr_type = DBuilder.createPointerType(SubTy, Size, 0, "__vtbl_ptr_type"); VTablePtrType = DBuilder.createPointerType(vtbl_ptr_type, Size); return VTablePtrType; } /// getVTableName - Get vtable name for the given Class. StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) { // Copy the gdb compatible name on the side and use its reference. return internString("_vptr$", RD->getNameAsString()); } /// CollectVTableInfo - If the C++ class has vtable info then insert appropriate /// debug info entry in EltTys vector. void CGDebugInfo:: CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile Unit, SmallVectorImpl &EltTys) { const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); // If there is a primary base then it will hold vtable info. if (RL.getPrimaryBase()) return; // If this class is not dynamic then there is not any vtable info to collect. if (!RD->isDynamicClass()) return; unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy); llvm::DIType VPTR = DBuilder.createMemberType(Unit, getVTableName(RD), Unit, 0, Size, 0, 0, llvm::DIDescriptor::FlagArtificial, getOrCreateVTablePtrType(Unit)); EltTys.push_back(VPTR); } /// getOrCreateRecordType - Emit record type's standalone debug info. llvm::DIType CGDebugInfo::getOrCreateRecordType(QualType RTy, SourceLocation Loc) { assert(DebugKind >= CodeGenOptions::LimitedDebugInfo); llvm::DIType T = getOrCreateType(RTy, getOrCreateFile(Loc)); return T; } /// getOrCreateInterfaceType - Emit an objective c interface type standalone /// debug info. llvm::DIType CGDebugInfo::getOrCreateInterfaceType(QualType D, SourceLocation Loc) { assert(DebugKind >= CodeGenOptions::LimitedDebugInfo); llvm::DIType T = getOrCreateType(D, getOrCreateFile(Loc)); RetainedTypes.push_back(D.getAsOpaquePtr()); return T; } void CGDebugInfo::completeType(const RecordDecl *RD) { if (DebugKind > CodeGenOptions::LimitedDebugInfo || !CGM.getLangOpts().CPlusPlus) completeRequiredType(RD); } void CGDebugInfo::completeRequiredType(const RecordDecl *RD) { if (const CXXRecordDecl *CXXDecl = dyn_cast(RD)) if (CXXDecl->isDynamicClass()) return; QualType Ty = CGM.getContext().getRecordType(RD); llvm::DIType T = getTypeOrNull(Ty); if (T && T.isForwardDecl()) completeClassData(RD); } void CGDebugInfo::completeClassData(const RecordDecl *RD) { if (DebugKind <= CodeGenOptions::DebugLineTablesOnly) return; QualType Ty = CGM.getContext().getRecordType(RD); void* TyPtr = Ty.getAsOpaquePtr(); if (CompletedTypeCache.count(TyPtr)) return; llvm::DIType Res = CreateTypeDefinition(Ty->castAs()); assert(!Res.isForwardDecl()); CompletedTypeCache[TyPtr] = Res; TypeCache[TyPtr] = Res; } /// CreateType - get structure or union type. llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) { RecordDecl *RD = Ty->getDecl(); const CXXRecordDecl *CXXDecl = dyn_cast(RD); // Always emit declarations for types that aren't required to be complete when // in limit-debug-info mode. If the type is later found to be required to be // complete this declaration will be upgraded to a definition by // `completeRequiredType`. // If the type is dynamic, only emit the definition in TUs that require class // data. This is handled by `completeClassData`. llvm::DICompositeType T(getTypeOrNull(QualType(Ty, 0))); // If we've already emitted the type, just use that, even if it's only a // declaration. The completeType, completeRequiredType, and completeClassData // callbacks will handle promoting the declaration to a definition. if (T || + // Under -flimit-debug-info: (DebugKind <= CodeGenOptions::LimitedDebugInfo && - // Under -flimit-debug-info, emit only a declaration unless the type is - // required to be complete. - !RD->isCompleteDefinitionRequired() && CGM.getLangOpts().CPlusPlus) || - // If the class is dynamic, only emit a declaration. A definition will be - // emitted whenever the vtable is emitted. - (CXXDecl && CXXDecl->hasDefinition() && CXXDecl->isDynamicClass()) || T) { + // Emit only a forward declaration unless the type is required. + ((!RD->isCompleteDefinitionRequired() && CGM.getLangOpts().CPlusPlus) || + // If the class is dynamic, only emit a declaration. A definition will be + // emitted whenever the vtable is emitted. + (CXXDecl && CXXDecl->hasDefinition() && CXXDecl->isDynamicClass())))) { llvm::DIDescriptor FDContext = getContextDescriptor(cast(RD->getDeclContext())); if (!T) T = getOrCreateRecordFwdDecl(Ty, FDContext); return T; } return CreateTypeDefinition(Ty); } llvm::DIType CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) { RecordDecl *RD = Ty->getDecl(); // Get overall information about the record type for the debug info. llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation()); // Records and classes and unions can all be recursive. To handle them, we // first generate a debug descriptor for the struct as a forward declaration. // Then (if it is a definition) we go through and get debug info for all of // its members. Finally, we create a descriptor for the complete type (which // may refer to the forward decl if the struct is recursive) and replace all // uses of the forward declaration with the final definition. llvm::DICompositeType FwdDecl(getOrCreateLimitedType(Ty, DefUnit)); assert(FwdDecl.isCompositeType() && "The debug type of a RecordType should be a llvm::DICompositeType"); if (FwdDecl.isForwardDecl()) return FwdDecl; if (const CXXRecordDecl *CXXDecl = dyn_cast(RD)) CollectContainingType(CXXDecl, FwdDecl); // Push the struct on region stack. LexicalBlockStack.push_back(&*FwdDecl); RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl); // Add this to the completed-type cache while we're completing it recursively. CompletedTypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl; // Convert all the elements. SmallVector EltTys; // what about nested types? // Note: The split of CXXDecl information here is intentional, the // gdb tests will depend on a certain ordering at printout. The debug // information offsets are still correct if we merge them all together // though. const CXXRecordDecl *CXXDecl = dyn_cast(RD); if (CXXDecl) { CollectCXXBases(CXXDecl, DefUnit, EltTys, FwdDecl); CollectVTableInfo(CXXDecl, DefUnit, EltTys); } // Collect data fields (including static variables and any initializers). CollectRecordFields(RD, DefUnit, EltTys, FwdDecl); if (CXXDecl) CollectCXXMemberFunctions(CXXDecl, DefUnit, EltTys, FwdDecl); LexicalBlockStack.pop_back(); RegionMap.erase(Ty->getDecl()); llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys); FwdDecl.setTypeArray(Elements); RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl); return FwdDecl; } /// CreateType - get objective-c object type. llvm::DIType CGDebugInfo::CreateType(const ObjCObjectType *Ty, llvm::DIFile Unit) { // Ignore protocols. return getOrCreateType(Ty->getBaseType(), Unit); } /// \return true if Getter has the default name for the property PD. static bool hasDefaultGetterName(const ObjCPropertyDecl *PD, const ObjCMethodDecl *Getter) { assert(PD); if (!Getter) return true; assert(Getter->getDeclName().isObjCZeroArgSelector()); return PD->getName() == Getter->getDeclName().getObjCSelector().getNameForSlot(0); } /// \return true if Setter has the default name for the property PD. static bool hasDefaultSetterName(const ObjCPropertyDecl *PD, const ObjCMethodDecl *Setter) { assert(PD); if (!Setter) return true; assert(Setter->getDeclName().isObjCOneArgSelector()); return SelectorTable::constructSetterName(PD->getName()) == Setter->getDeclName().getObjCSelector().getNameForSlot(0); } /// CreateType - get objective-c interface type. llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, llvm::DIFile Unit) { ObjCInterfaceDecl *ID = Ty->getDecl(); if (!ID) return llvm::DIType(); // Get overall information about the record type for the debug info. llvm::DIFile DefUnit = getOrCreateFile(ID->getLocation()); unsigned Line = getLineNumber(ID->getLocation()); unsigned RuntimeLang = TheCU.getLanguage(); // If this is just a forward declaration return a special forward-declaration // debug type since we won't be able to lay out the entire type. ObjCInterfaceDecl *Def = ID->getDefinition(); if (!Def) { llvm::DIType FwdDecl = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, ID->getName(), TheCU, DefUnit, Line, RuntimeLang); return FwdDecl; } ID = Def; // Bit size, align and offset of the type. uint64_t Size = CGM.getContext().getTypeSize(Ty); uint64_t Align = CGM.getContext().getTypeAlign(Ty); unsigned Flags = 0; if (ID->getImplementation()) Flags |= llvm::DIDescriptor::FlagObjcClassComplete; llvm::DICompositeType RealDecl = DBuilder.createStructType(Unit, ID->getName(), DefUnit, Line, Size, Align, Flags, llvm::DIType(), llvm::DIArray(), RuntimeLang); // Otherwise, insert it into the CompletedTypeCache so that recursive uses // will find it and we're emitting the complete type. QualType QualTy = QualType(Ty, 0); CompletedTypeCache[QualTy.getAsOpaquePtr()] = RealDecl; // Push the struct on region stack. LexicalBlockStack.push_back(static_cast(RealDecl)); RegionMap[Ty->getDecl()] = llvm::WeakVH(RealDecl); // Convert all the elements. SmallVector EltTys; ObjCInterfaceDecl *SClass = ID->getSuperClass(); if (SClass) { llvm::DIType SClassTy = getOrCreateType(CGM.getContext().getObjCInterfaceType(SClass), Unit); if (!SClassTy.isValid()) return llvm::DIType(); llvm::DIType InhTag = DBuilder.createInheritance(RealDecl, SClassTy, 0, 0); EltTys.push_back(InhTag); } // Create entries for all of the properties. for (ObjCContainerDecl::prop_iterator I = ID->prop_begin(), E = ID->prop_end(); I != E; ++I) { const ObjCPropertyDecl *PD = *I; SourceLocation Loc = PD->getLocation(); llvm::DIFile PUnit = getOrCreateFile(Loc); unsigned PLine = getLineNumber(Loc); ObjCMethodDecl *Getter = PD->getGetterMethodDecl(); ObjCMethodDecl *Setter = PD->getSetterMethodDecl(); llvm::MDNode *PropertyNode = DBuilder.createObjCProperty(PD->getName(), PUnit, PLine, hasDefaultGetterName(PD, Getter) ? "" : getSelectorName(PD->getGetterName()), hasDefaultSetterName(PD, Setter) ? "" : getSelectorName(PD->getSetterName()), PD->getPropertyAttributes(), getOrCreateType(PD->getType(), PUnit)); EltTys.push_back(PropertyNode); } const ASTRecordLayout &RL = CGM.getContext().getASTObjCInterfaceLayout(ID); unsigned FieldNo = 0; for (ObjCIvarDecl *Field = ID->all_declared_ivar_begin(); Field; Field = Field->getNextIvar(), ++FieldNo) { llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit); if (!FieldTy.isValid()) return llvm::DIType(); StringRef FieldName = Field->getName(); // Ignore unnamed fields. if (FieldName.empty()) continue; // Get the location for the field. llvm::DIFile FieldDefUnit = getOrCreateFile(Field->getLocation()); unsigned FieldLine = getLineNumber(Field->getLocation()); QualType FType = Field->getType(); uint64_t FieldSize = 0; unsigned FieldAlign = 0; if (!FType->isIncompleteArrayType()) { // Bit size, align and offset of the type. FieldSize = Field->isBitField() ? Field->getBitWidthValue(CGM.getContext()) : CGM.getContext().getTypeSize(FType); FieldAlign = CGM.getContext().getTypeAlign(FType); } uint64_t FieldOffset; if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) { // We don't know the runtime offset of an ivar if we're using the // non-fragile ABI. For bitfields, use the bit offset into the first // byte of storage of the bitfield. For other fields, use zero. if (Field->isBitField()) { FieldOffset = CGM.getObjCRuntime().ComputeBitfieldBitOffset( CGM, ID, Field); FieldOffset %= CGM.getContext().getCharWidth(); } else { FieldOffset = 0; } } else { FieldOffset = RL.getFieldOffset(FieldNo); } unsigned Flags = 0; if (Field->getAccessControl() == ObjCIvarDecl::Protected) Flags = llvm::DIDescriptor::FlagProtected; else if (Field->getAccessControl() == ObjCIvarDecl::Private) Flags = llvm::DIDescriptor::FlagPrivate; llvm::MDNode *PropertyNode = NULL; if (ObjCImplementationDecl *ImpD = ID->getImplementation()) { if (ObjCPropertyImplDecl *PImpD = ImpD->FindPropertyImplIvarDecl(Field->getIdentifier())) { if (ObjCPropertyDecl *PD = PImpD->getPropertyDecl()) { SourceLocation Loc = PD->getLocation(); llvm::DIFile PUnit = getOrCreateFile(Loc); unsigned PLine = getLineNumber(Loc); ObjCMethodDecl *Getter = PD->getGetterMethodDecl(); ObjCMethodDecl *Setter = PD->getSetterMethodDecl(); PropertyNode = DBuilder.createObjCProperty(PD->getName(), PUnit, PLine, hasDefaultGetterName(PD, Getter) ? "" : getSelectorName(PD->getGetterName()), hasDefaultSetterName(PD, Setter) ? "" : getSelectorName(PD->getSetterName()), PD->getPropertyAttributes(), getOrCreateType(PD->getType(), PUnit)); } } } FieldTy = DBuilder.createObjCIVar(FieldName, FieldDefUnit, FieldLine, FieldSize, FieldAlign, FieldOffset, Flags, FieldTy, PropertyNode); EltTys.push_back(FieldTy); } llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys); RealDecl.setTypeArray(Elements); // If the implementation is not yet set, we do not want to mark it // as complete. An implementation may declare additional // private ivars that we would miss otherwise. if (ID->getImplementation() == 0) CompletedTypeCache.erase(QualTy.getAsOpaquePtr()); LexicalBlockStack.pop_back(); return RealDecl; } llvm::DIType CGDebugInfo::CreateType(const VectorType *Ty, llvm::DIFile Unit) { llvm::DIType ElementTy = getOrCreateType(Ty->getElementType(), Unit); int64_t Count = Ty->getNumElements(); if (Count == 0) // If number of elements are not known then this is an unbounded array. // Use Count == -1 to express such arrays. Count = -1; llvm::Value *Subscript = DBuilder.getOrCreateSubrange(0, Count); llvm::DIArray SubscriptArray = DBuilder.getOrCreateArray(Subscript); uint64_t Size = CGM.getContext().getTypeSize(Ty); uint64_t Align = CGM.getContext().getTypeAlign(Ty); return DBuilder.createVectorType(Size, Align, ElementTy, SubscriptArray); } llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty, llvm::DIFile Unit) { uint64_t Size; uint64_t Align; // FIXME: make getTypeAlign() aware of VLAs and incomplete array types if (const VariableArrayType *VAT = dyn_cast(Ty)) { Size = 0; Align = CGM.getContext().getTypeAlign(CGM.getContext().getBaseElementType(VAT)); } else if (Ty->isIncompleteArrayType()) { Size = 0; if (Ty->getElementType()->isIncompleteType()) Align = 0; else Align = CGM.getContext().getTypeAlign(Ty->getElementType()); } else if (Ty->isIncompleteType()) { Size = 0; Align = 0; } else { // Size and align of the whole array, not the element type. Size = CGM.getContext().getTypeSize(Ty); Align = CGM.getContext().getTypeAlign(Ty); } // Add the dimensions of the array. FIXME: This loses CV qualifiers from // interior arrays, do we care? Why aren't nested arrays represented the // obvious/recursive way? SmallVector Subscripts; QualType EltTy(Ty, 0); while ((Ty = dyn_cast(EltTy))) { // If the number of elements is known, then count is that number. Otherwise, // it's -1. This allows us to represent a subrange with an array of 0 // elements, like this: // // struct foo { // int x[0]; // }; int64_t Count = -1; // Count == -1 is an unbounded array. if (const ConstantArrayType *CAT = dyn_cast(Ty)) Count = CAT->getSize().getZExtValue(); // FIXME: Verify this is right for VLAs. Subscripts.push_back(DBuilder.getOrCreateSubrange(0, Count)); EltTy = Ty->getElementType(); } llvm::DIArray SubscriptArray = DBuilder.getOrCreateArray(Subscripts); llvm::DIType DbgTy = DBuilder.createArrayType(Size, Align, getOrCreateType(EltTy, Unit), SubscriptArray); return DbgTy; } llvm::DIType CGDebugInfo::CreateType(const LValueReferenceType *Ty, llvm::DIFile Unit) { return CreatePointerLikeType(llvm::dwarf::DW_TAG_reference_type, Ty, Ty->getPointeeType(), Unit); } llvm::DIType CGDebugInfo::CreateType(const RValueReferenceType *Ty, llvm::DIFile Unit) { return CreatePointerLikeType(llvm::dwarf::DW_TAG_rvalue_reference_type, Ty, Ty->getPointeeType(), Unit); } llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty, llvm::DIFile U) { llvm::DIType ClassType = getOrCreateType(QualType(Ty->getClass(), 0), U); if (!Ty->getPointeeType()->isFunctionType()) return DBuilder.createMemberPointerType( getOrCreateType(Ty->getPointeeType(), U), ClassType); return DBuilder.createMemberPointerType(getOrCreateInstanceMethodType( CGM.getContext().getPointerType( QualType(Ty->getClass(), Ty->getPointeeType().getCVRQualifiers())), Ty->getPointeeType()->getAs(), U), ClassType); } llvm::DIType CGDebugInfo::CreateType(const AtomicType *Ty, llvm::DIFile U) { // Ignore the atomic wrapping // FIXME: What is the correct representation? return getOrCreateType(Ty->getValueType(), U); } /// CreateEnumType - get enumeration type. llvm::DIType CGDebugInfo::CreateEnumType(const EnumType *Ty) { const EnumDecl *ED = Ty->getDecl(); uint64_t Size = 0; uint64_t Align = 0; if (!ED->getTypeForDecl()->isIncompleteType()) { Size = CGM.getContext().getTypeSize(ED->getTypeForDecl()); Align = CGM.getContext().getTypeAlign(ED->getTypeForDecl()); } SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU); // If this is just a forward declaration, construct an appropriately // marked node and just return it. if (!ED->getDefinition()) { llvm::DIDescriptor EDContext; EDContext = getContextDescriptor(cast(ED->getDeclContext())); llvm::DIFile DefUnit = getOrCreateFile(ED->getLocation()); unsigned Line = getLineNumber(ED->getLocation()); StringRef EDName = ED->getName(); return DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_enumeration_type, EDName, EDContext, DefUnit, Line, 0, Size, Align, FullName); } // Create DIEnumerator elements for each enumerator. SmallVector Enumerators; ED = ED->getDefinition(); for (EnumDecl::enumerator_iterator Enum = ED->enumerator_begin(), EnumEnd = ED->enumerator_end(); Enum != EnumEnd; ++Enum) { Enumerators.push_back( DBuilder.createEnumerator(Enum->getName(), Enum->getInitVal().getSExtValue())); } // Return a CompositeType for the enum itself. llvm::DIArray EltArray = DBuilder.getOrCreateArray(Enumerators); llvm::DIFile DefUnit = getOrCreateFile(ED->getLocation()); unsigned Line = getLineNumber(ED->getLocation()); llvm::DIDescriptor EnumContext = getContextDescriptor(cast(ED->getDeclContext())); llvm::DIType ClassTy = ED->isFixed() ? getOrCreateType(ED->getIntegerType(), DefUnit) : llvm::DIType(); llvm::DIType DbgTy = DBuilder.createEnumerationType(EnumContext, ED->getName(), DefUnit, Line, Size, Align, EltArray, ClassTy, FullName); return DbgTy; } static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) { Qualifiers Quals; do { Qualifiers InnerQuals = T.getLocalQualifiers(); // Qualifiers::operator+() doesn't like it if you add a Qualifier // that is already there. Quals += Qualifiers::removeCommonQualifiers(Quals, InnerQuals); Quals += InnerQuals; QualType LastT = T; switch (T->getTypeClass()) { default: return C.getQualifiedType(T.getTypePtr(), Quals); case Type::TemplateSpecialization: T = cast(T)->desugar(); break; case Type::TypeOfExpr: T = cast(T)->getUnderlyingExpr()->getType(); break; case Type::TypeOf: T = cast(T)->getUnderlyingType(); break; case Type::Decltype: T = cast(T)->getUnderlyingType(); break; case Type::UnaryTransform: T = cast(T)->getUnderlyingType(); break; case Type::Attributed: T = cast(T)->getEquivalentType(); break; case Type::Elaborated: T = cast(T)->getNamedType(); break; case Type::Paren: T = cast(T)->getInnerType(); break; case Type::SubstTemplateTypeParm: T = cast(T)->getReplacementType(); break; case Type::Auto: QualType DT = cast(T)->getDeducedType(); if (DT.isNull()) return T; T = DT; break; } assert(T != LastT && "Type unwrapping failed to unwrap!"); (void)LastT; } while (true); } /// getType - Get the type from the cache or return null type if it doesn't /// exist. llvm::DIType CGDebugInfo::getTypeOrNull(QualType Ty) { // Unwrap the type as needed for debug information. Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext()); // Check for existing entry. if (Ty->getTypeClass() == Type::ObjCInterface) { llvm::Value *V = getCachedInterfaceTypeOrNull(Ty); if (V) return llvm::DIType(cast(V)); else return llvm::DIType(); } llvm::DenseMap::iterator it = TypeCache.find(Ty.getAsOpaquePtr()); if (it != TypeCache.end()) { // Verify that the debug info still exists. if (llvm::Value *V = it->second) return llvm::DIType(cast(V)); } return llvm::DIType(); } /// getCompletedTypeOrNull - Get the type from the cache or return null if it /// doesn't exist. llvm::DIType CGDebugInfo::getCompletedTypeOrNull(QualType Ty) { // Unwrap the type as needed for debug information. Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext()); // Check for existing entry. llvm::Value *V = 0; llvm::DenseMap::iterator it = CompletedTypeCache.find(Ty.getAsOpaquePtr()); if (it != CompletedTypeCache.end()) V = it->second; else { V = getCachedInterfaceTypeOrNull(Ty); } // Verify that any cached debug info still exists. return llvm::DIType(cast_or_null(V)); } /// getCachedInterfaceTypeOrNull - Get the type from the interface /// cache, unless it needs to regenerated. Otherwise return null. llvm::Value *CGDebugInfo::getCachedInterfaceTypeOrNull(QualType Ty) { // Is there a cached interface that hasn't changed? llvm::DenseMap > ::iterator it1 = ObjCInterfaceCache.find(Ty.getAsOpaquePtr()); if (it1 != ObjCInterfaceCache.end()) if (ObjCInterfaceDecl* Decl = getObjCInterfaceDecl(Ty)) if (Checksum(Decl) == it1->second.second) // Return cached forward declaration. return it1->second.first; return 0; } /// getOrCreateType - Get the type from the cache or create a new /// one if necessary. llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile Unit) { if (Ty.isNull()) return llvm::DIType(); // Unwrap the type as needed for debug information. Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext()); if (llvm::DIType T = getCompletedTypeOrNull(Ty)) return T; // Otherwise create the type. llvm::DIType Res = CreateTypeNode(Ty, Unit); void* TyPtr = Ty.getAsOpaquePtr(); // And update the type cache. TypeCache[TyPtr] = Res; // FIXME: this getTypeOrNull call seems silly when we just inserted the type // into the cache - but getTypeOrNull has a special case for cached interface // types. We should probably just pull that out as a special case for the // "else" block below & skip the otherwise needless lookup. llvm::DIType TC = getTypeOrNull(Ty); if (TC && TC.isForwardDecl()) ReplaceMap.push_back(std::make_pair(TyPtr, static_cast(TC))); else if (ObjCInterfaceDecl* Decl = getObjCInterfaceDecl(Ty)) { // Interface types may have elements added to them by a // subsequent implementation or extension, so we keep them in // the ObjCInterfaceCache together with a checksum. Instead of // the (possibly) incomplete interface type, we return a forward // declaration that gets RAUW'd in CGDebugInfo::finalize(). std::pair &V = ObjCInterfaceCache[TyPtr]; if (V.first) return llvm::DIType(cast(V.first)); TC = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, Decl->getName(), TheCU, Unit, getLineNumber(Decl->getLocation()), TheCU.getLanguage()); // Store the forward declaration in the cache. V.first = TC; V.second = Checksum(Decl); // Register the type for replacement in finalize(). ReplaceMap.push_back(std::make_pair(TyPtr, static_cast(TC))); return TC; } if (!Res.isForwardDecl()) CompletedTypeCache[TyPtr] = Res; return Res; } /// Currently the checksum of an interface includes the number of /// ivars and property accessors. unsigned CGDebugInfo::Checksum(const ObjCInterfaceDecl *ID) { // The assumption is that the number of ivars can only increase // monotonically, so it is safe to just use their current number as // a checksum. unsigned Sum = 0; for (const ObjCIvarDecl *Ivar = ID->all_declared_ivar_begin(); Ivar != 0; Ivar = Ivar->getNextIvar()) ++Sum; return Sum; } ObjCInterfaceDecl *CGDebugInfo::getObjCInterfaceDecl(QualType Ty) { switch (Ty->getTypeClass()) { case Type::ObjCObjectPointer: return getObjCInterfaceDecl(cast(Ty) ->getPointeeType()); case Type::ObjCInterface: return cast(Ty)->getDecl(); default: return 0; } } /// CreateTypeNode - Create a new debug type node. llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit) { // Handle qualifiers, which recursively handles what they refer to. if (Ty.hasLocalQualifiers()) return CreateQualifiedType(Ty, Unit); const char *Diag = 0; // Work out details of type. switch (Ty->getTypeClass()) { #define TYPE(Class, Base) #define ABSTRACT_TYPE(Class, Base) #define NON_CANONICAL_TYPE(Class, Base) #define DEPENDENT_TYPE(Class, Base) case Type::Class: #include "clang/AST/TypeNodes.def" llvm_unreachable("Dependent types cannot show up in debug information"); case Type::ExtVector: case Type::Vector: return CreateType(cast(Ty), Unit); case Type::ObjCObjectPointer: return CreateType(cast(Ty), Unit); case Type::ObjCObject: return CreateType(cast(Ty), Unit); case Type::ObjCInterface: return CreateType(cast(Ty), Unit); case Type::Builtin: return CreateType(cast(Ty)); case Type::Complex: return CreateType(cast(Ty)); case Type::Pointer: return CreateType(cast(Ty), Unit); case Type::Decayed: // Decayed types are just pointers in LLVM and DWARF. return CreateType( cast(cast(Ty)->getDecayedType()), Unit); case Type::BlockPointer: return CreateType(cast(Ty), Unit); case Type::Typedef: return CreateType(cast(Ty), Unit); case Type::Record: return CreateType(cast(Ty)); case Type::Enum: return CreateEnumType(cast(Ty)); case Type::FunctionProto: case Type::FunctionNoProto: return CreateType(cast(Ty), Unit); case Type::ConstantArray: case Type::VariableArray: case Type::IncompleteArray: return CreateType(cast(Ty), Unit); case Type::LValueReference: return CreateType(cast(Ty), Unit); case Type::RValueReference: return CreateType(cast(Ty), Unit); case Type::MemberPointer: return CreateType(cast(Ty), Unit); case Type::Atomic: return CreateType(cast(Ty), Unit); case Type::Attributed: case Type::TemplateSpecialization: case Type::Elaborated: case Type::Paren: case Type::SubstTemplateTypeParm: case Type::TypeOfExpr: case Type::TypeOf: case Type::Decltype: case Type::UnaryTransform: case Type::PackExpansion: llvm_unreachable("type should have been unwrapped!"); case Type::Auto: Diag = "auto"; break; } assert(Diag && "Fall through without a diagnostic?"); unsigned DiagID = CGM.getDiags().getCustomDiagID(DiagnosticsEngine::Error, "debug information for %0 is not yet supported"); CGM.getDiags().Report(DiagID) << Diag; return llvm::DIType(); } /// getOrCreateLimitedType - Get the type from the cache or create a new /// limited type if necessary. llvm::DIType CGDebugInfo::getOrCreateLimitedType(const RecordType *Ty, llvm::DIFile Unit) { QualType QTy(Ty, 0); llvm::DICompositeType T(getTypeOrNull(QTy)); // We may have cached a forward decl when we could have created // a non-forward decl. Go ahead and create a non-forward decl // now. if (T && !T.isForwardDecl()) return T; // Otherwise create the type. llvm::DICompositeType Res = CreateLimitedType(Ty); // Propagate members from the declaration to the definition // CreateType(const RecordType*) will overwrite this with the members in the // correct order if the full type is needed. Res.setTypeArray(T.getTypeArray()); if (T && T.isForwardDecl()) ReplaceMap.push_back( std::make_pair(QTy.getAsOpaquePtr(), static_cast(T))); // And update the type cache. TypeCache[QTy.getAsOpaquePtr()] = Res; return Res; } // TODO: Currently used for context chains when limiting debug info. llvm::DICompositeType CGDebugInfo::CreateLimitedType(const RecordType *Ty) { RecordDecl *RD = Ty->getDecl(); // Get overall information about the record type for the debug info. llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation()); unsigned Line = getLineNumber(RD->getLocation()); StringRef RDName = getClassName(RD); llvm::DIDescriptor RDContext = getContextDescriptor(cast(RD->getDeclContext())); // If we ended up creating the type during the context chain construction, // just return that. // FIXME: this could be dealt with better if the type was recorded as // completed before we started this (see the CompletedTypeCache usage in // CGDebugInfo::CreateTypeDefinition(const RecordType*) - that would need to // be pushed to before context creation, but after it was known to be // destined for completion (might still have an issue if this caller only // required a declaration but the context construction ended up creating a // definition) llvm::DICompositeType T(getTypeOrNull(CGM.getContext().getRecordType(RD))); if (T && (!T.isForwardDecl() || !RD->getDefinition())) return T; // If this is just a forward or incomplete declaration, construct an // appropriately marked node and just return it. const RecordDecl *D = RD->getDefinition(); if (!D || !D->isCompleteDefinition()) return getOrCreateRecordFwdDecl(Ty, RDContext); uint64_t Size = CGM.getContext().getTypeSize(Ty); uint64_t Align = CGM.getContext().getTypeAlign(Ty); llvm::DICompositeType RealDecl; SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU); if (RD->isUnion()) RealDecl = DBuilder.createUnionType(RDContext, RDName, DefUnit, Line, Size, Align, 0, llvm::DIArray(), 0, FullName); else if (RD->isClass()) { // FIXME: This could be a struct type giving a default visibility different // than C++ class type, but needs llvm metadata changes first. RealDecl = DBuilder.createClassType(RDContext, RDName, DefUnit, Line, Size, Align, 0, 0, llvm::DIType(), llvm::DIArray(), llvm::DIType(), llvm::DIArray(), FullName); } else RealDecl = DBuilder.createStructType(RDContext, RDName, DefUnit, Line, Size, Align, 0, llvm::DIType(), llvm::DIArray(), 0, llvm::DIType(), FullName); RegionMap[Ty->getDecl()] = llvm::WeakVH(RealDecl); TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = RealDecl; if (const ClassTemplateSpecializationDecl *TSpecial = dyn_cast(RD)) RealDecl.setTypeArray(llvm::DIArray(), CollectCXXTemplateParams(TSpecial, DefUnit)); return RealDecl; } void CGDebugInfo::CollectContainingType(const CXXRecordDecl *RD, llvm::DICompositeType RealDecl) { // A class's primary base or the class itself contains the vtable. llvm::DICompositeType ContainingType; const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); if (const CXXRecordDecl *PBase = RL.getPrimaryBase()) { // Seek non virtual primary base root. while (1) { const ASTRecordLayout &BRL = CGM.getContext().getASTRecordLayout(PBase); const CXXRecordDecl *PBT = BRL.getPrimaryBase(); if (PBT && !BRL.isPrimaryBaseVirtual()) PBase = PBT; else break; } ContainingType = llvm::DICompositeType( getOrCreateType(QualType(PBase->getTypeForDecl(), 0), getOrCreateFile(RD->getLocation()))); } else if (RD->isDynamicClass()) ContainingType = RealDecl; RealDecl.setContainingType(ContainingType); } /// CreateMemberType - Create new member and increase Offset by FType's size. llvm::DIType CGDebugInfo::CreateMemberType(llvm::DIFile Unit, QualType FType, StringRef Name, uint64_t *Offset) { llvm::DIType FieldTy = CGDebugInfo::getOrCreateType(FType, Unit); uint64_t FieldSize = CGM.getContext().getTypeSize(FType); unsigned FieldAlign = CGM.getContext().getTypeAlign(FType); llvm::DIType Ty = DBuilder.createMemberType(Unit, Name, Unit, 0, FieldSize, FieldAlign, *Offset, 0, FieldTy); *Offset += FieldSize; return Ty; } llvm::DIDescriptor CGDebugInfo::getDeclarationOrDefinition(const Decl *D) { // We only need a declaration (not a definition) of the type - so use whatever // we would otherwise do to get a type for a pointee. (forward declarations in // limited debug info, full definitions (if the type definition is available) // in unlimited debug info) if (const TypeDecl *TD = dyn_cast(D)) return getOrCreateType(CGM.getContext().getTypeDeclType(TD), getOrCreateFile(TD->getLocation())); // Otherwise fall back to a fairly rudimentary cache of existing declarations. // This doesn't handle providing declarations (for functions or variables) for // entities without definitions in this TU, nor when the definition proceeds // the call to this function. // FIXME: This should be split out into more specific maps with support for // emitting forward declarations and merging definitions with declarations, // the same way as we do for types. llvm::DenseMap::iterator I = DeclCache.find(D->getCanonicalDecl()); if (I == DeclCache.end()) return llvm::DIDescriptor(); llvm::Value *V = I->second; return llvm::DIDescriptor(dyn_cast_or_null(V)); } /// getFunctionDeclaration - Return debug info descriptor to describe method /// declaration for the given method definition. llvm::DISubprogram CGDebugInfo::getFunctionDeclaration(const Decl *D) { if (!D || DebugKind == CodeGenOptions::DebugLineTablesOnly) return llvm::DISubprogram(); const FunctionDecl *FD = dyn_cast(D); if (!FD) return llvm::DISubprogram(); // Setup context. llvm::DIScope S = getContextDescriptor(cast(D->getDeclContext())); llvm::DenseMap::iterator MI = SPCache.find(FD->getCanonicalDecl()); if (MI == SPCache.end()) { if (const CXXMethodDecl *MD = dyn_cast(FD->getCanonicalDecl())) { llvm::DICompositeType T(S); llvm::DISubprogram SP = CreateCXXMemberFunction(MD, getOrCreateFile(MD->getLocation()), T); T.addMember(SP); return SP; } } if (MI != SPCache.end()) { llvm::Value *V = MI->second; llvm::DISubprogram SP(dyn_cast_or_null(V)); if (SP.isSubprogram() && !SP.isDefinition()) return SP; } for (FunctionDecl::redecl_iterator I = FD->redecls_begin(), E = FD->redecls_end(); I != E; ++I) { const FunctionDecl *NextFD = *I; llvm::DenseMap::iterator MI = SPCache.find(NextFD->getCanonicalDecl()); if (MI != SPCache.end()) { llvm::Value *V = MI->second; llvm::DISubprogram SP(dyn_cast_or_null(V)); if (SP.isSubprogram() && !SP.isDefinition()) return SP; } } return llvm::DISubprogram(); } // getOrCreateFunctionType - Construct DIType. If it is a c++ method, include // implicit parameter "this". llvm::DICompositeType CGDebugInfo::getOrCreateFunctionType(const Decl *D, QualType FnType, llvm::DIFile F) { if (!D || DebugKind == CodeGenOptions::DebugLineTablesOnly) // Create fake but valid subroutine type. Otherwise // llvm::DISubprogram::Verify() would return false, and // subprogram DIE will miss DW_AT_decl_file and // DW_AT_decl_line fields. return DBuilder.createSubroutineType(F, DBuilder.getOrCreateArray(None)); if (const CXXMethodDecl *Method = dyn_cast(D)) return getOrCreateMethodType(Method, F); if (const ObjCMethodDecl *OMethod = dyn_cast(D)) { // Add "self" and "_cmd" SmallVector Elts; // First element is always return type. For 'void' functions it is NULL. QualType ResultTy = OMethod->getResultType(); // Replace the instancetype keyword with the actual type. if (ResultTy == CGM.getContext().getObjCInstanceType()) ResultTy = CGM.getContext().getPointerType( QualType(OMethod->getClassInterface()->getTypeForDecl(), 0)); Elts.push_back(getOrCreateType(ResultTy, F)); // "self" pointer is always first argument. QualType SelfDeclTy = OMethod->getSelfDecl()->getType(); llvm::DIType SelfTy = getOrCreateType(SelfDeclTy, F); Elts.push_back(CreateSelfType(SelfDeclTy, SelfTy)); // "_cmd" pointer is always second argument. llvm::DIType CmdTy = getOrCreateType(OMethod->getCmdDecl()->getType(), F); Elts.push_back(DBuilder.createArtificialType(CmdTy)); // Get rest of the arguments. for (ObjCMethodDecl::param_const_iterator PI = OMethod->param_begin(), PE = OMethod->param_end(); PI != PE; ++PI) Elts.push_back(getOrCreateType((*PI)->getType(), F)); llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(Elts); return DBuilder.createSubroutineType(F, EltTypeArray); } + + // Variadic function. + if (const FunctionDecl *FD = dyn_cast(D)) + if (FD->isVariadic()) { + SmallVector EltTys; + EltTys.push_back(getOrCreateType(FD->getResultType(), F)); + if (const FunctionProtoType *FPT = dyn_cast(FnType)) + for (unsigned i = 0, e = FPT->getNumArgs(); i != e; ++i) + EltTys.push_back(getOrCreateType(FPT->getArgType(i), F)); + EltTys.push_back(DBuilder.createUnspecifiedParameter()); + llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(EltTys); + return DBuilder.createSubroutineType(F, EltTypeArray); + } + return llvm::DICompositeType(getOrCreateType(FnType, F)); } /// EmitFunctionStart - Constructs the debug code for entering a function. void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType, llvm::Function *Fn, CGBuilderTy &Builder) { StringRef Name; StringRef LinkageName; FnBeginRegionCount.push_back(LexicalBlockStack.size()); const Decl *D = GD.getDecl(); // Function may lack declaration in source code if it is created by Clang // CodeGen (examples: _GLOBAL__I_a, __cxx_global_array_dtor, thunk). bool HasDecl = (D != 0); // Use the location of the declaration. SourceLocation Loc; if (HasDecl) Loc = D->getLocation(); unsigned Flags = 0; llvm::DIFile Unit = getOrCreateFile(Loc); llvm::DIDescriptor FDContext(Unit); llvm::DIArray TParamsArray; if (!HasDecl) { // Use llvm function name. LinkageName = Fn->getName(); } else if (const FunctionDecl *FD = dyn_cast(D)) { // If there is a DISubprogram for this function available then use it. llvm::DenseMap::iterator FI = SPCache.find(FD->getCanonicalDecl()); if (FI != SPCache.end()) { llvm::Value *V = FI->second; llvm::DIDescriptor SP(dyn_cast_or_null(V)); if (SP.isSubprogram() && llvm::DISubprogram(SP).isDefinition()) { llvm::MDNode *SPN = SP; LexicalBlockStack.push_back(SPN); RegionMap[D] = llvm::WeakVH(SP); return; } } Name = getFunctionName(FD); // Use mangled name as linkage name for C/C++ functions. if (FD->hasPrototype()) { LinkageName = CGM.getMangledName(GD); Flags |= llvm::DIDescriptor::FlagPrototyped; } // No need to replicate the linkage name if it isn't different from the // subprogram name, no need to have it at all unless coverage is enabled or // debug is set to more than just line tables. if (LinkageName == Name || (!CGM.getCodeGenOpts().EmitGcovArcs && !CGM.getCodeGenOpts().EmitGcovNotes && DebugKind <= CodeGenOptions::DebugLineTablesOnly)) LinkageName = StringRef(); if (DebugKind >= CodeGenOptions::LimitedDebugInfo) { if (const NamespaceDecl *NSDecl = dyn_cast_or_null(FD->getDeclContext())) FDContext = getOrCreateNameSpace(NSDecl); else if (const RecordDecl *RDecl = dyn_cast_or_null(FD->getDeclContext())) FDContext = getContextDescriptor(cast(RDecl)); // Collect template parameters. TParamsArray = CollectFunctionTemplateParams(FD, Unit); } } else if (const ObjCMethodDecl *OMD = dyn_cast(D)) { Name = getObjCMethodName(OMD); Flags |= llvm::DIDescriptor::FlagPrototyped; } else { // Use llvm function name. Name = Fn->getName(); Flags |= llvm::DIDescriptor::FlagPrototyped; } if (!Name.empty() && Name[0] == '\01') Name = Name.substr(1); unsigned LineNo = getLineNumber(Loc); if (!HasDecl || D->isImplicit()) Flags |= llvm::DIDescriptor::FlagArtificial; llvm::DISubprogram SP = DBuilder.createFunction(FDContext, Name, LinkageName, Unit, LineNo, getOrCreateFunctionType(D, FnType, Unit), Fn->hasInternalLinkage(), true /*definition*/, getLineNumber(CurLoc), Flags, CGM.getLangOpts().Optimize, Fn, TParamsArray, getFunctionDeclaration(D)); if (HasDecl) DeclCache.insert(std::make_pair(D->getCanonicalDecl(), llvm::WeakVH(SP))); // Push function on region stack. llvm::MDNode *SPN = SP; LexicalBlockStack.push_back(SPN); if (HasDecl) RegionMap[D] = llvm::WeakVH(SP); } /// EmitLocation - Emit metadata to indicate a change in line/column /// information in the source file. If the location is invalid, the /// previous location will be reused. void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc, bool ForceColumnInfo) { // Update our current location setLocation(Loc); if (CurLoc.isInvalid() || CurLoc.isMacroID()) return; // Don't bother if things are the same as last time. SourceManager &SM = CGM.getContext().getSourceManager(); if (CurLoc == PrevLoc || SM.getExpansionLoc(CurLoc) == SM.getExpansionLoc(PrevLoc)) // New Builder may not be in sync with CGDebugInfo. if (!Builder.getCurrentDebugLocation().isUnknown() && Builder.getCurrentDebugLocation().getScope(CGM.getLLVMContext()) == LexicalBlockStack.back()) return; // Update last state. PrevLoc = CurLoc; llvm::MDNode *Scope = LexicalBlockStack.back(); Builder.SetCurrentDebugLocation(llvm::DebugLoc::get (getLineNumber(CurLoc), getColumnNumber(CurLoc, ForceColumnInfo), Scope)); } /// CreateLexicalBlock - Creates a new lexical block node and pushes it on /// the stack. void CGDebugInfo::CreateLexicalBlock(SourceLocation Loc) { llvm::DIDescriptor D = DBuilder.createLexicalBlock(LexicalBlockStack.empty() ? llvm::DIDescriptor() : llvm::DIDescriptor(LexicalBlockStack.back()), getOrCreateFile(CurLoc), getLineNumber(CurLoc), getColumnNumber(CurLoc)); llvm::MDNode *DN = D; LexicalBlockStack.push_back(DN); } /// EmitLexicalBlockStart - Constructs the debug code for entering a declarative /// region - beginning of a DW_TAG_lexical_block. void CGDebugInfo::EmitLexicalBlockStart(CGBuilderTy &Builder, SourceLocation Loc) { // Set our current location. setLocation(Loc); // Create a new lexical block and push it on the stack. CreateLexicalBlock(Loc); // Emit a line table change for the current location inside the new scope. Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(getLineNumber(Loc), getColumnNumber(Loc), LexicalBlockStack.back())); } /// EmitLexicalBlockEnd - Constructs the debug code for exiting a declarative /// region - end of a DW_TAG_lexical_block. void CGDebugInfo::EmitLexicalBlockEnd(CGBuilderTy &Builder, SourceLocation Loc) { assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!"); // Provide an entry in the line table for the end of the block. EmitLocation(Builder, Loc); LexicalBlockStack.pop_back(); } /// EmitFunctionEnd - Constructs the debug code for exiting a function. void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder) { assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!"); unsigned RCount = FnBeginRegionCount.back(); assert(RCount <= LexicalBlockStack.size() && "Region stack mismatch"); // Pop all regions for this function. while (LexicalBlockStack.size() != RCount) EmitLexicalBlockEnd(Builder, CurLoc); FnBeginRegionCount.pop_back(); } // EmitTypeForVarWithBlocksAttr - Build up structure info for the byref. // See BuildByRefType. llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD, uint64_t *XOffset) { SmallVector EltTys; QualType FType; uint64_t FieldSize, FieldOffset; unsigned FieldAlign; llvm::DIFile Unit = getOrCreateFile(VD->getLocation()); QualType Type = VD->getType(); FieldOffset = 0; FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy); EltTys.push_back(CreateMemberType(Unit, FType, "__isa", &FieldOffset)); EltTys.push_back(CreateMemberType(Unit, FType, "__forwarding", &FieldOffset)); FType = CGM.getContext().IntTy; EltTys.push_back(CreateMemberType(Unit, FType, "__flags", &FieldOffset)); EltTys.push_back(CreateMemberType(Unit, FType, "__size", &FieldOffset)); bool HasCopyAndDispose = CGM.getContext().BlockRequiresCopying(Type, VD); if (HasCopyAndDispose) { FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy); EltTys.push_back(CreateMemberType(Unit, FType, "__copy_helper", &FieldOffset)); EltTys.push_back(CreateMemberType(Unit, FType, "__destroy_helper", &FieldOffset)); } bool HasByrefExtendedLayout; Qualifiers::ObjCLifetime Lifetime; if (CGM.getContext().getByrefLifetime(Type, Lifetime, HasByrefExtendedLayout) && HasByrefExtendedLayout) { FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy); EltTys.push_back(CreateMemberType(Unit, FType, "__byref_variable_layout", &FieldOffset)); } CharUnits Align = CGM.getContext().getDeclAlign(VD); if (Align > CGM.getContext().toCharUnitsFromBits( CGM.getTarget().getPointerAlign(0))) { CharUnits FieldOffsetInBytes = CGM.getContext().toCharUnitsFromBits(FieldOffset); CharUnits AlignedOffsetInBytes = FieldOffsetInBytes.RoundUpToAlignment(Align); CharUnits NumPaddingBytes = AlignedOffsetInBytes - FieldOffsetInBytes; if (NumPaddingBytes.isPositive()) { llvm::APInt pad(32, NumPaddingBytes.getQuantity()); FType = CGM.getContext().getConstantArrayType(CGM.getContext().CharTy, pad, ArrayType::Normal, 0); EltTys.push_back(CreateMemberType(Unit, FType, "", &FieldOffset)); } } FType = Type; llvm::DIType FieldTy = CGDebugInfo::getOrCreateType(FType, Unit); FieldSize = CGM.getContext().getTypeSize(FType); FieldAlign = CGM.getContext().toBits(Align); *XOffset = FieldOffset; FieldTy = DBuilder.createMemberType(Unit, VD->getName(), Unit, 0, FieldSize, FieldAlign, FieldOffset, 0, FieldTy); EltTys.push_back(FieldTy); FieldOffset += FieldSize; llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys); unsigned Flags = llvm::DIDescriptor::FlagBlockByrefStruct; return DBuilder.createStructType(Unit, "", Unit, 0, FieldOffset, 0, Flags, llvm::DIType(), Elements); } /// EmitDeclare - Emit local variable declaration debug info. void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag, llvm::Value *Storage, unsigned ArgNo, CGBuilderTy &Builder) { assert(DebugKind >= CodeGenOptions::LimitedDebugInfo); assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!"); bool Unwritten = VD->isImplicit() || (isa(VD->getDeclContext()) && cast(VD->getDeclContext())->isImplicit()); llvm::DIFile Unit; if (!Unwritten) Unit = getOrCreateFile(VD->getLocation()); llvm::DIType Ty; uint64_t XOffset = 0; if (VD->hasAttr()) Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset); else Ty = getOrCreateType(VD->getType(), Unit); // If there is no debug info for this type then do not emit debug info // for this variable. if (!Ty) return; // Get location information. unsigned Line = 0; unsigned Column = 0; if (!Unwritten) { Line = getLineNumber(VD->getLocation()); Column = getColumnNumber(VD->getLocation()); } unsigned Flags = 0; if (VD->isImplicit()) Flags |= llvm::DIDescriptor::FlagArtificial; // If this is the first argument and it is implicit then // give it an object pointer flag. // FIXME: There has to be a better way to do this, but for static // functions there won't be an implicit param at arg1 and // otherwise it is 'self' or 'this'. if (isa(VD) && ArgNo == 1) Flags |= llvm::DIDescriptor::FlagObjectPointer; if (llvm::Argument *Arg = dyn_cast(Storage)) if (Arg->getType()->isPointerTy() && !Arg->hasByValAttr() && !VD->getType()->isPointerType()) Flags |= llvm::DIDescriptor::FlagIndirectVariable; llvm::MDNode *Scope = LexicalBlockStack.back(); StringRef Name = VD->getName(); if (!Name.empty()) { if (VD->hasAttr()) { CharUnits offset = CharUnits::fromQuantity(32); SmallVector addr; llvm::Type *Int64Ty = CGM.Int64Ty; addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus)); // offset of __forwarding field offset = CGM.getContext().toCharUnitsFromBits( CGM.getTarget().getPointerWidth(0)); addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity())); addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref)); addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus)); // offset of x field offset = CGM.getContext().toCharUnitsFromBits(XOffset); addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity())); // Create the descriptor for the variable. llvm::DIVariable D = DBuilder.createComplexVariable(Tag, llvm::DIDescriptor(Scope), VD->getName(), Unit, Line, Ty, addr, ArgNo); // Insert an llvm.dbg.declare into the current block. llvm::Instruction *Call = DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock()); Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope)); return; } else if (isa(VD->getType())) Flags |= llvm::DIDescriptor::FlagIndirectVariable; } else if (const RecordType *RT = dyn_cast(VD->getType())) { // If VD is an anonymous union then Storage represents value for // all union fields. const RecordDecl *RD = cast(RT->getDecl()); if (RD->isUnion() && RD->isAnonymousStructOrUnion()) { for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); I != E; ++I) { FieldDecl *Field = *I; llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit); StringRef FieldName = Field->getName(); // Ignore unnamed fields. Do not ignore unnamed records. if (FieldName.empty() && !isa(Field->getType())) continue; // Use VarDecl's Tag, Scope and Line number. llvm::DIVariable D = DBuilder.createLocalVariable(Tag, llvm::DIDescriptor(Scope), FieldName, Unit, Line, FieldTy, CGM.getLangOpts().Optimize, Flags, ArgNo); // Insert an llvm.dbg.declare into the current block. llvm::Instruction *Call = DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock()); Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope)); } return; } } // Create the descriptor for the variable. llvm::DIVariable D = DBuilder.createLocalVariable(Tag, llvm::DIDescriptor(Scope), Name, Unit, Line, Ty, CGM.getLangOpts().Optimize, Flags, ArgNo); // Insert an llvm.dbg.declare into the current block. llvm::Instruction *Call = DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock()); Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope)); } void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD, llvm::Value *Storage, CGBuilderTy &Builder) { assert(DebugKind >= CodeGenOptions::LimitedDebugInfo); EmitDeclare(VD, llvm::dwarf::DW_TAG_auto_variable, Storage, 0, Builder); } /// Look up the completed type for a self pointer in the TypeCache and /// create a copy of it with the ObjectPointer and Artificial flags /// set. If the type is not cached, a new one is created. This should /// never happen though, since creating a type for the implicit self /// argument implies that we already parsed the interface definition /// and the ivar declarations in the implementation. llvm::DIType CGDebugInfo::CreateSelfType(const QualType &QualTy, llvm::DIType Ty) { llvm::DIType CachedTy = getTypeOrNull(QualTy); if (CachedTy) Ty = CachedTy; else DEBUG(llvm::dbgs() << "No cached type for self."); return DBuilder.createObjectPointerType(Ty); } void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(const VarDecl *VD, llvm::Value *Storage, CGBuilderTy &Builder, const CGBlockInfo &blockInfo) { assert(DebugKind >= CodeGenOptions::LimitedDebugInfo); assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!"); if (Builder.GetInsertBlock() == 0) return; bool isByRef = VD->hasAttr(); uint64_t XOffset = 0; llvm::DIFile Unit = getOrCreateFile(VD->getLocation()); llvm::DIType Ty; if (isByRef) Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset); else Ty = getOrCreateType(VD->getType(), Unit); // Self is passed along as an implicit non-arg variable in a // block. Mark it as the object pointer. if (isa(VD) && VD->getName() == "self") Ty = CreateSelfType(VD->getType(), Ty); // Get location information. unsigned Line = getLineNumber(VD->getLocation()); unsigned Column = getColumnNumber(VD->getLocation()); const llvm::DataLayout &target = CGM.getDataLayout(); CharUnits offset = CharUnits::fromQuantity( target.getStructLayout(blockInfo.StructureType) ->getElementOffset(blockInfo.getCapture(VD).getIndex())); SmallVector addr; llvm::Type *Int64Ty = CGM.Int64Ty; if (isa(Storage)) addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref)); addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus)); addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity())); if (isByRef) { addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref)); addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus)); // offset of __forwarding field offset = CGM.getContext() .toCharUnitsFromBits(target.getPointerSizeInBits(0)); addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity())); addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref)); addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus)); // offset of x field offset = CGM.getContext().toCharUnitsFromBits(XOffset); addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity())); } // Create the descriptor for the variable. llvm::DIVariable D = DBuilder.createComplexVariable(llvm::dwarf::DW_TAG_auto_variable, llvm::DIDescriptor(LexicalBlockStack.back()), VD->getName(), Unit, Line, Ty, addr); // Insert an llvm.dbg.declare into the current block. llvm::Instruction *Call = DBuilder.insertDeclare(Storage, D, Builder.GetInsertPoint()); Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, LexicalBlockStack.back())); } /// EmitDeclareOfArgVariable - Emit call to llvm.dbg.declare for an argument /// variable declaration. void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *VD, llvm::Value *AI, unsigned ArgNo, CGBuilderTy &Builder) { assert(DebugKind >= CodeGenOptions::LimitedDebugInfo); EmitDeclare(VD, llvm::dwarf::DW_TAG_arg_variable, AI, ArgNo, Builder); } namespace { struct BlockLayoutChunk { uint64_t OffsetInBits; const BlockDecl::Capture *Capture; }; bool operator<(const BlockLayoutChunk &l, const BlockLayoutChunk &r) { return l.OffsetInBits < r.OffsetInBits; } } void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, llvm::Value *Arg, llvm::Value *LocalAddr, CGBuilderTy &Builder) { assert(DebugKind >= CodeGenOptions::LimitedDebugInfo); ASTContext &C = CGM.getContext(); const BlockDecl *blockDecl = block.getBlockDecl(); // Collect some general information about the block's location. SourceLocation loc = blockDecl->getCaretLocation(); llvm::DIFile tunit = getOrCreateFile(loc); unsigned line = getLineNumber(loc); unsigned column = getColumnNumber(loc); // Build the debug-info type for the block literal. getContextDescriptor(cast(blockDecl->getDeclContext())); const llvm::StructLayout *blockLayout = CGM.getDataLayout().getStructLayout(block.StructureType); SmallVector fields; fields.push_back(createFieldType("__isa", C.VoidPtrTy, 0, loc, AS_public, blockLayout->getElementOffsetInBits(0), tunit, tunit)); fields.push_back(createFieldType("__flags", C.IntTy, 0, loc, AS_public, blockLayout->getElementOffsetInBits(1), tunit, tunit)); fields.push_back(createFieldType("__reserved", C.IntTy, 0, loc, AS_public, blockLayout->getElementOffsetInBits(2), tunit, tunit)); fields.push_back(createFieldType("__FuncPtr", C.VoidPtrTy, 0, loc, AS_public, blockLayout->getElementOffsetInBits(3), tunit, tunit)); fields.push_back(createFieldType("__descriptor", C.getPointerType(block.NeedsCopyDispose ? C.getBlockDescriptorExtendedType() : C.getBlockDescriptorType()), 0, loc, AS_public, blockLayout->getElementOffsetInBits(4), tunit, tunit)); // We want to sort the captures by offset, not because DWARF // requires this, but because we're paranoid about debuggers. SmallVector chunks; // 'this' capture. if (blockDecl->capturesCXXThis()) { BlockLayoutChunk chunk; chunk.OffsetInBits = blockLayout->getElementOffsetInBits(block.CXXThisIndex); chunk.Capture = 0; chunks.push_back(chunk); } // Variable captures. for (BlockDecl::capture_const_iterator i = blockDecl->capture_begin(), e = blockDecl->capture_end(); i != e; ++i) { const BlockDecl::Capture &capture = *i; const VarDecl *variable = capture.getVariable(); const CGBlockInfo::Capture &captureInfo = block.getCapture(variable); // Ignore constant captures. if (captureInfo.isConstant()) continue; BlockLayoutChunk chunk; chunk.OffsetInBits = blockLayout->getElementOffsetInBits(captureInfo.getIndex()); chunk.Capture = &capture; chunks.push_back(chunk); } // Sort by offset. llvm::array_pod_sort(chunks.begin(), chunks.end()); for (SmallVectorImpl::iterator i = chunks.begin(), e = chunks.end(); i != e; ++i) { uint64_t offsetInBits = i->OffsetInBits; const BlockDecl::Capture *capture = i->Capture; // If we have a null capture, this must be the C++ 'this' capture. if (!capture) { const CXXMethodDecl *method = cast(blockDecl->getNonClosureContext()); QualType type = method->getThisType(C); fields.push_back(createFieldType("this", type, 0, loc, AS_public, offsetInBits, tunit, tunit)); continue; } const VarDecl *variable = capture->getVariable(); StringRef name = variable->getName(); llvm::DIType fieldType; if (capture->isByRef()) { std::pair ptrInfo = C.getTypeInfo(C.VoidPtrTy); // FIXME: this creates a second copy of this type! uint64_t xoffset; fieldType = EmitTypeForVarWithBlocksAttr(variable, &xoffset); fieldType = DBuilder.createPointerType(fieldType, ptrInfo.first); fieldType = DBuilder.createMemberType(tunit, name, tunit, line, ptrInfo.first, ptrInfo.second, offsetInBits, 0, fieldType); } else { fieldType = createFieldType(name, variable->getType(), 0, loc, AS_public, offsetInBits, tunit, tunit); } fields.push_back(fieldType); } SmallString<36> typeName; llvm::raw_svector_ostream(typeName) << "__block_literal_" << CGM.getUniqueBlockCount(); llvm::DIArray fieldsArray = DBuilder.getOrCreateArray(fields); llvm::DIType type = DBuilder.createStructType(tunit, typeName.str(), tunit, line, CGM.getContext().toBits(block.BlockSize), CGM.getContext().toBits(block.BlockAlign), 0, llvm::DIType(), fieldsArray); type = DBuilder.createPointerType(type, CGM.PointerWidthInBits); // Get overall information about the block. unsigned flags = llvm::DIDescriptor::FlagArtificial; llvm::MDNode *scope = LexicalBlockStack.back(); // Create the descriptor for the parameter. llvm::DIVariable debugVar = DBuilder.createLocalVariable(llvm::dwarf::DW_TAG_arg_variable, llvm::DIDescriptor(scope), Arg->getName(), tunit, line, type, CGM.getLangOpts().Optimize, flags, cast(Arg)->getArgNo() + 1); if (LocalAddr) { // Insert an llvm.dbg.value into the current block. llvm::Instruction *DbgVal = DBuilder.insertDbgValueIntrinsic(LocalAddr, 0, debugVar, Builder.GetInsertBlock()); DbgVal->setDebugLoc(llvm::DebugLoc::get(line, column, scope)); } // Insert an llvm.dbg.declare into the current block. llvm::Instruction *DbgDecl = DBuilder.insertDeclare(Arg, debugVar, Builder.GetInsertBlock()); DbgDecl->setDebugLoc(llvm::DebugLoc::get(line, column, scope)); } /// If D is an out-of-class definition of a static data member of a class, find /// its corresponding in-class declaration. llvm::DIDerivedType CGDebugInfo::getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D) { if (!D->isStaticDataMember()) return llvm::DIDerivedType(); llvm::DenseMap::iterator MI = StaticDataMemberCache.find(D->getCanonicalDecl()); if (MI != StaticDataMemberCache.end()) { assert(MI->second && "Static data member declaration should still exist"); return llvm::DIDerivedType(cast(MI->second)); } // If the member wasn't found in the cache, lazily construct and add it to the // type (used when a limited form of the type is emitted). llvm::DICompositeType Ctxt( getContextDescriptor(cast(D->getDeclContext()))); llvm::DIDerivedType T = CreateRecordStaticField(D, Ctxt); Ctxt.addMember(T); return T; } /// EmitGlobalVariable - Emit information about a global variable. void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, const VarDecl *D) { assert(DebugKind >= CodeGenOptions::LimitedDebugInfo); // Create global variable debug descriptor. llvm::DIFile Unit = getOrCreateFile(D->getLocation()); unsigned LineNo = getLineNumber(D->getLocation()); setLocation(D->getLocation()); QualType T = D->getType(); if (T->isIncompleteArrayType()) { // CodeGen turns int[] into int[1] so we'll do the same here. llvm::APInt ConstVal(32, 1); QualType ET = CGM.getContext().getAsArrayType(T)->getElementType(); T = CGM.getContext().getConstantArrayType(ET, ConstVal, ArrayType::Normal, 0); } StringRef DeclName = D->getName(); StringRef LinkageName; if (D->getDeclContext() && !isa(D->getDeclContext()) && !isa(D->getDeclContext())) LinkageName = Var->getName(); if (LinkageName == DeclName) LinkageName = StringRef(); llvm::DIDescriptor DContext = getContextDescriptor(dyn_cast(D->getDeclContext())); llvm::DIGlobalVariable GV = DBuilder.createStaticVariable( DContext, DeclName, LinkageName, Unit, LineNo, getOrCreateType(T, Unit), Var->hasInternalLinkage(), Var, getOrCreateStaticDataMemberDeclarationOrNull(D)); DeclCache.insert(std::make_pair(D->getCanonicalDecl(), llvm::WeakVH(GV))); } /// EmitGlobalVariable - Emit information about an objective-c interface. void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, ObjCInterfaceDecl *ID) { assert(DebugKind >= CodeGenOptions::LimitedDebugInfo); // Create global variable debug descriptor. llvm::DIFile Unit = getOrCreateFile(ID->getLocation()); unsigned LineNo = getLineNumber(ID->getLocation()); StringRef Name = ID->getName(); QualType T = CGM.getContext().getObjCInterfaceType(ID); if (T->isIncompleteArrayType()) { // CodeGen turns int[] into int[1] so we'll do the same here. llvm::APInt ConstVal(32, 1); QualType ET = CGM.getContext().getAsArrayType(T)->getElementType(); T = CGM.getContext().getConstantArrayType(ET, ConstVal, ArrayType::Normal, 0); } DBuilder.createGlobalVariable(Name, Unit, LineNo, getOrCreateType(T, Unit), Var->hasInternalLinkage(), Var); } /// EmitGlobalVariable - Emit global variable's debug info. void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, llvm::Constant *Init) { assert(DebugKind >= CodeGenOptions::LimitedDebugInfo); // Create the descriptor for the variable. llvm::DIFile Unit = getOrCreateFile(VD->getLocation()); StringRef Name = VD->getName(); llvm::DIType Ty = getOrCreateType(VD->getType(), Unit); if (const EnumConstantDecl *ECD = dyn_cast(VD)) { const EnumDecl *ED = cast(ECD->getDeclContext()); assert(isa(ED->getTypeForDecl()) && "Enum without EnumType?"); Ty = getOrCreateType(QualType(ED->getTypeForDecl(), 0), Unit); } // Do not use DIGlobalVariable for enums. if (Ty.getTag() == llvm::dwarf::DW_TAG_enumeration_type) return; llvm::DIGlobalVariable GV = DBuilder.createStaticVariable( Unit, Name, Name, Unit, getLineNumber(VD->getLocation()), Ty, true, Init, getOrCreateStaticDataMemberDeclarationOrNull(cast(VD))); DeclCache.insert(std::make_pair(VD->getCanonicalDecl(), llvm::WeakVH(GV))); } llvm::DIScope CGDebugInfo::getCurrentContextDescriptor(const Decl *D) { if (!LexicalBlockStack.empty()) return llvm::DIScope(LexicalBlockStack.back()); return getContextDescriptor(D); } void CGDebugInfo::EmitUsingDirective(const UsingDirectiveDecl &UD) { if (CGM.getCodeGenOpts().getDebugInfo() < CodeGenOptions::LimitedDebugInfo) return; DBuilder.createImportedModule( getCurrentContextDescriptor(cast(UD.getDeclContext())), getOrCreateNameSpace(UD.getNominatedNamespace()), getLineNumber(UD.getLocation())); } void CGDebugInfo::EmitUsingDecl(const UsingDecl &UD) { if (CGM.getCodeGenOpts().getDebugInfo() < CodeGenOptions::LimitedDebugInfo) return; assert(UD.shadow_size() && "We shouldn't be codegening an invalid UsingDecl containing no decls"); // Emitting one decl is sufficient - debuggers can detect that this is an // overloaded name & provide lookup for all the overloads. const UsingShadowDecl &USD = **UD.shadow_begin(); if (llvm::DIDescriptor Target = getDeclarationOrDefinition(USD.getUnderlyingDecl())) DBuilder.createImportedDeclaration( getCurrentContextDescriptor(cast(USD.getDeclContext())), Target, getLineNumber(USD.getLocation())); } llvm::DIImportedEntity CGDebugInfo::EmitNamespaceAlias(const NamespaceAliasDecl &NA) { if (CGM.getCodeGenOpts().getDebugInfo() < CodeGenOptions::LimitedDebugInfo) return llvm::DIImportedEntity(0); llvm::WeakVH &VH = NamespaceAliasCache[&NA]; if (VH) return llvm::DIImportedEntity(cast(VH)); llvm::DIImportedEntity R(0); if (const NamespaceAliasDecl *Underlying = dyn_cast(NA.getAliasedNamespace())) // This could cache & dedup here rather than relying on metadata deduping. R = DBuilder.createImportedModule( getCurrentContextDescriptor(cast(NA.getDeclContext())), EmitNamespaceAlias(*Underlying), getLineNumber(NA.getLocation()), NA.getName()); else R = DBuilder.createImportedModule( getCurrentContextDescriptor(cast(NA.getDeclContext())), getOrCreateNameSpace(cast(NA.getAliasedNamespace())), getLineNumber(NA.getLocation()), NA.getName()); VH = R; return R; } /// getOrCreateNamesSpace - Return namespace descriptor for the given /// namespace decl. llvm::DINameSpace CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl) { NSDecl = NSDecl->getCanonicalDecl(); llvm::DenseMap::iterator I = NameSpaceCache.find(NSDecl); if (I != NameSpaceCache.end()) return llvm::DINameSpace(cast(I->second)); unsigned LineNo = getLineNumber(NSDecl->getLocation()); llvm::DIFile FileD = getOrCreateFile(NSDecl->getLocation()); llvm::DIDescriptor Context = getContextDescriptor(dyn_cast(NSDecl->getDeclContext())); llvm::DINameSpace NS = DBuilder.createNameSpace(Context, NSDecl->getName(), FileD, LineNo); NameSpaceCache[NSDecl] = llvm::WeakVH(NS); return NS; } void CGDebugInfo::finalize() { for (std::vector >::const_iterator VI = ReplaceMap.begin(), VE = ReplaceMap.end(); VI != VE; ++VI) { llvm::DIType Ty, RepTy; // Verify that the debug info still exists. if (llvm::Value *V = VI->second) Ty = llvm::DIType(cast(V)); llvm::DenseMap::iterator it = TypeCache.find(VI->first); if (it != TypeCache.end()) { // Verify that the debug info still exists. if (llvm::Value *V = it->second) RepTy = llvm::DIType(cast(V)); } if (Ty && Ty.isForwardDecl() && RepTy) Ty.replaceAllUsesWith(RepTy); } // We keep our own list of retained types, because we need to look // up the final type in the type cache. for (std::vector::const_iterator RI = RetainedTypes.begin(), RE = RetainedTypes.end(); RI != RE; ++RI) DBuilder.retainType(llvm::DIType(cast(TypeCache[*RI]))); DBuilder.finalize(); } Index: stable/9/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp =================================================================== --- stable/9/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp (revision 283018) +++ stable/9/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp (revision 283019) @@ -1,478 +1,479 @@ //===--- ToolChain.cpp - Collections of tools for one platform ------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "Tools.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Driver/Action.h" #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" #include "clang/Driver/SanitizerArgs.h" #include "clang/Driver/ToolChain.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" using namespace clang::driver; using namespace clang; using namespace llvm::opt; ToolChain::ToolChain(const Driver &D, const llvm::Triple &T, const ArgList &A) : D(D), Triple(T), Args(A) { } ToolChain::~ToolChain() { } const Driver &ToolChain::getDriver() const { return D; } bool ToolChain::useIntegratedAs() const { return Args.hasFlag(options::OPT_integrated_as, options::OPT_no_integrated_as, IsIntegratedAssemblerDefault()); } const SanitizerArgs& ToolChain::getSanitizerArgs() const { if (!SanitizerArguments.get()) SanitizerArguments.reset(new SanitizerArgs(*this, Args)); return *SanitizerArguments.get(); } std::string ToolChain::getDefaultUniversalArchName() const { // In universal driver terms, the arch name accepted by -arch isn't exactly // the same as the ones that appear in the triple. Roughly speaking, this is // an inverse of the darwin::getArchTypeForDarwinArchName() function, but the // only interesting special case is powerpc. switch (Triple.getArch()) { case llvm::Triple::ppc: return "ppc"; case llvm::Triple::ppc64: return "ppc64"; case llvm::Triple::ppc64le: return "ppc64le"; default: return Triple.getArchName(); } } bool ToolChain::IsUnwindTablesDefault() const { return false; } Tool *ToolChain::getClang() const { if (!Clang) Clang.reset(new tools::Clang(*this)); return Clang.get(); } Tool *ToolChain::buildAssembler() const { return new tools::ClangAs(*this); } Tool *ToolChain::buildLinker() const { llvm_unreachable("Linking is not supported by this toolchain"); } Tool *ToolChain::getAssemble() const { if (!Assemble) Assemble.reset(buildAssembler()); return Assemble.get(); } Tool *ToolChain::getClangAs() const { if (!Assemble) Assemble.reset(new tools::ClangAs(*this)); return Assemble.get(); } Tool *ToolChain::getLink() const { if (!Link) Link.reset(buildLinker()); return Link.get(); } Tool *ToolChain::getTool(Action::ActionClass AC) const { switch (AC) { case Action::AssembleJobClass: return getAssemble(); case Action::LinkJobClass: return getLink(); case Action::InputClass: case Action::BindArchClass: case Action::LipoJobClass: case Action::DsymutilJobClass: case Action::VerifyJobClass: llvm_unreachable("Invalid tool kind."); case Action::CompileJobClass: case Action::PrecompileJobClass: case Action::PreprocessJobClass: case Action::AnalyzeJobClass: case Action::MigrateJobClass: return getClang(); } llvm_unreachable("Invalid tool kind."); } Tool *ToolChain::SelectTool(const JobAction &JA) const { if (getDriver().ShouldUseClangCompiler(JA)) return getClang(); Action::ActionClass AC = JA.getKind(); if (AC == Action::AssembleJobClass && useIntegratedAs()) return getClangAs(); return getTool(AC); } std::string ToolChain::GetFilePath(const char *Name) const { return D.GetFilePath(Name, *this); } std::string ToolChain::GetProgramPath(const char *Name) const { return D.GetProgramPath(Name, *this); } std::string ToolChain::GetLinkerPath() const { if (Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ)) { StringRef Suffix = A->getValue(); // If we're passed -fuse-ld= with no argument, or with the argument ld, // then use whatever the default system linker is. if (Suffix.empty() || Suffix == "ld") return GetProgramPath("ld"); llvm::SmallString<8> LinkerName("ld."); LinkerName.append(Suffix); std::string LinkerPath(GetProgramPath(LinkerName.c_str())); if (llvm::sys::fs::exists(LinkerPath)) return LinkerPath; getDriver().Diag(diag::err_drv_invalid_linker_name) << A->getAsString(Args); return ""; } return GetProgramPath("ld"); } types::ID ToolChain::LookupTypeForExtension(const char *Ext) const { return types::lookupTypeForExtension(Ext); } bool ToolChain::HasNativeLLVMSupport() const { return false; } ObjCRuntime ToolChain::getDefaultObjCRuntime(bool isNonFragile) const { return ObjCRuntime(isNonFragile ? ObjCRuntime::GNUstep : ObjCRuntime::GCC, VersionTuple()); } /// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting. // // FIXME: tblgen this. static const char *getARMTargetCPU(const ArgList &Args, const llvm::Triple &Triple) { // For Darwin targets, the -arch option (which is translated to a // corresponding -march option) should determine the architecture // (and the Mach-O slice) regardless of any -mcpu options. if (!Triple.isOSDarwin()) { // FIXME: Warn on inconsistent use of -mcpu and -march. // If we have -mcpu=, use that. if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) return A->getValue(); } StringRef MArch; if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) { // Otherwise, if we have -march= choose the base CPU for that arch. MArch = A->getValue(); } else { // Otherwise, use the Arch from the triple. MArch = Triple.getArchName(); } - if (Triple.getOS() == llvm::Triple::NetBSD) { + if (Triple.getOS() == llvm::Triple::NetBSD || + Triple.getOS() == llvm::Triple::FreeBSD) { if (MArch == "armv6") return "arm1176jzf-s"; } const char *result = llvm::StringSwitch(MArch) .Cases("armv2", "armv2a","arm2") .Case("armv3", "arm6") .Case("armv3m", "arm7m") .Case("armv4", "strongarm") .Case("armv4t", "arm7tdmi") .Cases("armv5", "armv5t", "arm10tdmi") .Cases("armv5e", "armv5te", "arm1026ejs") .Case("armv5tej", "arm926ej-s") .Cases("armv6", "armv6k", "arm1136jf-s") .Case("armv6j", "arm1136j-s") .Cases("armv6z", "armv6zk", "arm1176jzf-s") .Case("armv6t2", "arm1156t2-s") .Cases("armv6m", "armv6-m", "cortex-m0") .Cases("armv7", "armv7a", "armv7-a", "cortex-a8") .Cases("armv7l", "armv7-l", "cortex-a8") .Cases("armv7f", "armv7-f", "cortex-a9-mp") .Cases("armv7s", "armv7-s", "swift") .Cases("armv7r", "armv7-r", "cortex-r4") .Cases("armv7m", "armv7-m", "cortex-m3") .Cases("armv7em", "armv7e-m", "cortex-m4") .Cases("armv8", "armv8a", "armv8-a", "cortex-a53") .Case("ep9312", "ep9312") .Case("iwmmxt", "iwmmxt") .Case("xscale", "xscale") // If all else failed, return the most base CPU with thumb interworking // supported by LLVM. .Default(0); if (result) return result; return Triple.getEnvironment() == llvm::Triple::GNUEABIHF ? "arm1176jzf-s" : "arm7tdmi"; } /// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular /// CPU. // // FIXME: This is redundant with -mcpu, why does LLVM use this. // FIXME: tblgen this, or kill it! static const char *getLLVMArchSuffixForARM(StringRef CPU) { return llvm::StringSwitch(CPU) .Case("strongarm", "v4") .Cases("arm7tdmi", "arm7tdmi-s", "arm710t", "v4t") .Cases("arm720t", "arm9", "arm9tdmi", "v4t") .Cases("arm920", "arm920t", "arm922t", "v4t") .Cases("arm940t", "ep9312","v4t") .Cases("arm10tdmi", "arm1020t", "v5") .Cases("arm9e", "arm926ej-s", "arm946e-s", "v5e") .Cases("arm966e-s", "arm968e-s", "arm10e", "v5e") .Cases("arm1020e", "arm1022e", "xscale", "iwmmxt", "v5e") .Cases("arm1136j-s", "arm1136jf-s", "arm1176jz-s", "v6") .Cases("arm1176jzf-s", "mpcorenovfp", "mpcore", "v6") .Cases("arm1156t2-s", "arm1156t2f-s", "v6t2") .Cases("cortex-a5", "cortex-a7", "cortex-a8", "v7") .Cases("cortex-a9", "cortex-a12", "cortex-a15", "v7") .Cases("cortex-r4", "cortex-r5", "v7r") .Case("cortex-m0", "v6m") .Case("cortex-m3", "v7m") .Case("cortex-m4", "v7em") .Case("cortex-a9-mp", "v7f") .Case("swift", "v7s") .Cases("cortex-a53", "cortex-a57", "v8") .Default(""); } std::string ToolChain::ComputeLLVMTriple(const ArgList &Args, types::ID InputType) const { switch (getTriple().getArch()) { default: return getTripleString(); case llvm::Triple::x86_64: { llvm::Triple Triple = getTriple(); if (!Triple.isOSDarwin()) return getTripleString(); if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) { // x86_64h goes in the triple. Other -march options just use the // vanilla triple we already have. StringRef MArch = A->getValue(); if (MArch == "x86_64h") Triple.setArchName(MArch); } return Triple.getTriple(); } case llvm::Triple::arm: case llvm::Triple::thumb: { // FIXME: Factor into subclasses. llvm::Triple Triple = getTriple(); // Thumb2 is the default for V7 on Darwin. // // FIXME: Thumb should just be another -target-feaure, not in the triple. StringRef Suffix = getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple)); bool ThumbDefault = Suffix.startswith("v6m") || (Suffix.startswith("v7") && getTriple().isOSDarwin()); std::string ArchName = "arm"; // Assembly files should start in ARM mode. if (InputType != types::TY_PP_Asm && Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault)) ArchName = "thumb"; Triple.setArchName(ArchName + Suffix.str()); return Triple.getTriple(); } } } std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args, types::ID InputType) const { // Diagnose use of Darwin OS deployment target arguments on non-Darwin. if (Arg *A = Args.getLastArg(options::OPT_mmacosx_version_min_EQ, options::OPT_miphoneos_version_min_EQ, options::OPT_mios_simulator_version_min_EQ)) getDriver().Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); return ComputeLLVMTriple(Args, InputType); } void ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { // Each toolchain should provide the appropriate include flags. } void ToolChain::addClangTargetOptions(const ArgList &DriverArgs, ArgStringList &CC1Args) const { } ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType( const ArgList &Args) const { if (Arg *A = Args.getLastArg(options::OPT_rtlib_EQ)) { StringRef Value = A->getValue(); if (Value == "compiler-rt") return ToolChain::RLT_CompilerRT; if (Value == "libgcc") return ToolChain::RLT_Libgcc; getDriver().Diag(diag::err_drv_invalid_rtlib_name) << A->getAsString(Args); } return GetDefaultRuntimeLibType(); } ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{ if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) { StringRef Value = A->getValue(); if (Value == "libc++") return ToolChain::CST_Libcxx; if (Value == "libstdc++") return ToolChain::CST_Libstdcxx; getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args); } return ToolChain::CST_Libstdcxx; } /// \brief Utility function to add a system include directory to CC1 arguments. /*static*/ void ToolChain::addSystemInclude(const ArgList &DriverArgs, ArgStringList &CC1Args, const Twine &Path) { CC1Args.push_back("-internal-isystem"); CC1Args.push_back(DriverArgs.MakeArgString(Path)); } /// \brief Utility function to add a system include directory with extern "C" /// semantics to CC1 arguments. /// /// Note that this should be used rarely, and only for directories that /// historically and for legacy reasons are treated as having implicit extern /// "C" semantics. These semantics are *ignored* by and large today, but its /// important to preserve the preprocessor changes resulting from the /// classification. /*static*/ void ToolChain::addExternCSystemInclude(const ArgList &DriverArgs, ArgStringList &CC1Args, const Twine &Path) { CC1Args.push_back("-internal-externc-isystem"); CC1Args.push_back(DriverArgs.MakeArgString(Path)); } void ToolChain::addExternCSystemIncludeIfExists(const ArgList &DriverArgs, ArgStringList &CC1Args, const Twine &Path) { if (llvm::sys::fs::exists(Path)) addExternCSystemInclude(DriverArgs, CC1Args, Path); } /// \brief Utility function to add a list of system include directories to CC1. /*static*/ void ToolChain::addSystemIncludes(const ArgList &DriverArgs, ArgStringList &CC1Args, ArrayRef Paths) { for (ArrayRef::iterator I = Paths.begin(), E = Paths.end(); I != E; ++I) { CC1Args.push_back("-internal-isystem"); CC1Args.push_back(DriverArgs.MakeArgString(*I)); } } void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { // Header search paths should be handled by each of the subclasses. // Historically, they have not been, and instead have been handled inside of // the CC1-layer frontend. As the logic is hoisted out, this generic function // will slowly stop being called. // // While it is being called, replicate a bit of a hack to propagate the // '-stdlib=' flag down to CC1 so that it can in turn customize the C++ // header search paths with it. Once all systems are overriding this // function, the CC1 flag and this line can be removed. DriverArgs.AddAllArgs(CC1Args, options::OPT_stdlib_EQ); } void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args, ArgStringList &CmdArgs) const { CXXStdlibType Type = GetCXXStdlibType(Args); switch (Type) { case ToolChain::CST_Libcxx: CmdArgs.push_back("-lc++"); break; case ToolChain::CST_Libstdcxx: CmdArgs.push_back("-lstdc++"); break; } } void ToolChain::AddCCKextLibArgs(const ArgList &Args, ArgStringList &CmdArgs) const { CmdArgs.push_back("-lcc_kext"); } bool ToolChain::AddFastMathRuntimeIfAvailable(const ArgList &Args, ArgStringList &CmdArgs) const { // Do not check for -fno-fast-math or -fno-unsafe-math when -Ofast passed // (to keep the linker options consistent with gcc and clang itself). if (!isOptimizationLevelFast(Args)) { // Check if -ffast-math or -funsafe-math. Arg *A = Args.getLastArg(options::OPT_ffast_math, options::OPT_fno_fast_math, options::OPT_funsafe_math_optimizations, options::OPT_fno_unsafe_math_optimizations); if (!A || A->getOption().getID() == options::OPT_fno_fast_math || A->getOption().getID() == options::OPT_fno_unsafe_math_optimizations) return false; } // If crtfastmath.o exists add it to the arguments. std::string Path = GetFilePath("crtfastmath.o"); if (Path == "crtfastmath.o") // Not found. return false; CmdArgs.push_back(Args.MakeArgString(Path)); return true; } Index: stable/9/contrib/llvm/tools/clang/lib/Driver/Tools.cpp =================================================================== --- stable/9/contrib/llvm/tools/clang/lib/Driver/Tools.cpp (revision 283018) +++ stable/9/contrib/llvm/tools/clang/lib/Driver/Tools.cpp (revision 283019) @@ -1,7173 +1,7174 @@ //===--- Tools.cpp - Tools Implementations --------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "Tools.h" #include "InputInfo.h" #include "ToolChains.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/Version.h" #include "clang/Driver/Action.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Job.h" #include "clang/Driver/Options.h" #include "clang/Driver/SanitizerArgs.h" #include "clang/Driver/ToolChain.h" #include "clang/Driver/Util.h" #include "clang/Sema/SemaDiagnostic.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Format.h" #include "llvm/Support/Host.h" #include "llvm/Support/Path.h" #include "llvm/Support/Program.h" #include "llvm/Support/Process.h" #include "llvm/Support/raw_ostream.h" #include using namespace clang::driver; using namespace clang::driver::tools; using namespace clang; using namespace llvm::opt; /// CheckPreprocessingOptions - Perform some validation of preprocessing /// arguments that is shared with gcc. static void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) { if (Arg *A = Args.getLastArg(options::OPT_C, options::OPT_CC)) if (!Args.hasArg(options::OPT_E) && !D.CCCIsCPP()) D.Diag(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args) << "-E"; } /// CheckCodeGenerationOptions - Perform some validation of code generation /// arguments that is shared with gcc. static void CheckCodeGenerationOptions(const Driver &D, const ArgList &Args) { // In gcc, only ARM checks this, but it seems reasonable to check universally. if (Args.hasArg(options::OPT_static)) if (const Arg *A = Args.getLastArg(options::OPT_dynamic, options::OPT_mdynamic_no_pic)) D.Diag(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args) << "-static"; } // Quote target names for inclusion in GNU Make dependency files. // Only the characters '$', '#', ' ', '\t' are quoted. static void QuoteTarget(StringRef Target, SmallVectorImpl &Res) { for (unsigned i = 0, e = Target.size(); i != e; ++i) { switch (Target[i]) { case ' ': case '\t': // Escape the preceding backslashes for (int j = i - 1; j >= 0 && Target[j] == '\\'; --j) Res.push_back('\\'); // Escape the space/tab Res.push_back('\\'); break; case '$': Res.push_back('$'); break; case '#': Res.push_back('\\'); break; default: break; } Res.push_back(Target[i]); } } static void addDirectoryList(const ArgList &Args, ArgStringList &CmdArgs, const char *ArgName, const char *EnvVar) { const char *DirList = ::getenv(EnvVar); bool CombinedArg = false; if (!DirList) return; // Nothing to do. StringRef Name(ArgName); if (Name.equals("-I") || Name.equals("-L")) CombinedArg = true; StringRef Dirs(DirList); if (Dirs.empty()) // Empty string should not add '.'. return; StringRef::size_type Delim; while ((Delim = Dirs.find(llvm::sys::EnvPathSeparator)) != StringRef::npos) { if (Delim == 0) { // Leading colon. if (CombinedArg) { CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + ".")); } else { CmdArgs.push_back(ArgName); CmdArgs.push_back("."); } } else { if (CombinedArg) { CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + Dirs.substr(0, Delim))); } else { CmdArgs.push_back(ArgName); CmdArgs.push_back(Args.MakeArgString(Dirs.substr(0, Delim))); } } Dirs = Dirs.substr(Delim + 1); } if (Dirs.empty()) { // Trailing colon. if (CombinedArg) { CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + ".")); } else { CmdArgs.push_back(ArgName); CmdArgs.push_back("."); } } else { // Add the last path. if (CombinedArg) { CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + Dirs)); } else { CmdArgs.push_back(ArgName); CmdArgs.push_back(Args.MakeArgString(Dirs)); } } } static void AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, const ArgList &Args, ArgStringList &CmdArgs) { const Driver &D = TC.getDriver(); // Add extra linker input arguments which are not treated as inputs // (constructed via -Xarch_). Args.AddAllArgValues(CmdArgs, options::OPT_Zlinker_input); for (InputInfoList::const_iterator it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { const InputInfo &II = *it; if (!TC.HasNativeLLVMSupport()) { // Don't try to pass LLVM inputs unless we have native support. if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR || II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC) D.Diag(diag::err_drv_no_linker_llvm_support) << TC.getTripleString(); } // Add filenames immediately. if (II.isFilename()) { CmdArgs.push_back(II.getFilename()); continue; } // Otherwise, this is a linker input argument. const Arg &A = II.getInputArg(); // Handle reserved library options. if (A.getOption().matches(options::OPT_Z_reserved_lib_stdcxx)) { TC.AddCXXStdlibLibArgs(Args, CmdArgs); } else if (A.getOption().matches(options::OPT_Z_reserved_lib_cckext)) { TC.AddCCKextLibArgs(Args, CmdArgs); } else A.renderAsInput(Args, CmdArgs); } // LIBRARY_PATH - included following the user specified library paths. addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH"); } /// \brief Determine whether Objective-C automated reference counting is /// enabled. static bool isObjCAutoRefCount(const ArgList &Args) { return Args.hasFlag(options::OPT_fobjc_arc, options::OPT_fno_objc_arc, false); } /// \brief Determine whether we are linking the ObjC runtime. static bool isObjCRuntimeLinked(const ArgList &Args) { if (isObjCAutoRefCount(Args)) { Args.ClaimAllArgs(options::OPT_fobjc_link_runtime); return true; } return Args.hasArg(options::OPT_fobjc_link_runtime); } static void addProfileRT(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs, llvm::Triple Triple) { if (!(Args.hasArg(options::OPT_fprofile_arcs) || Args.hasArg(options::OPT_fprofile_generate) || Args.hasArg(options::OPT_fcreate_profile) || Args.hasArg(options::OPT_coverage))) return; // GCC links libgcov.a by adding -L/gcc/lib/gcc// -lgcov to // the link line. We cannot do the same thing because unlike gcov there is a // libprofile_rt.so. We used to use the -l:libprofile_rt.a syntax, but that is // not supported by old linkers. std::string ProfileRT = std::string(TC.getDriver().Dir) + "/../lib/libprofile_rt.a"; CmdArgs.push_back(Args.MakeArgString(ProfileRT)); } static bool forwardToGCC(const Option &O) { // Don't forward inputs from the original command line. They are added from // InputInfoList. return O.getKind() != Option::InputClass && !O.hasFlag(options::DriverOption) && !O.hasFlag(options::LinkerInput); } void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, const Driver &D, const ArgList &Args, ArgStringList &CmdArgs, const InputInfo &Output, const InputInfoList &Inputs) const { Arg *A; CheckPreprocessingOptions(D, Args); Args.AddLastArg(CmdArgs, options::OPT_C); Args.AddLastArg(CmdArgs, options::OPT_CC); // Handle dependency file generation. if ((A = Args.getLastArg(options::OPT_M, options::OPT_MM)) || (A = Args.getLastArg(options::OPT_MD)) || (A = Args.getLastArg(options::OPT_MMD))) { // Determine the output location. const char *DepFile; if (Arg *MF = Args.getLastArg(options::OPT_MF)) { DepFile = MF->getValue(); C.addFailureResultFile(DepFile, &JA); } else if (Output.getType() == types::TY_Dependencies) { DepFile = Output.getFilename(); } else if (A->getOption().matches(options::OPT_M) || A->getOption().matches(options::OPT_MM)) { DepFile = "-"; } else { DepFile = getDependencyFileName(Args, Inputs); C.addFailureResultFile(DepFile, &JA); } CmdArgs.push_back("-dependency-file"); CmdArgs.push_back(DepFile); // Add a default target if one wasn't specified. if (!Args.hasArg(options::OPT_MT) && !Args.hasArg(options::OPT_MQ)) { const char *DepTarget; // If user provided -o, that is the dependency target, except // when we are only generating a dependency file. Arg *OutputOpt = Args.getLastArg(options::OPT_o); if (OutputOpt && Output.getType() != types::TY_Dependencies) { DepTarget = OutputOpt->getValue(); } else { // Otherwise derive from the base input. // // FIXME: This should use the computed output file location. SmallString<128> P(Inputs[0].getBaseInput()); llvm::sys::path::replace_extension(P, "o"); DepTarget = Args.MakeArgString(llvm::sys::path::filename(P)); } CmdArgs.push_back("-MT"); SmallString<128> Quoted; QuoteTarget(DepTarget, Quoted); CmdArgs.push_back(Args.MakeArgString(Quoted)); } if (A->getOption().matches(options::OPT_M) || A->getOption().matches(options::OPT_MD)) CmdArgs.push_back("-sys-header-deps"); } if (Args.hasArg(options::OPT_MG)) { if (!A || A->getOption().matches(options::OPT_MD) || A->getOption().matches(options::OPT_MMD)) D.Diag(diag::err_drv_mg_requires_m_or_mm); CmdArgs.push_back("-MG"); } Args.AddLastArg(CmdArgs, options::OPT_MP); // Convert all -MQ args to -MT for (arg_iterator it = Args.filtered_begin(options::OPT_MT, options::OPT_MQ), ie = Args.filtered_end(); it != ie; ++it) { const Arg *A = *it; A->claim(); if (A->getOption().matches(options::OPT_MQ)) { CmdArgs.push_back("-MT"); SmallString<128> Quoted; QuoteTarget(A->getValue(), Quoted); CmdArgs.push_back(Args.MakeArgString(Quoted)); // -MT flag - no change } else { A->render(Args, CmdArgs); } } // Add -i* options, and automatically translate to // -include-pch/-include-pth for transparent PCH support. It's // wonky, but we include looking for .gch so we can support seamless // replacement into a build system already set up to be generating // .gch files. bool RenderedImplicitInclude = false; for (arg_iterator it = Args.filtered_begin(options::OPT_clang_i_Group), ie = Args.filtered_end(); it != ie; ++it) { const Arg *A = it; if (A->getOption().matches(options::OPT_include)) { bool IsFirstImplicitInclude = !RenderedImplicitInclude; RenderedImplicitInclude = true; // Use PCH if the user requested it. bool UsePCH = D.CCCUsePCH; bool FoundPTH = false; bool FoundPCH = false; SmallString<128> P(A->getValue()); // We want the files to have a name like foo.h.pch. Add a dummy extension // so that replace_extension does the right thing. P += ".dummy"; if (UsePCH) { llvm::sys::path::replace_extension(P, "pch"); if (llvm::sys::fs::exists(P.str())) FoundPCH = true; } if (!FoundPCH) { llvm::sys::path::replace_extension(P, "pth"); if (llvm::sys::fs::exists(P.str())) FoundPTH = true; } if (!FoundPCH && !FoundPTH) { llvm::sys::path::replace_extension(P, "gch"); if (llvm::sys::fs::exists(P.str())) { FoundPCH = UsePCH; FoundPTH = !UsePCH; } } if (FoundPCH || FoundPTH) { if (IsFirstImplicitInclude) { A->claim(); if (UsePCH) CmdArgs.push_back("-include-pch"); else CmdArgs.push_back("-include-pth"); CmdArgs.push_back(Args.MakeArgString(P.str())); continue; } else { // Ignore the PCH if not first on command line and emit warning. D.Diag(diag::warn_drv_pch_not_first_include) << P.str() << A->getAsString(Args); } } } // Not translated, render as usual. A->claim(); A->render(Args, CmdArgs); } Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U); Args.AddAllArgs(CmdArgs, options::OPT_I_Group, options::OPT_F, options::OPT_index_header_map); // Add -Wp, and -Xassembler if using the preprocessor. // FIXME: There is a very unfortunate problem here, some troubled // souls abuse -Wp, to pass preprocessor options in gcc syntax. To // really support that we would have to parse and then translate // those options. :( Args.AddAllArgValues(CmdArgs, options::OPT_Wp_COMMA, options::OPT_Xpreprocessor); // -I- is a deprecated GCC feature, reject it. if (Arg *A = Args.getLastArg(options::OPT_I_)) D.Diag(diag::err_drv_I_dash_not_supported) << A->getAsString(Args); // If we have a --sysroot, and don't have an explicit -isysroot flag, add an // -isysroot to the CC1 invocation. StringRef sysroot = C.getSysRoot(); if (sysroot != "") { if (!Args.hasArg(options::OPT_isysroot)) { CmdArgs.push_back("-isysroot"); CmdArgs.push_back(C.getArgs().MakeArgString(sysroot)); } } // Parse additional include paths from environment variables. // FIXME: We should probably sink the logic for handling these from the // frontend into the driver. It will allow deleting 4 otherwise unused flags. // CPATH - included following the user specified includes (but prior to // builtin and standard includes). addDirectoryList(Args, CmdArgs, "-I", "CPATH"); // C_INCLUDE_PATH - system includes enabled when compiling C. addDirectoryList(Args, CmdArgs, "-c-isystem", "C_INCLUDE_PATH"); // CPLUS_INCLUDE_PATH - system includes enabled when compiling C++. addDirectoryList(Args, CmdArgs, "-cxx-isystem", "CPLUS_INCLUDE_PATH"); // OBJC_INCLUDE_PATH - system includes enabled when compiling ObjC. addDirectoryList(Args, CmdArgs, "-objc-isystem", "OBJC_INCLUDE_PATH"); // OBJCPLUS_INCLUDE_PATH - system includes enabled when compiling ObjC++. addDirectoryList(Args, CmdArgs, "-objcxx-isystem", "OBJCPLUS_INCLUDE_PATH"); // Add C++ include arguments, if needed. if (types::isCXX(Inputs[0].getType())) getToolChain().AddClangCXXStdlibIncludeArgs(Args, CmdArgs); // Add system include arguments. getToolChain().AddClangSystemIncludeArgs(Args, CmdArgs); } /// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular /// CPU. // // FIXME: This is redundant with -mcpu, why does LLVM use this. // FIXME: tblgen this, or kill it! static const char *getLLVMArchSuffixForARM(StringRef CPU) { return llvm::StringSwitch(CPU) .Case("strongarm", "v4") .Cases("arm7tdmi", "arm7tdmi-s", "arm710t", "v4t") .Cases("arm720t", "arm9", "arm9tdmi", "v4t") .Cases("arm920", "arm920t", "arm922t", "v4t") .Cases("arm940t", "ep9312","v4t") .Cases("arm10tdmi", "arm1020t", "v5") .Cases("arm9e", "arm926ej-s", "arm946e-s", "v5e") .Cases("arm966e-s", "arm968e-s", "arm10e", "v5e") .Cases("arm1020e", "arm1022e", "xscale", "iwmmxt", "v5e") .Cases("arm1136j-s", "arm1136jf-s", "arm1176jz-s", "v6") .Cases("arm1176jzf-s", "mpcorenovfp", "mpcore", "v6") .Cases("arm1156t2-s", "arm1156t2f-s", "v6t2") .Cases("cortex-a5", "cortex-a7", "cortex-a8", "v7") .Cases("cortex-a9", "cortex-a12", "cortex-a15", "v7") .Cases("cortex-r4", "cortex-r5", "v7r") .Case("cortex-m0", "v6m") .Case("cortex-m3", "v7m") .Case("cortex-m4", "v7em") .Case("cortex-a9-mp", "v7f") .Case("swift", "v7s") .Cases("cortex-a53", "cortex-a57", "v8") .Default(""); } /// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting. // // FIXME: tblgen this. static std::string getARMTargetCPU(const ArgList &Args, const llvm::Triple &Triple) { // FIXME: Warn on inconsistent use of -mcpu and -march. // If we have -mcpu=, use that. if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { StringRef MCPU = A->getValue(); // Handle -mcpu=native. if (MCPU == "native") return llvm::sys::getHostCPUName(); else return MCPU; } StringRef MArch; if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) { // Otherwise, if we have -march= choose the base CPU for that arch. MArch = A->getValue(); } else { // Otherwise, use the Arch from the triple. MArch = Triple.getArchName(); } - if (Triple.getOS() == llvm::Triple::NetBSD) { + if (Triple.getOS() == llvm::Triple::NetBSD || + Triple.getOS() == llvm::Triple::FreeBSD) { if (MArch == "armv6") return "arm1176jzf-s"; } // Handle -march=native. std::string NativeMArch; if (MArch == "native") { std::string CPU = llvm::sys::getHostCPUName(); if (CPU != "generic") { // Translate the native cpu into the architecture. The switch below will // then chose the minimum cpu for that arch. NativeMArch = std::string("arm") + getLLVMArchSuffixForARM(CPU); MArch = NativeMArch; } } return llvm::StringSwitch(MArch) .Cases("armv2", "armv2a","arm2") .Case("armv3", "arm6") .Case("armv3m", "arm7m") .Case("armv4", "strongarm") .Case("armv4t", "arm7tdmi") .Cases("armv5", "armv5t", "arm10tdmi") .Cases("armv5e", "armv5te", "arm1022e") .Case("armv5tej", "arm926ej-s") .Cases("armv6", "armv6k", "arm1136jf-s") .Case("armv6j", "arm1136j-s") .Cases("armv6z", "armv6zk", "arm1176jzf-s") .Case("armv6t2", "arm1156t2-s") .Cases("armv6m", "armv6-m", "cortex-m0") .Cases("armv7", "armv7a", "armv7-a", "cortex-a8") .Cases("armv7em", "armv7e-m", "cortex-m4") .Cases("armv7f", "armv7-f", "cortex-a9-mp") .Cases("armv7s", "armv7-s", "swift") .Cases("armv7r", "armv7-r", "cortex-r4") .Cases("armv7m", "armv7-m", "cortex-m3") .Cases("armv8", "armv8a", "armv8-a", "cortex-a53") .Case("ep9312", "ep9312") .Case("iwmmxt", "iwmmxt") .Case("xscale", "xscale") // If all else failed, return the most base CPU with thumb interworking // supported by LLVM. .Default("arm7tdmi"); } /// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are targeting. // // FIXME: tblgen this. static std::string getAArch64TargetCPU(const ArgList &Args, const llvm::Triple &Triple) { // FIXME: Warn on inconsistent use of -mcpu and -march. // If we have -mcpu=, use that. if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { StringRef MCPU = A->getValue(); // Handle -mcpu=native. if (MCPU == "native") return llvm::sys::getHostCPUName(); else return MCPU; } return "generic"; } // FIXME: Move to target hook. static bool isSignedCharDefault(const llvm::Triple &Triple) { switch (Triple.getArch()) { default: return true; case llvm::Triple::aarch64: case llvm::Triple::arm: case llvm::Triple::ppc: case llvm::Triple::ppc64: if (Triple.isOSDarwin()) return true; return false; case llvm::Triple::ppc64le: case llvm::Triple::systemz: case llvm::Triple::xcore: return false; } } static bool isNoCommonDefault(const llvm::Triple &Triple) { switch (Triple.getArch()) { default: return false; case llvm::Triple::xcore: return true; } } // Handle -mfpu=. // // FIXME: Centralize feature selection, defaulting shouldn't be also in the // frontend target. static void getAArch64FPUFeatures(const Driver &D, const Arg *A, const ArgList &Args, std::vector &Features) { StringRef FPU = A->getValue(); if (FPU == "fp-armv8") { Features.push_back("+fp-armv8"); } else if (FPU == "neon-fp-armv8") { Features.push_back("+fp-armv8"); Features.push_back("+neon"); } else if (FPU == "crypto-neon-fp-armv8") { Features.push_back("+fp-armv8"); Features.push_back("+neon"); Features.push_back("+crypto"); } else if (FPU == "neon") { Features.push_back("+neon"); } else if (FPU == "none") { Features.push_back("-fp-armv8"); Features.push_back("-crypto"); Features.push_back("-neon"); } else D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); } // Handle -mhwdiv=. static void getARMHWDivFeatures(const Driver &D, const Arg *A, const ArgList &Args, std::vector &Features) { StringRef HWDiv = A->getValue(); if (HWDiv == "arm") { Features.push_back("+hwdiv-arm"); Features.push_back("-hwdiv"); } else if (HWDiv == "thumb") { Features.push_back("-hwdiv-arm"); Features.push_back("+hwdiv"); } else if (HWDiv == "arm,thumb" || HWDiv == "thumb,arm") { Features.push_back("+hwdiv-arm"); Features.push_back("+hwdiv"); } else if (HWDiv == "none") { Features.push_back("-hwdiv-arm"); Features.push_back("-hwdiv"); } else D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); } // Handle -mfpu=. // // FIXME: Centralize feature selection, defaulting shouldn't be also in the // frontend target. static void getARMFPUFeatures(const Driver &D, const Arg *A, const ArgList &Args, std::vector &Features) { StringRef FPU = A->getValue(); // Set the target features based on the FPU. if (FPU == "fpa" || FPU == "fpe2" || FPU == "fpe3" || FPU == "maverick") { // Disable any default FPU support. Features.push_back("-vfp2"); Features.push_back("-vfp3"); Features.push_back("-neon"); } else if (FPU == "vfp3-d16" || FPU == "vfpv3-d16") { Features.push_back("+vfp3"); Features.push_back("+d16"); Features.push_back("-neon"); } else if (FPU == "vfp") { Features.push_back("+vfp2"); Features.push_back("-neon"); } else if (FPU == "vfp3" || FPU == "vfpv3") { Features.push_back("+vfp3"); Features.push_back("-neon"); } else if (FPU == "fp-armv8") { Features.push_back("+fp-armv8"); Features.push_back("-neon"); Features.push_back("-crypto"); } else if (FPU == "neon-fp-armv8") { Features.push_back("+fp-armv8"); Features.push_back("+neon"); Features.push_back("-crypto"); } else if (FPU == "crypto-neon-fp-armv8") { Features.push_back("+fp-armv8"); Features.push_back("+neon"); Features.push_back("+crypto"); } else if (FPU == "neon") { Features.push_back("+neon"); } else if (FPU == "none") { Features.push_back("-vfp2"); Features.push_back("-vfp3"); Features.push_back("-vfp4"); Features.push_back("-fp-armv8"); Features.push_back("-crypto"); Features.push_back("-neon"); } else D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); } // Select the float ABI as determined by -msoft-float, -mhard-float, and // -mfloat-abi=. static StringRef getARMFloatABI(const Driver &D, const ArgList &Args, const llvm::Triple &Triple) { StringRef FloatABI; if (Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, options::OPT_mfloat_abi_EQ)) { if (A->getOption().matches(options::OPT_msoft_float)) FloatABI = "soft"; else if (A->getOption().matches(options::OPT_mhard_float)) FloatABI = "hard"; else { FloatABI = A->getValue(); if (FloatABI != "soft" && FloatABI != "softfp" && FloatABI != "hard") { D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args); FloatABI = "soft"; } } } // If unspecified, choose the default based on the platform. if (FloatABI.empty()) { switch (Triple.getOS()) { case llvm::Triple::Darwin: case llvm::Triple::MacOSX: case llvm::Triple::IOS: { // Darwin defaults to "softfp" for v6 and v7. // // FIXME: Factor out an ARM class so we can cache the arch somewhere. std::string ArchName = getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple)); if (StringRef(ArchName).startswith("v6") || StringRef(ArchName).startswith("v7")) FloatABI = "softfp"; else FloatABI = "soft"; break; } case llvm::Triple::FreeBSD: // FreeBSD defaults to soft float FloatABI = "soft"; break; default: switch(Triple.getEnvironment()) { case llvm::Triple::GNUEABIHF: FloatABI = "hard"; break; case llvm::Triple::GNUEABI: FloatABI = "softfp"; break; case llvm::Triple::EABI: // EABI is always AAPCS, and if it was not marked 'hard', it's softfp FloatABI = "softfp"; break; case llvm::Triple::Android: { std::string ArchName = getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple)); if (StringRef(ArchName).startswith("v7")) FloatABI = "softfp"; else FloatABI = "soft"; break; } default: // Assume "soft", but warn the user we are guessing. FloatABI = "soft"; D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft"; break; } } } return FloatABI; } static void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple, const ArgList &Args, std::vector &Features) { StringRef FloatABI = getARMFloatABI(D, Args, Triple); // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these // yet (it uses the -mfloat-abi and -msoft-float options), and it is // stripped out by the ARM target. // Use software floating point operations? if (FloatABI == "soft") Features.push_back("+soft-float"); // Use software floating point argument passing? if (FloatABI != "hard") Features.push_back("+soft-float-abi"); // Honor -mfpu=. if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) getARMFPUFeatures(D, A, Args, Features); if (const Arg *A = Args.getLastArg(options::OPT_mhwdiv_EQ)) getARMHWDivFeatures(D, A, Args, Features); // Setting -msoft-float effectively disables NEON because of the GCC // implementation, although the same isn't true of VFP or VFP3. if (FloatABI == "soft") Features.push_back("-neon"); // En/disable crc if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) { if (A->getOption().matches(options::OPT_mcrc)) Features.push_back("+crc"); else Features.push_back("-crc"); } } void Clang::AddARMTargetArgs(const ArgList &Args, ArgStringList &CmdArgs, bool KernelOrKext) const { const Driver &D = getToolChain().getDriver(); // Get the effective triple, which takes into account the deployment target. std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args); llvm::Triple Triple(TripleStr); std::string CPUName = getARMTargetCPU(Args, Triple); // Select the ABI to use. // // FIXME: Support -meabi. const char *ABIName = 0; if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { ABIName = A->getValue(); } else if (Triple.isOSDarwin()) { // The backend is hardwired to assume AAPCS for M-class processors, ensure // the frontend matches that. if (Triple.getEnvironment() == llvm::Triple::EABI || StringRef(CPUName).startswith("cortex-m")) { ABIName = "aapcs"; } else { ABIName = "apcs-gnu"; } } else { // Select the default based on the platform. switch(Triple.getEnvironment()) { case llvm::Triple::Android: case llvm::Triple::GNUEABI: case llvm::Triple::GNUEABIHF: ABIName = "aapcs-linux"; break; case llvm::Triple::EABI: ABIName = "aapcs"; break; default: ABIName = "apcs-gnu"; } } CmdArgs.push_back("-target-abi"); CmdArgs.push_back(ABIName); // Determine floating point ABI from the options & target defaults. StringRef FloatABI = getARMFloatABI(D, Args, Triple); if (FloatABI == "soft") { // Floating point operations and argument passing are soft. // // FIXME: This changes CPP defines, we need -target-soft-float. CmdArgs.push_back("-msoft-float"); CmdArgs.push_back("-mfloat-abi"); CmdArgs.push_back("soft"); } else if (FloatABI == "softfp") { // Floating point operations are hard, but argument passing is soft. CmdArgs.push_back("-mfloat-abi"); CmdArgs.push_back("soft"); } else { // Floating point operations and argument passing are hard. assert(FloatABI == "hard" && "Invalid float abi!"); CmdArgs.push_back("-mfloat-abi"); CmdArgs.push_back("hard"); } // Kernel code has more strict alignment requirements. if (KernelOrKext) { if (!Triple.isiOS() || Triple.isOSVersionLT(6)) { CmdArgs.push_back("-backend-option"); CmdArgs.push_back("-arm-long-calls"); } CmdArgs.push_back("-backend-option"); CmdArgs.push_back("-arm-strict-align"); // The kext linker doesn't know how to deal with movw/movt. CmdArgs.push_back("-backend-option"); CmdArgs.push_back("-arm-use-movt=0"); } // Setting -mno-global-merge disables the codegen global merge pass. Setting // -mglobal-merge has no effect as the pass is enabled by default. if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge, options::OPT_mno_global_merge)) { if (A->getOption().matches(options::OPT_mno_global_merge)) CmdArgs.push_back("-mno-global-merge"); } if (!Args.hasFlag(options::OPT_mimplicit_float, options::OPT_mno_implicit_float, true)) CmdArgs.push_back("-no-implicit-float"); // llvm does not support reserving registers in general. There is support // for reserving r9 on ARM though (defined as a platform-specific register // in ARM EABI). if (Args.hasArg(options::OPT_ffixed_r9)) { CmdArgs.push_back("-backend-option"); CmdArgs.push_back("-arm-reserve-r9"); } } // Get CPU and ABI names. They are not independent // so we have to calculate them together. static void getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple, StringRef &CPUName, StringRef &ABIName) { const char *DefMips32CPU = "mips32"; const char *DefMips64CPU = "mips64"; if (Arg *A = Args.getLastArg(options::OPT_march_EQ, options::OPT_mcpu_EQ)) CPUName = A->getValue(); if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { ABIName = A->getValue(); // Convert a GNU style Mips ABI name to the name // accepted by LLVM Mips backend. ABIName = llvm::StringSwitch(ABIName) .Case("32", "o32") .Case("64", "n64") .Default(ABIName); } // Setup default CPU and ABI names. if (CPUName.empty() && ABIName.empty()) { switch (Triple.getArch()) { default: llvm_unreachable("Unexpected triple arch name"); case llvm::Triple::mips: case llvm::Triple::mipsel: CPUName = DefMips32CPU; break; case llvm::Triple::mips64: case llvm::Triple::mips64el: CPUName = DefMips64CPU; break; } } if (!ABIName.empty()) { // Deduce CPU name from ABI name. CPUName = llvm::StringSwitch(ABIName) .Cases("32", "o32", "eabi", DefMips32CPU) .Cases("n32", "n64", "64", DefMips64CPU) .Default(""); } else if (!CPUName.empty()) { // Deduce ABI name from CPU name. ABIName = llvm::StringSwitch(CPUName) .Cases("mips32", "mips32r2", "o32") .Cases("mips64", "mips64r2", "n64") .Default(""); } // FIXME: Warn on inconsistent cpu and abi usage. } // Convert ABI name to the GNU tools acceptable variant. static StringRef getGnuCompatibleMipsABIName(StringRef ABI) { return llvm::StringSwitch(ABI) .Case("o32", "32") .Case("n64", "64") .Default(ABI); } // Select the MIPS float ABI as determined by -msoft-float, -mhard-float, // and -mfloat-abi=. static StringRef getMipsFloatABI(const Driver &D, const ArgList &Args) { StringRef FloatABI; if (Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, options::OPT_mfloat_abi_EQ)) { if (A->getOption().matches(options::OPT_msoft_float)) FloatABI = "soft"; else if (A->getOption().matches(options::OPT_mhard_float)) FloatABI = "hard"; else { FloatABI = A->getValue(); if (FloatABI != "soft" && FloatABI != "hard") { D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args); FloatABI = "hard"; } } } // If unspecified, choose the default based on the platform. if (FloatABI.empty()) { // Assume "hard", because it's a default value used by gcc. // When we start to recognize specific target MIPS processors, // we will be able to select the default more correctly. FloatABI = "hard"; } return FloatABI; } static void AddTargetFeature(const ArgList &Args, std::vector &Features, OptSpecifier OnOpt, OptSpecifier OffOpt, StringRef FeatureName) { if (Arg *A = Args.getLastArg(OnOpt, OffOpt)) { if (A->getOption().matches(OnOpt)) Features.push_back(Args.MakeArgString("+" + FeatureName)); else Features.push_back(Args.MakeArgString("-" + FeatureName)); } } static void getMIPSTargetFeatures(const Driver &D, const ArgList &Args, std::vector &Features) { StringRef FloatABI = getMipsFloatABI(D, Args); bool IsMips16 = Args.getLastArg(options::OPT_mips16) != NULL; if (FloatABI == "soft" || (FloatABI == "hard" && IsMips16)) { // FIXME: Note, this is a hack. We need to pass the selected float // mode to the MipsTargetInfoBase to define appropriate macros there. // Now it is the only method. Features.push_back("+soft-float"); } if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) { if (StringRef(A->getValue()) == "2008") Features.push_back("+nan2008"); } AddTargetFeature(Args, Features, options::OPT_msingle_float, options::OPT_mdouble_float, "single-float"); AddTargetFeature(Args, Features, options::OPT_mips16, options::OPT_mno_mips16, "mips16"); AddTargetFeature(Args, Features, options::OPT_mmicromips, options::OPT_mno_micromips, "micromips"); AddTargetFeature(Args, Features, options::OPT_mdsp, options::OPT_mno_dsp, "dsp"); AddTargetFeature(Args, Features, options::OPT_mdspr2, options::OPT_mno_dspr2, "dspr2"); AddTargetFeature(Args, Features, options::OPT_mmsa, options::OPT_mno_msa, "msa"); AddTargetFeature(Args, Features, options::OPT_mfp64, options::OPT_mfp32, "fp64"); } void Clang::AddMIPSTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { const Driver &D = getToolChain().getDriver(); StringRef CPUName; StringRef ABIName; const llvm::Triple &Triple = getToolChain().getTriple(); getMipsCPUAndABI(Args, Triple, CPUName, ABIName); CmdArgs.push_back("-target-abi"); CmdArgs.push_back(ABIName.data()); StringRef FloatABI = getMipsFloatABI(D, Args); bool IsMips16 = Args.getLastArg(options::OPT_mips16) != NULL; if (FloatABI == "soft" || (FloatABI == "hard" && IsMips16)) { // Floating point operations and argument passing are soft. CmdArgs.push_back("-msoft-float"); CmdArgs.push_back("-mfloat-abi"); CmdArgs.push_back("soft"); if (FloatABI == "hard" && IsMips16) { CmdArgs.push_back("-mllvm"); CmdArgs.push_back("-mips16-hard-float"); } } else { // Floating point operations and argument passing are hard. assert(FloatABI == "hard" && "Invalid float abi!"); CmdArgs.push_back("-mfloat-abi"); CmdArgs.push_back("hard"); } if (Arg *A = Args.getLastArg(options::OPT_mxgot, options::OPT_mno_xgot)) { if (A->getOption().matches(options::OPT_mxgot)) { CmdArgs.push_back("-mllvm"); CmdArgs.push_back("-mxgot"); } } if (Arg *A = Args.getLastArg(options::OPT_mldc1_sdc1, options::OPT_mno_ldc1_sdc1)) { if (A->getOption().matches(options::OPT_mno_ldc1_sdc1)) { CmdArgs.push_back("-mllvm"); CmdArgs.push_back("-mno-ldc1-sdc1"); } } if (Arg *A = Args.getLastArg(options::OPT_mcheck_zero_division, options::OPT_mno_check_zero_division)) { if (A->getOption().matches(options::OPT_mno_check_zero_division)) { CmdArgs.push_back("-mllvm"); CmdArgs.push_back("-mno-check-zero-division"); } } if (Arg *A = Args.getLastArg(options::OPT_G)) { StringRef v = A->getValue(); CmdArgs.push_back("-mllvm"); CmdArgs.push_back(Args.MakeArgString("-mips-ssection-threshold=" + v)); A->claim(); } } /// getPPCTargetCPU - Get the (LLVM) name of the PowerPC cpu we are targeting. static std::string getPPCTargetCPU(const ArgList &Args) { if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { StringRef CPUName = A->getValue(); if (CPUName == "native") { std::string CPU = llvm::sys::getHostCPUName(); if (!CPU.empty() && CPU != "generic") return CPU; else return ""; } return llvm::StringSwitch(CPUName) .Case("common", "generic") .Case("440", "440") .Case("440fp", "440") .Case("450", "450") .Case("601", "601") .Case("602", "602") .Case("603", "603") .Case("603e", "603e") .Case("603ev", "603ev") .Case("604", "604") .Case("604e", "604e") .Case("620", "620") .Case("630", "pwr3") .Case("G3", "g3") .Case("7400", "7400") .Case("G4", "g4") .Case("7450", "7450") .Case("G4+", "g4+") .Case("750", "750") .Case("970", "970") .Case("G5", "g5") .Case("a2", "a2") .Case("a2q", "a2q") .Case("e500mc", "e500mc") .Case("e5500", "e5500") .Case("power3", "pwr3") .Case("power4", "pwr4") .Case("power5", "pwr5") .Case("power5x", "pwr5x") .Case("power6", "pwr6") .Case("power6x", "pwr6x") .Case("power7", "pwr7") .Case("pwr3", "pwr3") .Case("pwr4", "pwr4") .Case("pwr5", "pwr5") .Case("pwr5x", "pwr5x") .Case("pwr6", "pwr6") .Case("pwr6x", "pwr6x") .Case("pwr7", "pwr7") .Case("powerpc", "ppc") .Case("powerpc64", "ppc64") .Case("powerpc64le", "ppc64le") .Default(""); } return ""; } static void getPPCTargetFeatures(const ArgList &Args, std::vector &Features) { for (arg_iterator it = Args.filtered_begin(options::OPT_m_ppc_Features_Group), ie = Args.filtered_end(); it != ie; ++it) { StringRef Name = (*it)->getOption().getName(); (*it)->claim(); // Skip over "-m". assert(Name.startswith("m") && "Invalid feature name."); Name = Name.substr(1); bool IsNegative = Name.startswith("no-"); if (IsNegative) Name = Name.substr(3); // Note that gcc calls this mfcrf and LLVM calls this mfocrf so we // pass the correct option to the backend while calling the frontend // option the same. // TODO: Change the LLVM backend option maybe? if (Name == "mfcrf") Name = "mfocrf"; Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name)); } // Altivec is a bit weird, allow overriding of the Altivec feature here. AddTargetFeature(Args, Features, options::OPT_faltivec, options::OPT_fno_altivec, "altivec"); } /// Get the (LLVM) name of the R600 gpu we are targeting. static std::string getR600TargetGPU(const ArgList &Args) { if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { const char *GPUName = A->getValue(); return llvm::StringSwitch(GPUName) .Cases("rv630", "rv635", "r600") .Cases("rv610", "rv620", "rs780", "rs880") .Case("rv740", "rv770") .Case("palm", "cedar") .Cases("sumo", "sumo2", "sumo") .Case("hemlock", "cypress") .Case("aruba", "cayman") .Default(GPUName); } return ""; } static void getSparcTargetFeatures(const ArgList &Args, std::vector Features) { bool SoftFloatABI = true; if (Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float)) { if (A->getOption().matches(options::OPT_mhard_float)) SoftFloatABI = false; } if (SoftFloatABI) Features.push_back("+soft-float"); } void Clang::AddSparcTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { const Driver &D = getToolChain().getDriver(); // Select the float ABI as determined by -msoft-float, -mhard-float, and StringRef FloatABI; if (Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float)) { if (A->getOption().matches(options::OPT_msoft_float)) FloatABI = "soft"; else if (A->getOption().matches(options::OPT_mhard_float)) FloatABI = "hard"; } // If unspecified, choose the default based on the platform. if (FloatABI.empty()) { // Assume "soft", but warn the user we are guessing. FloatABI = "soft"; D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft"; } if (FloatABI == "soft") { // Floating point operations and argument passing are soft. // // FIXME: This changes CPP defines, we need -target-soft-float. CmdArgs.push_back("-msoft-float"); } else { assert(FloatABI == "hard" && "Invalid float abi!"); CmdArgs.push_back("-mhard-float"); } } static const char *getSystemZTargetCPU(const ArgList &Args) { if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) return A->getValue(); return "z10"; } static const char *getX86TargetCPU(const ArgList &Args, const llvm::Triple &Triple) { if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { if (StringRef(A->getValue()) != "native") { if (Triple.isOSDarwin() && Triple.getArchName() == "x86_64h") return "core-avx2"; return A->getValue(); } // FIXME: Reject attempts to use -march=native unless the target matches // the host. // // FIXME: We should also incorporate the detected target features for use // with -native. std::string CPU = llvm::sys::getHostCPUName(); if (!CPU.empty() && CPU != "generic") return Args.MakeArgString(CPU); } // Select the default CPU if none was given (or detection failed). if (Triple.getArch() != llvm::Triple::x86_64 && Triple.getArch() != llvm::Triple::x86) return 0; // This routine is only handling x86 targets. bool Is64Bit = Triple.getArch() == llvm::Triple::x86_64; // FIXME: Need target hooks. if (Triple.isOSDarwin()) { if (Triple.getArchName() == "x86_64h") return "core-avx2"; return Is64Bit ? "core2" : "yonah"; } // All x86 devices running Android have core2 as their common // denominator. This makes a better choice than pentium4. if (Triple.getEnvironment() == llvm::Triple::Android) return "core2"; // Everything else goes to x86-64 in 64-bit mode. if (Is64Bit) return "x86-64"; switch (Triple.getOS()) { case llvm::Triple::FreeBSD: case llvm::Triple::NetBSD: case llvm::Triple::OpenBSD: return "i486"; case llvm::Triple::Haiku: return "i586"; case llvm::Triple::Bitrig: return "i686"; default: // Fallback to p4. return "pentium4"; } } static std::string getCPUName(const ArgList &Args, const llvm::Triple &T) { switch(T.getArch()) { default: return ""; case llvm::Triple::aarch64: return getAArch64TargetCPU(Args, T); case llvm::Triple::arm: case llvm::Triple::thumb: return getARMTargetCPU(Args, T); case llvm::Triple::mips: case llvm::Triple::mipsel: case llvm::Triple::mips64: case llvm::Triple::mips64el: { StringRef CPUName; StringRef ABIName; getMipsCPUAndABI(Args, T, CPUName, ABIName); return CPUName; } case llvm::Triple::ppc: case llvm::Triple::ppc64: case llvm::Triple::ppc64le: { std::string TargetCPUName = getPPCTargetCPU(Args); // LLVM may default to generating code for the native CPU, // but, like gcc, we default to a more generic option for // each architecture. (except on Darwin) if (TargetCPUName.empty() && !T.isOSDarwin()) { if (T.getArch() == llvm::Triple::ppc64) TargetCPUName = "ppc64"; else if (T.getArch() == llvm::Triple::ppc64le) TargetCPUName = "ppc64le"; else TargetCPUName = "ppc"; } return TargetCPUName; } case llvm::Triple::sparc: case llvm::Triple::sparcv9: if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) return A->getValue(); return ""; case llvm::Triple::x86: case llvm::Triple::x86_64: return getX86TargetCPU(Args, T); case llvm::Triple::hexagon: return "hexagon" + toolchains::Hexagon_TC::GetTargetCPU(Args).str(); case llvm::Triple::systemz: return getSystemZTargetCPU(Args); case llvm::Triple::r600: return getR600TargetGPU(Args); } } static void getX86TargetFeatures(const llvm::Triple &Triple, const ArgList &Args, std::vector &Features) { if (Triple.getArchName() == "x86_64h") { // x86_64h implies quite a few of the more modern subtarget features // for Haswell class CPUs, but not all of them. Opt-out of a few. Features.push_back("-rdrnd"); Features.push_back("-aes"); Features.push_back("-pclmul"); Features.push_back("-rtm"); Features.push_back("-hle"); Features.push_back("-fsgsbase"); } // Now add any that the user explicitly requested on the command line, // which may override the defaults. for (arg_iterator it = Args.filtered_begin(options::OPT_m_x86_Features_Group), ie = Args.filtered_end(); it != ie; ++it) { StringRef Name = (*it)->getOption().getName(); (*it)->claim(); // Skip over "-m". assert(Name.startswith("m") && "Invalid feature name."); Name = Name.substr(1); bool IsNegative = Name.startswith("no-"); if (IsNegative) Name = Name.substr(3); Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name)); } } void Clang::AddX86TargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) || Args.hasArg(options::OPT_mkernel) || Args.hasArg(options::OPT_fapple_kext)) CmdArgs.push_back("-disable-red-zone"); // Default to avoid implicit floating-point for kernel/kext code, but allow // that to be overridden with -mno-soft-float. bool NoImplicitFloat = (Args.hasArg(options::OPT_mkernel) || Args.hasArg(options::OPT_fapple_kext)); if (Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mno_soft_float, options::OPT_mimplicit_float, options::OPT_mno_implicit_float)) { const Option &O = A->getOption(); NoImplicitFloat = (O.matches(options::OPT_mno_implicit_float) || O.matches(options::OPT_msoft_float)); } if (NoImplicitFloat) CmdArgs.push_back("-no-implicit-float"); } static inline bool HasPICArg(const ArgList &Args) { return Args.hasArg(options::OPT_fPIC) || Args.hasArg(options::OPT_fpic); } static Arg *GetLastSmallDataThresholdArg(const ArgList &Args) { return Args.getLastArg(options::OPT_G, options::OPT_G_EQ, options::OPT_msmall_data_threshold_EQ); } static std::string GetHexagonSmallDataThresholdValue(const ArgList &Args) { std::string value; if (HasPICArg(Args)) value = "0"; else if (Arg *A = GetLastSmallDataThresholdArg(Args)) { value = A->getValue(); A->claim(); } return value; } void Clang::AddHexagonTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { CmdArgs.push_back("-fno-signed-char"); CmdArgs.push_back("-mqdsp6-compat"); CmdArgs.push_back("-Wreturn-type"); std::string SmallDataThreshold = GetHexagonSmallDataThresholdValue(Args); if (!SmallDataThreshold.empty()) { CmdArgs.push_back ("-mllvm"); CmdArgs.push_back(Args.MakeArgString( "-hexagon-small-data-threshold=" + SmallDataThreshold)); } if (!Args.hasArg(options::OPT_fno_short_enums)) CmdArgs.push_back("-fshort-enums"); if (Args.getLastArg(options::OPT_mieee_rnd_near)) { CmdArgs.push_back ("-mllvm"); CmdArgs.push_back ("-enable-hexagon-ieee-rnd-near"); } CmdArgs.push_back ("-mllvm"); CmdArgs.push_back ("-machine-sink-split=0"); } static void getAArch64TargetFeatures(const Driver &D, const ArgList &Args, std::vector &Features) { // Honor -mfpu=. if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) getAArch64FPUFeatures(D, A, Args, Features); } static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple, const ArgList &Args, ArgStringList &CmdArgs) { std::vector Features; switch (Triple.getArch()) { default: break; case llvm::Triple::mips: case llvm::Triple::mipsel: case llvm::Triple::mips64: case llvm::Triple::mips64el: getMIPSTargetFeatures(D, Args, Features); break; case llvm::Triple::arm: case llvm::Triple::thumb: getARMTargetFeatures(D, Triple, Args, Features); break; case llvm::Triple::ppc: case llvm::Triple::ppc64: case llvm::Triple::ppc64le: getPPCTargetFeatures(Args, Features); break; case llvm::Triple::sparc: getSparcTargetFeatures(Args, Features); break; case llvm::Triple::aarch64: getAArch64TargetFeatures(D, Args, Features); break; case llvm::Triple::x86: case llvm::Triple::x86_64: getX86TargetFeatures(Triple, Args, Features); break; } // Find the last of each feature. llvm::StringMap LastOpt; for (unsigned I = 0, N = Features.size(); I < N; ++I) { const char *Name = Features[I]; assert(Name[0] == '-' || Name[0] == '+'); LastOpt[Name + 1] = I; } for (unsigned I = 0, N = Features.size(); I < N; ++I) { // If this feature was overridden, ignore it. const char *Name = Features[I]; llvm::StringMap::iterator LastI = LastOpt.find(Name + 1); assert(LastI != LastOpt.end()); unsigned Last = LastI->second; if (Last != I) continue; CmdArgs.push_back("-target-feature"); CmdArgs.push_back(Name); } } static bool shouldUseExceptionTablesForObjCExceptions(const ObjCRuntime &runtime, const llvm::Triple &Triple) { // We use the zero-cost exception tables for Objective-C if the non-fragile // ABI is enabled or when compiling for x86_64 and ARM on Snow Leopard and // later. if (runtime.isNonFragile()) return true; if (!Triple.isOSDarwin()) return false; return (!Triple.isMacOSXVersionLT(10,5) && (Triple.getArch() == llvm::Triple::x86_64 || Triple.getArch() == llvm::Triple::arm)); } /// addExceptionArgs - Adds exception related arguments to the driver command /// arguments. There's a master flag, -fexceptions and also language specific /// flags to enable/disable C++ and Objective-C exceptions. /// This makes it possible to for example disable C++ exceptions but enable /// Objective-C exceptions. static void addExceptionArgs(const ArgList &Args, types::ID InputType, const llvm::Triple &Triple, bool KernelOrKext, const ObjCRuntime &objcRuntime, ArgStringList &CmdArgs) { if (KernelOrKext) { // -mkernel and -fapple-kext imply no exceptions, so claim exception related // arguments now to avoid warnings about unused arguments. Args.ClaimAllArgs(options::OPT_fexceptions); Args.ClaimAllArgs(options::OPT_fno_exceptions); Args.ClaimAllArgs(options::OPT_fobjc_exceptions); Args.ClaimAllArgs(options::OPT_fno_objc_exceptions); Args.ClaimAllArgs(options::OPT_fcxx_exceptions); Args.ClaimAllArgs(options::OPT_fno_cxx_exceptions); return; } // Exceptions are enabled by default. bool ExceptionsEnabled = true; // This keeps track of whether exceptions were explicitly turned on or off. bool DidHaveExplicitExceptionFlag = false; if (Arg *A = Args.getLastArg(options::OPT_fexceptions, options::OPT_fno_exceptions)) { if (A->getOption().matches(options::OPT_fexceptions)) ExceptionsEnabled = true; else ExceptionsEnabled = false; DidHaveExplicitExceptionFlag = true; } bool ShouldUseExceptionTables = false; // Exception tables and cleanups can be enabled with -fexceptions even if the // language itself doesn't support exceptions. if (ExceptionsEnabled && DidHaveExplicitExceptionFlag) ShouldUseExceptionTables = true; // Obj-C exceptions are enabled by default, regardless of -fexceptions. This // is not necessarily sensible, but follows GCC. if (types::isObjC(InputType) && Args.hasFlag(options::OPT_fobjc_exceptions, options::OPT_fno_objc_exceptions, true)) { CmdArgs.push_back("-fobjc-exceptions"); ShouldUseExceptionTables |= shouldUseExceptionTablesForObjCExceptions(objcRuntime, Triple); } if (types::isCXX(InputType)) { bool CXXExceptionsEnabled = ExceptionsEnabled; if (Arg *A = Args.getLastArg(options::OPT_fcxx_exceptions, options::OPT_fno_cxx_exceptions, options::OPT_fexceptions, options::OPT_fno_exceptions)) { if (A->getOption().matches(options::OPT_fcxx_exceptions)) CXXExceptionsEnabled = true; else if (A->getOption().matches(options::OPT_fno_cxx_exceptions)) CXXExceptionsEnabled = false; } if (CXXExceptionsEnabled) { CmdArgs.push_back("-fcxx-exceptions"); ShouldUseExceptionTables = true; } } if (ShouldUseExceptionTables) CmdArgs.push_back("-fexceptions"); } static bool ShouldDisableAutolink(const ArgList &Args, const ToolChain &TC) { bool Default = true; if (TC.getTriple().isOSDarwin()) { // The native darwin assembler doesn't support the linker_option directives, // so we disable them if we think the .s file will be passed to it. Default = TC.useIntegratedAs(); } return !Args.hasFlag(options::OPT_fautolink, options::OPT_fno_autolink, Default); } static bool ShouldDisableCFI(const ArgList &Args, const ToolChain &TC) { bool Default = true; if (TC.getTriple().isOSDarwin()) { // The native darwin assembler doesn't support cfi directives, so // we disable them if we think the .s file will be passed to it. Default = TC.useIntegratedAs(); } return !Args.hasFlag(options::OPT_fdwarf2_cfi_asm, options::OPT_fno_dwarf2_cfi_asm, Default); } static bool ShouldDisableDwarfDirectory(const ArgList &Args, const ToolChain &TC) { bool UseDwarfDirectory = Args.hasFlag(options::OPT_fdwarf_directory_asm, options::OPT_fno_dwarf_directory_asm, TC.useIntegratedAs()); return !UseDwarfDirectory; } /// \brief Check whether the given input tree contains any compilation actions. static bool ContainsCompileAction(const Action *A) { if (isa(A)) return true; for (Action::const_iterator it = A->begin(), ie = A->end(); it != ie; ++it) if (ContainsCompileAction(*it)) return true; return false; } /// \brief Check if -relax-all should be passed to the internal assembler. /// This is done by default when compiling non-assembler source with -O0. static bool UseRelaxAll(Compilation &C, const ArgList &Args) { bool RelaxDefault = true; if (Arg *A = Args.getLastArg(options::OPT_O_Group)) RelaxDefault = A->getOption().matches(options::OPT_O0); if (RelaxDefault) { RelaxDefault = false; for (ActionList::const_iterator it = C.getActions().begin(), ie = C.getActions().end(); it != ie; ++it) { if (ContainsCompileAction(*it)) { RelaxDefault = true; break; } } } return Args.hasFlag(options::OPT_mrelax_all, options::OPT_mno_relax_all, RelaxDefault); } static void CollectArgsForIntegratedAssembler(Compilation &C, const ArgList &Args, ArgStringList &CmdArgs, const Driver &D) { if (UseRelaxAll(C, Args)) CmdArgs.push_back("-mrelax-all"); // When passing -I arguments to the assembler we sometimes need to // unconditionally take the next argument. For example, when parsing // '-Wa,-I -Wa,foo' we need to accept the -Wa,foo arg after seeing the // -Wa,-I arg and when parsing '-Wa,-I,foo' we need to accept the 'foo' // arg after parsing the '-I' arg. bool TakeNextArg = false; // When using an integrated assembler, translate -Wa, and -Xassembler // options. for (arg_iterator it = Args.filtered_begin(options::OPT_Wa_COMMA, options::OPT_Xassembler), ie = Args.filtered_end(); it != ie; ++it) { const Arg *A = *it; A->claim(); for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) { StringRef Value = A->getValue(i); if (TakeNextArg) { CmdArgs.push_back(Value.data()); TakeNextArg = false; continue; } if (Value == "-force_cpusubtype_ALL") { // Do nothing, this is the default and we don't support anything else. } else if (Value == "-L") { CmdArgs.push_back("-msave-temp-labels"); } else if (Value == "--fatal-warnings") { CmdArgs.push_back("-mllvm"); CmdArgs.push_back("-fatal-assembler-warnings"); } else if (Value == "--noexecstack") { CmdArgs.push_back("-mnoexecstack"); } else if (Value.startswith("-I")) { CmdArgs.push_back(Value.data()); // We need to consume the next argument if the current arg is a plain // -I. The next arg will be the include directory. if (Value == "-I") TakeNextArg = true; } else { D.Diag(diag::err_drv_unsupported_option_argument) << A->getOption().getName() << Value; } } } } static void addProfileRTLinux( const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) { if (!(Args.hasArg(options::OPT_fprofile_arcs) || Args.hasArg(options::OPT_fprofile_generate) || Args.hasArg(options::OPT_fcreate_profile) || Args.hasArg(options::OPT_coverage))) return; // The profile runtime is located in the Linux library directory and has name // "libclang_rt.profile-.a". SmallString<128> LibProfile(TC.getDriver().ResourceDir); llvm::sys::path::append( LibProfile, "lib", "linux", Twine("libclang_rt.profile-") + TC.getArchName() + ".a"); CmdArgs.push_back(Args.MakeArgString(LibProfile)); } static void addSanitizerRTLinkFlagsLinux( const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs, const StringRef Sanitizer, bool BeforeLibStdCXX, bool ExportSymbols = true) { // Sanitizer runtime is located in the Linux library directory and // has name "libclang_rt.-.a". SmallString<128> LibSanitizer(TC.getDriver().ResourceDir); llvm::sys::path::append( LibSanitizer, "lib", "linux", (Twine("libclang_rt.") + Sanitizer + "-" + TC.getArchName() + ".a")); // Sanitizer runtime may need to come before -lstdc++ (or -lc++, libstdc++.a, // etc.) so that the linker picks custom versions of the global 'operator // new' and 'operator delete' symbols. We take the extreme (but simple) // strategy of inserting it at the front of the link command. It also // needs to be forced to end up in the executable, so wrap it in // whole-archive. SmallVector LibSanitizerArgs; LibSanitizerArgs.push_back("-whole-archive"); LibSanitizerArgs.push_back(Args.MakeArgString(LibSanitizer)); LibSanitizerArgs.push_back("-no-whole-archive"); CmdArgs.insert(BeforeLibStdCXX ? CmdArgs.begin() : CmdArgs.end(), LibSanitizerArgs.begin(), LibSanitizerArgs.end()); CmdArgs.push_back("-lpthread"); CmdArgs.push_back("-lrt"); CmdArgs.push_back("-ldl"); CmdArgs.push_back("-lm"); // If possible, use a dynamic symbols file to export the symbols from the // runtime library. If we can't do so, use -export-dynamic instead to export // all symbols from the binary. if (ExportSymbols) { if (llvm::sys::fs::exists(LibSanitizer + ".syms")) CmdArgs.push_back( Args.MakeArgString("--dynamic-list=" + LibSanitizer + ".syms")); else CmdArgs.push_back("-export-dynamic"); } } /// If AddressSanitizer is enabled, add appropriate linker flags (Linux). /// This needs to be called before we add the C run-time (malloc, etc). static void addAsanRTLinux(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) { if (TC.getTriple().getEnvironment() == llvm::Triple::Android) { SmallString<128> LibAsan(TC.getDriver().ResourceDir); llvm::sys::path::append(LibAsan, "lib", "linux", (Twine("libclang_rt.asan-") + TC.getArchName() + "-android.so")); CmdArgs.insert(CmdArgs.begin(), Args.MakeArgString(LibAsan)); } else { if (!Args.hasArg(options::OPT_shared)) addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "asan", true); } } /// If ThreadSanitizer is enabled, add appropriate linker flags (Linux). /// This needs to be called before we add the C run-time (malloc, etc). static void addTsanRTLinux(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) { if (!Args.hasArg(options::OPT_shared)) addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "tsan", true); } /// If MemorySanitizer is enabled, add appropriate linker flags (Linux). /// This needs to be called before we add the C run-time (malloc, etc). static void addMsanRTLinux(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) { if (!Args.hasArg(options::OPT_shared)) addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "msan", true); } /// If LeakSanitizer is enabled, add appropriate linker flags (Linux). /// This needs to be called before we add the C run-time (malloc, etc). static void addLsanRTLinux(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) { if (!Args.hasArg(options::OPT_shared)) addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "lsan", true); } /// If UndefinedBehaviorSanitizer is enabled, add appropriate linker flags /// (Linux). static void addUbsanRTLinux(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs, bool IsCXX, bool HasOtherSanitizerRt) { // Need a copy of sanitizer_common. This could come from another sanitizer // runtime; if we're not including one, include our own copy. if (!HasOtherSanitizerRt) addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "san", true, false); addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "ubsan", false); // Only include the bits of the runtime which need a C++ ABI library if // we're linking in C++ mode. if (IsCXX) addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "ubsan_cxx", false); } static void addDfsanRTLinux(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) { if (!Args.hasArg(options::OPT_shared)) addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "dfsan", true); } static bool shouldUseFramePointerForTarget(const ArgList &Args, const llvm::Triple &Triple) { switch (Triple.getArch()) { // Don't use a frame pointer on linux if optimizing for certain targets. case llvm::Triple::mips64: case llvm::Triple::mips64el: case llvm::Triple::mips: case llvm::Triple::mipsel: case llvm::Triple::systemz: case llvm::Triple::x86: case llvm::Triple::x86_64: if (Triple.isOSLinux()) if (Arg *A = Args.getLastArg(options::OPT_O_Group)) if (!A->getOption().matches(options::OPT_O0)) return false; return true; case llvm::Triple::xcore: return false; default: return true; } } static bool shouldUseFramePointer(const ArgList &Args, const llvm::Triple &Triple) { if (Arg *A = Args.getLastArg(options::OPT_fno_omit_frame_pointer, options::OPT_fomit_frame_pointer)) return A->getOption().matches(options::OPT_fno_omit_frame_pointer); return shouldUseFramePointerForTarget(Args, Triple); } static bool shouldUseLeafFramePointer(const ArgList &Args, const llvm::Triple &Triple) { if (Arg *A = Args.getLastArg(options::OPT_mno_omit_leaf_frame_pointer, options::OPT_momit_leaf_frame_pointer)) return A->getOption().matches(options::OPT_mno_omit_leaf_frame_pointer); return shouldUseFramePointerForTarget(Args, Triple); } /// Add a CC1 option to specify the debug compilation directory. static void addDebugCompDirArg(const ArgList &Args, ArgStringList &CmdArgs) { SmallString<128> cwd; if (!llvm::sys::fs::current_path(cwd)) { CmdArgs.push_back("-fdebug-compilation-dir"); CmdArgs.push_back(Args.MakeArgString(cwd)); } } static const char *SplitDebugName(const ArgList &Args, const InputInfoList &Inputs) { Arg *FinalOutput = Args.getLastArg(options::OPT_o); if (FinalOutput && Args.hasArg(options::OPT_c)) { SmallString<128> T(FinalOutput->getValue()); llvm::sys::path::replace_extension(T, "dwo"); return Args.MakeArgString(T); } else { // Use the compilation dir. SmallString<128> T(Args.getLastArgValue(options::OPT_fdebug_compilation_dir)); SmallString<128> F(llvm::sys::path::stem(Inputs[0].getBaseInput())); llvm::sys::path::replace_extension(F, "dwo"); T += F; return Args.MakeArgString(F); } } static void SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T, const JobAction &JA, const ArgList &Args, const InputInfo &Output, const char *OutFile) { ArgStringList ExtractArgs; ExtractArgs.push_back("--extract-dwo"); ArgStringList StripArgs; StripArgs.push_back("--strip-dwo"); // Grabbing the output of the earlier compile step. StripArgs.push_back(Output.getFilename()); ExtractArgs.push_back(Output.getFilename()); ExtractArgs.push_back(OutFile); const char *Exec = Args.MakeArgString(TC.GetProgramPath("objcopy")); // First extract the dwo sections. C.addCommand(new Command(JA, T, Exec, ExtractArgs)); // Then remove them from the original .o file. C.addCommand(new Command(JA, T, Exec, StripArgs)); } /// \brief Vectorize at all optimization levels greater than 1 except for -Oz. static bool shouldEnableVectorizerAtOLevel(const ArgList &Args) { if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { if (A->getOption().matches(options::OPT_O4) || A->getOption().matches(options::OPT_Ofast)) return true; if (A->getOption().matches(options::OPT_O0)) return false; assert(A->getOption().matches(options::OPT_O) && "Must have a -O flag"); // Vectorize -Os. StringRef S(A->getValue()); if (S == "s") return true; // Don't vectorize -Oz. if (S == "z") return false; unsigned OptLevel = 0; if (S.getAsInteger(10, OptLevel)) return false; return OptLevel > 1; } return false; } void Clang::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { bool KernelOrKext = Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext); const Driver &D = getToolChain().getDriver(); ArgStringList CmdArgs; assert(Inputs.size() == 1 && "Unable to handle multiple inputs."); // Invoke ourselves in -cc1 mode. // // FIXME: Implement custom jobs for internal actions. CmdArgs.push_back("-cc1"); // Add the "effective" target triple. CmdArgs.push_back("-triple"); std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args); CmdArgs.push_back(Args.MakeArgString(TripleStr)); // Select the appropriate action. RewriteKind rewriteKind = RK_None; if (isa(JA)) { assert(JA.getType() == types::TY_Plist && "Invalid output type."); CmdArgs.push_back("-analyze"); } else if (isa(JA)) { CmdArgs.push_back("-migrate"); } else if (isa(JA)) { if (Output.getType() == types::TY_Dependencies) CmdArgs.push_back("-Eonly"); else { CmdArgs.push_back("-E"); if (Args.hasArg(options::OPT_rewrite_objc) && !Args.hasArg(options::OPT_g_Group)) CmdArgs.push_back("-P"); } } else if (isa(JA)) { CmdArgs.push_back("-emit-obj"); CollectArgsForIntegratedAssembler(C, Args, CmdArgs, D); // Also ignore explicit -force_cpusubtype_ALL option. (void) Args.hasArg(options::OPT_force__cpusubtype__ALL); } else if (isa(JA)) { // Use PCH if the user requested it. bool UsePCH = D.CCCUsePCH; if (JA.getType() == types::TY_Nothing) CmdArgs.push_back("-fsyntax-only"); else if (UsePCH) CmdArgs.push_back("-emit-pch"); else CmdArgs.push_back("-emit-pth"); } else { assert(isa(JA) && "Invalid action for clang tool."); if (JA.getType() == types::TY_Nothing) { CmdArgs.push_back("-fsyntax-only"); } else if (JA.getType() == types::TY_LLVM_IR || JA.getType() == types::TY_LTO_IR) { CmdArgs.push_back("-emit-llvm"); } else if (JA.getType() == types::TY_LLVM_BC || JA.getType() == types::TY_LTO_BC) { CmdArgs.push_back("-emit-llvm-bc"); } else if (JA.getType() == types::TY_PP_Asm) { CmdArgs.push_back("-S"); } else if (JA.getType() == types::TY_AST) { CmdArgs.push_back("-emit-pch"); } else if (JA.getType() == types::TY_ModuleFile) { CmdArgs.push_back("-module-file-info"); } else if (JA.getType() == types::TY_RewrittenObjC) { CmdArgs.push_back("-rewrite-objc"); rewriteKind = RK_NonFragile; } else if (JA.getType() == types::TY_RewrittenLegacyObjC) { CmdArgs.push_back("-rewrite-objc"); rewriteKind = RK_Fragile; } else { assert(JA.getType() == types::TY_PP_Asm && "Unexpected output type!"); } } // The make clang go fast button. CmdArgs.push_back("-disable-free"); // Disable the verification pass in -asserts builds. #ifdef NDEBUG CmdArgs.push_back("-disable-llvm-verifier"); #endif // Set the main file name, so that debug info works even with // -save-temps. CmdArgs.push_back("-main-file-name"); CmdArgs.push_back(getBaseInputName(Args, Inputs)); // Some flags which affect the language (via preprocessor // defines). if (Args.hasArg(options::OPT_static)) CmdArgs.push_back("-static-define"); if (isa(JA)) { // Enable region store model by default. CmdArgs.push_back("-analyzer-store=region"); // Treat blocks as analysis entry points. CmdArgs.push_back("-analyzer-opt-analyze-nested-blocks"); CmdArgs.push_back("-analyzer-eagerly-assume"); // Add default argument set. if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) { CmdArgs.push_back("-analyzer-checker=core"); if (getToolChain().getTriple().getOS() != llvm::Triple::Win32) CmdArgs.push_back("-analyzer-checker=unix"); if (getToolChain().getTriple().getVendor() == llvm::Triple::Apple) CmdArgs.push_back("-analyzer-checker=osx"); CmdArgs.push_back("-analyzer-checker=deadcode"); if (types::isCXX(Inputs[0].getType())) CmdArgs.push_back("-analyzer-checker=cplusplus"); // Enable the following experimental checkers for testing. CmdArgs.push_back("-analyzer-checker=security.insecureAPI.UncheckedReturn"); CmdArgs.push_back("-analyzer-checker=security.insecureAPI.getpw"); CmdArgs.push_back("-analyzer-checker=security.insecureAPI.gets"); CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mktemp"); CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mkstemp"); CmdArgs.push_back("-analyzer-checker=security.insecureAPI.vfork"); } // Set the output format. The default is plist, for (lame) historical // reasons. CmdArgs.push_back("-analyzer-output"); if (Arg *A = Args.getLastArg(options::OPT__analyzer_output)) CmdArgs.push_back(A->getValue()); else CmdArgs.push_back("plist"); // Disable the presentation of standard compiler warnings when // using --analyze. We only want to show static analyzer diagnostics // or frontend errors. CmdArgs.push_back("-w"); // Add -Xanalyzer arguments when running as analyzer. Args.AddAllArgValues(CmdArgs, options::OPT_Xanalyzer); } CheckCodeGenerationOptions(D, Args); bool PIE = getToolChain().isPIEDefault(); bool PIC = PIE || getToolChain().isPICDefault(); bool IsPICLevelTwo = PIC; // For the PIC and PIE flag options, this logic is different from the // legacy logic in very old versions of GCC, as that logic was just // a bug no one had ever fixed. This logic is both more rational and // consistent with GCC's new logic now that the bugs are fixed. The last // argument relating to either PIC or PIE wins, and no other argument is // used. If the last argument is any flavor of the '-fno-...' arguments, // both PIC and PIE are disabled. Any PIE option implicitly enables PIC // at the same level. Arg *LastPICArg =Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, options::OPT_fpic, options::OPT_fno_pic, options::OPT_fPIE, options::OPT_fno_PIE, options::OPT_fpie, options::OPT_fno_pie); // Check whether the tool chain trumps the PIC-ness decision. If the PIC-ness // is forced, then neither PIC nor PIE flags will have no effect. if (!getToolChain().isPICDefaultForced()) { if (LastPICArg) { Option O = LastPICArg->getOption(); if (O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic) || O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie)) { PIE = O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie); PIC = PIE || O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic); IsPICLevelTwo = O.matches(options::OPT_fPIE) || O.matches(options::OPT_fPIC); } else { PIE = PIC = false; } } } // Introduce a Darwin-specific hack. If the default is PIC but the flags // specified while enabling PIC enabled level 1 PIC, just force it back to // level 2 PIC instead. This matches the behavior of Darwin GCC (based on my // informal testing). if (PIC && getToolChain().getTriple().isOSDarwin()) IsPICLevelTwo |= getToolChain().isPICDefault(); // Note that these flags are trump-cards. Regardless of the order w.r.t. the // PIC or PIE options above, if these show up, PIC is disabled. llvm::Triple Triple(TripleStr); if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6))) PIC = PIE = false; if (Args.hasArg(options::OPT_static)) PIC = PIE = false; if (Arg *A = Args.getLastArg(options::OPT_mdynamic_no_pic)) { // This is a very special mode. It trumps the other modes, almost no one // uses it, and it isn't even valid on any OS but Darwin. if (!getToolChain().getTriple().isOSDarwin()) D.Diag(diag::err_drv_unsupported_opt_for_target) << A->getSpelling() << getToolChain().getTriple().str(); // FIXME: Warn when this flag trumps some other PIC or PIE flag. CmdArgs.push_back("-mrelocation-model"); CmdArgs.push_back("dynamic-no-pic"); // Only a forced PIC mode can cause the actual compile to have PIC defines // etc., no flags are sufficient. This behavior was selected to closely // match that of llvm-gcc and Apple GCC before that. if (getToolChain().isPICDefault() && getToolChain().isPICDefaultForced()) { CmdArgs.push_back("-pic-level"); CmdArgs.push_back("2"); } } else { // Currently, LLVM only knows about PIC vs. static; the PIE differences are // handled in Clang's IRGen by the -pie-level flag. CmdArgs.push_back("-mrelocation-model"); CmdArgs.push_back(PIC ? "pic" : "static"); if (PIC) { CmdArgs.push_back("-pic-level"); CmdArgs.push_back(IsPICLevelTwo ? "2" : "1"); if (PIE) { CmdArgs.push_back("-pie-level"); CmdArgs.push_back(IsPICLevelTwo ? "2" : "1"); } } } if (!Args.hasFlag(options::OPT_fmerge_all_constants, options::OPT_fno_merge_all_constants)) CmdArgs.push_back("-fno-merge-all-constants"); // LLVM Code Generator Options. if (Arg *A = Args.getLastArg(options::OPT_mregparm_EQ)) { CmdArgs.push_back("-mregparm"); CmdArgs.push_back(A->getValue()); } if (Arg *A = Args.getLastArg(options::OPT_fpcc_struct_return, options::OPT_freg_struct_return)) { if (getToolChain().getArch() != llvm::Triple::x86) { D.Diag(diag::err_drv_unsupported_opt_for_target) << A->getSpelling() << getToolChain().getTriple().str(); } else if (A->getOption().matches(options::OPT_fpcc_struct_return)) { CmdArgs.push_back("-fpcc-struct-return"); } else { assert(A->getOption().matches(options::OPT_freg_struct_return)); CmdArgs.push_back("-freg-struct-return"); } } if (Args.hasFlag(options::OPT_mrtd, options::OPT_mno_rtd, false)) CmdArgs.push_back("-mrtd"); if (shouldUseFramePointer(Args, getToolChain().getTriple())) CmdArgs.push_back("-mdisable-fp-elim"); if (!Args.hasFlag(options::OPT_fzero_initialized_in_bss, options::OPT_fno_zero_initialized_in_bss)) CmdArgs.push_back("-mno-zero-initialized-in-bss"); bool OFastEnabled = isOptimizationLevelFast(Args); // If -Ofast is the optimization level, then -fstrict-aliasing should be // enabled. This alias option is being used to simplify the hasFlag logic. OptSpecifier StrictAliasingAliasOption = OFastEnabled ? options::OPT_Ofast : options::OPT_fstrict_aliasing; if (!Args.hasFlag(options::OPT_fstrict_aliasing, StrictAliasingAliasOption, options::OPT_fno_strict_aliasing, true)) CmdArgs.push_back("-relaxed-aliasing"); if (!Args.hasFlag(options::OPT_fstruct_path_tbaa, options::OPT_fno_struct_path_tbaa)) CmdArgs.push_back("-no-struct-path-tbaa"); if (Args.hasFlag(options::OPT_fstrict_enums, options::OPT_fno_strict_enums, false)) CmdArgs.push_back("-fstrict-enums"); if (!Args.hasFlag(options::OPT_foptimize_sibling_calls, options::OPT_fno_optimize_sibling_calls)) CmdArgs.push_back("-mdisable-tail-calls"); // Handle segmented stacks. if (Args.hasArg(options::OPT_fsplit_stack)) CmdArgs.push_back("-split-stacks"); // If -Ofast is the optimization level, then -ffast-math should be enabled. // This alias option is being used to simplify the getLastArg logic. OptSpecifier FastMathAliasOption = OFastEnabled ? options::OPT_Ofast : options::OPT_ffast_math; // Handle various floating point optimization flags, mapping them to the // appropriate LLVM code generation flags. The pattern for all of these is to // default off the codegen optimizations, and if any flag enables them and no // flag disables them after the flag enabling them, enable the codegen // optimization. This is complicated by several "umbrella" flags. if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption, options::OPT_fno_fast_math, options::OPT_ffinite_math_only, options::OPT_fno_finite_math_only, options::OPT_fhonor_infinities, options::OPT_fno_honor_infinities)) if (A->getOption().getID() != options::OPT_fno_fast_math && A->getOption().getID() != options::OPT_fno_finite_math_only && A->getOption().getID() != options::OPT_fhonor_infinities) CmdArgs.push_back("-menable-no-infs"); if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption, options::OPT_fno_fast_math, options::OPT_ffinite_math_only, options::OPT_fno_finite_math_only, options::OPT_fhonor_nans, options::OPT_fno_honor_nans)) if (A->getOption().getID() != options::OPT_fno_fast_math && A->getOption().getID() != options::OPT_fno_finite_math_only && A->getOption().getID() != options::OPT_fhonor_nans) CmdArgs.push_back("-menable-no-nans"); // -fmath-errno is the default on some platforms, e.g. BSD-derived OSes. bool MathErrno = getToolChain().IsMathErrnoDefault(); if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption, options::OPT_fno_fast_math, options::OPT_fmath_errno, options::OPT_fno_math_errno)) { // Turning on -ffast_math (with either flag) removes the need for MathErrno. // However, turning *off* -ffast_math merely restores the toolchain default // (which may be false). if (A->getOption().getID() == options::OPT_fno_math_errno || A->getOption().getID() == options::OPT_ffast_math || A->getOption().getID() == options::OPT_Ofast) MathErrno = false; else if (A->getOption().getID() == options::OPT_fmath_errno) MathErrno = true; } if (MathErrno) CmdArgs.push_back("-fmath-errno"); // There are several flags which require disabling very specific // optimizations. Any of these being disabled forces us to turn off the // entire set of LLVM optimizations, so collect them through all the flag // madness. bool AssociativeMath = false; if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption, options::OPT_fno_fast_math, options::OPT_funsafe_math_optimizations, options::OPT_fno_unsafe_math_optimizations, options::OPT_fassociative_math, options::OPT_fno_associative_math)) if (A->getOption().getID() != options::OPT_fno_fast_math && A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations && A->getOption().getID() != options::OPT_fno_associative_math) AssociativeMath = true; bool ReciprocalMath = false; if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption, options::OPT_fno_fast_math, options::OPT_funsafe_math_optimizations, options::OPT_fno_unsafe_math_optimizations, options::OPT_freciprocal_math, options::OPT_fno_reciprocal_math)) if (A->getOption().getID() != options::OPT_fno_fast_math && A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations && A->getOption().getID() != options::OPT_fno_reciprocal_math) ReciprocalMath = true; bool SignedZeros = true; if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption, options::OPT_fno_fast_math, options::OPT_funsafe_math_optimizations, options::OPT_fno_unsafe_math_optimizations, options::OPT_fsigned_zeros, options::OPT_fno_signed_zeros)) if (A->getOption().getID() != options::OPT_fno_fast_math && A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations && A->getOption().getID() != options::OPT_fsigned_zeros) SignedZeros = false; bool TrappingMath = true; if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption, options::OPT_fno_fast_math, options::OPT_funsafe_math_optimizations, options::OPT_fno_unsafe_math_optimizations, options::OPT_ftrapping_math, options::OPT_fno_trapping_math)) if (A->getOption().getID() != options::OPT_fno_fast_math && A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations && A->getOption().getID() != options::OPT_ftrapping_math) TrappingMath = false; if (!MathErrno && AssociativeMath && ReciprocalMath && !SignedZeros && !TrappingMath) CmdArgs.push_back("-menable-unsafe-fp-math"); // Validate and pass through -fp-contract option. if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption, options::OPT_fno_fast_math, options::OPT_ffp_contract)) { if (A->getOption().getID() == options::OPT_ffp_contract) { StringRef Val = A->getValue(); if (Val == "fast" || Val == "on" || Val == "off") { CmdArgs.push_back(Args.MakeArgString("-ffp-contract=" + Val)); } else { D.Diag(diag::err_drv_unsupported_option_argument) << A->getOption().getName() << Val; } } else if (A->getOption().matches(options::OPT_ffast_math) || (OFastEnabled && A->getOption().matches(options::OPT_Ofast))) { // If fast-math is set then set the fp-contract mode to fast. CmdArgs.push_back(Args.MakeArgString("-ffp-contract=fast")); } } // We separately look for the '-ffast-math' and '-ffinite-math-only' flags, // and if we find them, tell the frontend to provide the appropriate // preprocessor macros. This is distinct from enabling any optimizations as // these options induce language changes which must survive serialization // and deserialization, etc. if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption, options::OPT_fno_fast_math)) if (!A->getOption().matches(options::OPT_fno_fast_math)) CmdArgs.push_back("-ffast-math"); if (Arg *A = Args.getLastArg(options::OPT_ffinite_math_only, options::OPT_fno_fast_math)) if (A->getOption().matches(options::OPT_ffinite_math_only)) CmdArgs.push_back("-ffinite-math-only"); // Decide whether to use verbose asm. Verbose assembly is the default on // toolchains which have the integrated assembler on by default. bool IsVerboseAsmDefault = getToolChain().IsIntegratedAssemblerDefault(); if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm, IsVerboseAsmDefault) || Args.hasArg(options::OPT_dA)) CmdArgs.push_back("-masm-verbose"); if (Args.hasArg(options::OPT_fdebug_pass_structure)) { CmdArgs.push_back("-mdebug-pass"); CmdArgs.push_back("Structure"); } if (Args.hasArg(options::OPT_fdebug_pass_arguments)) { CmdArgs.push_back("-mdebug-pass"); CmdArgs.push_back("Arguments"); } // Enable -mconstructor-aliases except on darwin, where we have to // work around a linker bug; see . if (!getToolChain().getTriple().isOSDarwin()) CmdArgs.push_back("-mconstructor-aliases"); // Darwin's kernel doesn't support guard variables; just die if we // try to use them. if (KernelOrKext && getToolChain().getTriple().isOSDarwin()) CmdArgs.push_back("-fforbid-guard-variables"); if (Args.hasArg(options::OPT_mms_bitfields)) { CmdArgs.push_back("-mms-bitfields"); } // This is a coarse approximation of what llvm-gcc actually does, both // -fasynchronous-unwind-tables and -fnon-call-exceptions interact in more // complicated ways. bool AsynchronousUnwindTables = Args.hasFlag(options::OPT_fasynchronous_unwind_tables, options::OPT_fno_asynchronous_unwind_tables, getToolChain().IsUnwindTablesDefault() && !KernelOrKext); if (Args.hasFlag(options::OPT_funwind_tables, options::OPT_fno_unwind_tables, AsynchronousUnwindTables)) CmdArgs.push_back("-munwind-tables"); getToolChain().addClangTargetOptions(Args, CmdArgs); if (Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) { CmdArgs.push_back("-mlimit-float-precision"); CmdArgs.push_back(A->getValue()); } // FIXME: Handle -mtune=. (void) Args.hasArg(options::OPT_mtune_EQ); if (Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) { CmdArgs.push_back("-mcode-model"); CmdArgs.push_back(A->getValue()); } // Add the target cpu std::string ETripleStr = getToolChain().ComputeEffectiveClangTriple(Args); llvm::Triple ETriple(ETripleStr); std::string CPU = getCPUName(Args, ETriple); if (!CPU.empty()) { CmdArgs.push_back("-target-cpu"); CmdArgs.push_back(Args.MakeArgString(CPU)); } if (const Arg *A = Args.getLastArg(options::OPT_mfpmath_EQ)) { CmdArgs.push_back("-mfpmath"); CmdArgs.push_back(A->getValue()); } // Add the target features getTargetFeatures(D, ETriple, Args, CmdArgs); // Add target specific flags. switch(getToolChain().getArch()) { default: break; case llvm::Triple::arm: case llvm::Triple::thumb: AddARMTargetArgs(Args, CmdArgs, KernelOrKext); break; case llvm::Triple::mips: case llvm::Triple::mipsel: case llvm::Triple::mips64: case llvm::Triple::mips64el: AddMIPSTargetArgs(Args, CmdArgs); break; case llvm::Triple::sparc: AddSparcTargetArgs(Args, CmdArgs); break; case llvm::Triple::x86: case llvm::Triple::x86_64: AddX86TargetArgs(Args, CmdArgs); break; case llvm::Triple::hexagon: AddHexagonTargetArgs(Args, CmdArgs); break; } // Add clang-cl arguments. if (getToolChain().getDriver().IsCLMode()) AddClangCLArgs(Args, CmdArgs); // Pass the linker version in use. if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) { CmdArgs.push_back("-target-linker-version"); CmdArgs.push_back(A->getValue()); } if (!shouldUseLeafFramePointer(Args, getToolChain().getTriple())) CmdArgs.push_back("-momit-leaf-frame-pointer"); // Explicitly error on some things we know we don't support and can't just // ignore. types::ID InputType = Inputs[0].getType(); if (!Args.hasArg(options::OPT_fallow_unsupported)) { Arg *Unsupported; if (types::isCXX(InputType) && getToolChain().getTriple().isOSDarwin() && getToolChain().getArch() == llvm::Triple::x86) { if ((Unsupported = Args.getLastArg(options::OPT_fapple_kext)) || (Unsupported = Args.getLastArg(options::OPT_mkernel))) D.Diag(diag::err_drv_clang_unsupported_opt_cxx_darwin_i386) << Unsupported->getOption().getName(); } } Args.AddAllArgs(CmdArgs, options::OPT_v); Args.AddLastArg(CmdArgs, options::OPT_H); if (D.CCPrintHeaders && !D.CCGenDiagnostics) { CmdArgs.push_back("-header-include-file"); CmdArgs.push_back(D.CCPrintHeadersFilename ? D.CCPrintHeadersFilename : "-"); } Args.AddLastArg(CmdArgs, options::OPT_P); Args.AddLastArg(CmdArgs, options::OPT_print_ivar_layout); if (D.CCLogDiagnostics && !D.CCGenDiagnostics) { CmdArgs.push_back("-diagnostic-log-file"); CmdArgs.push_back(D.CCLogDiagnosticsFilename ? D.CCLogDiagnosticsFilename : "-"); } // Use the last option from "-g" group. "-gline-tables-only" // is preserved, all other debug options are substituted with "-g". Args.ClaimAllArgs(options::OPT_g_Group); if (Arg *A = Args.getLastArg(options::OPT_g_Group)) { if (A->getOption().matches(options::OPT_gline_tables_only)) CmdArgs.push_back("-gline-tables-only"); else if (A->getOption().matches(options::OPT_gdwarf_2)) CmdArgs.push_back("-gdwarf-2"); else if (A->getOption().matches(options::OPT_gdwarf_3)) CmdArgs.push_back("-gdwarf-3"); else if (A->getOption().matches(options::OPT_gdwarf_4)) CmdArgs.push_back("-gdwarf-4"); else if (!A->getOption().matches(options::OPT_g0) && !A->getOption().matches(options::OPT_ggdb0)) { // Default is dwarf-2 for darwin and FreeBSD. const llvm::Triple &Triple = getToolChain().getTriple(); if (Triple.isOSDarwin() || Triple.getOS() == llvm::Triple::FreeBSD) CmdArgs.push_back("-gdwarf-2"); else CmdArgs.push_back("-g"); } } // We ignore flags -gstrict-dwarf and -grecord-gcc-switches for now. Args.ClaimAllArgs(options::OPT_g_flags_Group); if (Args.hasArg(options::OPT_gcolumn_info)) CmdArgs.push_back("-dwarf-column-info"); // FIXME: Move backend command line options to the module. // -gsplit-dwarf should turn on -g and enable the backend dwarf // splitting and extraction. // FIXME: Currently only works on Linux. if (getToolChain().getTriple().isOSLinux() && Args.hasArg(options::OPT_gsplit_dwarf)) { CmdArgs.push_back("-g"); CmdArgs.push_back("-backend-option"); CmdArgs.push_back("-split-dwarf=Enable"); } // -ggnu-pubnames turns on gnu style pubnames in the backend. if (Args.hasArg(options::OPT_ggnu_pubnames)) { CmdArgs.push_back("-backend-option"); CmdArgs.push_back("-generate-gnu-dwarf-pub-sections"); } Args.AddAllArgs(CmdArgs, options::OPT_fdebug_types_section); Args.AddAllArgs(CmdArgs, options::OPT_ffunction_sections); Args.AddAllArgs(CmdArgs, options::OPT_fdata_sections); Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions); if (Args.hasArg(options::OPT_ftest_coverage) || Args.hasArg(options::OPT_coverage)) CmdArgs.push_back("-femit-coverage-notes"); if (Args.hasArg(options::OPT_fprofile_arcs) || Args.hasArg(options::OPT_coverage)) CmdArgs.push_back("-femit-coverage-data"); if (C.getArgs().hasArg(options::OPT_c) || C.getArgs().hasArg(options::OPT_S)) { if (Output.isFilename()) { CmdArgs.push_back("-coverage-file"); SmallString<128> CoverageFilename(Output.getFilename()); if (llvm::sys::path::is_relative(CoverageFilename.str())) { SmallString<128> Pwd; if (!llvm::sys::fs::current_path(Pwd)) { llvm::sys::path::append(Pwd, CoverageFilename.str()); CoverageFilename.swap(Pwd); } } CmdArgs.push_back(Args.MakeArgString(CoverageFilename)); } } // Pass options for controlling the default header search paths. if (Args.hasArg(options::OPT_nostdinc)) { CmdArgs.push_back("-nostdsysteminc"); CmdArgs.push_back("-nobuiltininc"); } else { if (Args.hasArg(options::OPT_nostdlibinc)) CmdArgs.push_back("-nostdsysteminc"); Args.AddLastArg(CmdArgs, options::OPT_nostdincxx); Args.AddLastArg(CmdArgs, options::OPT_nobuiltininc); } // Pass the path to compiler resource files. CmdArgs.push_back("-resource-dir"); CmdArgs.push_back(D.ResourceDir.c_str()); Args.AddLastArg(CmdArgs, options::OPT_working_directory); bool ARCMTEnabled = false; if (!Args.hasArg(options::OPT_fno_objc_arc, options::OPT_fobjc_arc)) { if (const Arg *A = Args.getLastArg(options::OPT_ccc_arcmt_check, options::OPT_ccc_arcmt_modify, options::OPT_ccc_arcmt_migrate)) { ARCMTEnabled = true; switch (A->getOption().getID()) { default: llvm_unreachable("missed a case"); case options::OPT_ccc_arcmt_check: CmdArgs.push_back("-arcmt-check"); break; case options::OPT_ccc_arcmt_modify: CmdArgs.push_back("-arcmt-modify"); break; case options::OPT_ccc_arcmt_migrate: CmdArgs.push_back("-arcmt-migrate"); CmdArgs.push_back("-mt-migrate-directory"); CmdArgs.push_back(A->getValue()); Args.AddLastArg(CmdArgs, options::OPT_arcmt_migrate_report_output); Args.AddLastArg(CmdArgs, options::OPT_arcmt_migrate_emit_arc_errors); break; } } } else { Args.ClaimAllArgs(options::OPT_ccc_arcmt_check); Args.ClaimAllArgs(options::OPT_ccc_arcmt_modify); Args.ClaimAllArgs(options::OPT_ccc_arcmt_migrate); } if (const Arg *A = Args.getLastArg(options::OPT_ccc_objcmt_migrate)) { if (ARCMTEnabled) { D.Diag(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args) << "-ccc-arcmt-migrate"; } CmdArgs.push_back("-mt-migrate-directory"); CmdArgs.push_back(A->getValue()); if (!Args.hasArg(options::OPT_objcmt_migrate_literals, options::OPT_objcmt_migrate_subscripting, options::OPT_objcmt_migrate_property)) { // None specified, means enable them all. CmdArgs.push_back("-objcmt-migrate-literals"); CmdArgs.push_back("-objcmt-migrate-subscripting"); CmdArgs.push_back("-objcmt-migrate-property"); } else { Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_literals); Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_subscripting); Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property); } } else { Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_literals); Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_subscripting); Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property); Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_all); Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_readonly_property); Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_readwrite_property); Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_annotation); Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_instancetype); Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_nsmacros); Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_protocol_conformance); Args.AddLastArg(CmdArgs, options::OPT_objcmt_atomic_property); Args.AddLastArg(CmdArgs, options::OPT_objcmt_returns_innerpointer_property); Args.AddLastArg(CmdArgs, options::OPT_objcmt_ns_nonatomic_iosonly); Args.AddLastArg(CmdArgs, options::OPT_objcmt_white_list_dir_path); } // Add preprocessing options like -I, -D, etc. if we are using the // preprocessor. // // FIXME: Support -fpreprocessed if (types::getPreprocessedType(InputType) != types::TY_INVALID) AddPreprocessingOptions(C, JA, D, Args, CmdArgs, Output, Inputs); // Don't warn about "clang -c -DPIC -fPIC test.i" because libtool.m4 assumes // that "The compiler can only warn and ignore the option if not recognized". // When building with ccache, it will pass -D options to clang even on // preprocessed inputs and configure concludes that -fPIC is not supported. Args.ClaimAllArgs(options::OPT_D); // Manually translate -O4 to -O3; let clang reject others. if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { if (A->getOption().matches(options::OPT_O4)) { CmdArgs.push_back("-O3"); D.Diag(diag::warn_O4_is_O3); } else { A->render(Args, CmdArgs); } } // Don't warn about unused -flto. This can happen when we're preprocessing or // precompiling. Args.ClaimAllArgs(options::OPT_flto); Args.AddAllArgs(CmdArgs, options::OPT_W_Group); if (Args.hasFlag(options::OPT_pedantic, options::OPT_no_pedantic, false)) CmdArgs.push_back("-pedantic"); Args.AddLastArg(CmdArgs, options::OPT_pedantic_errors); Args.AddLastArg(CmdArgs, options::OPT_w); // Handle -{std, ansi, trigraphs} -- take the last of -{std, ansi} // (-ansi is equivalent to -std=c89 or -std=c++98). // // If a std is supplied, only add -trigraphs if it follows the // option. if (Arg *Std = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi)) { if (Std->getOption().matches(options::OPT_ansi)) if (types::isCXX(InputType)) CmdArgs.push_back("-std=c++98"); else CmdArgs.push_back("-std=c89"); else Std->render(Args, CmdArgs); if (Arg *A = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi, options::OPT_trigraphs)) if (A != Std) A->render(Args, CmdArgs); } else { // Honor -std-default. // // FIXME: Clang doesn't correctly handle -std= when the input language // doesn't match. For the time being just ignore this for C++ inputs; // eventually we want to do all the standard defaulting here instead of // splitting it between the driver and clang -cc1. if (!types::isCXX(InputType)) Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ, "-std=", /*Joined=*/true); else if (getToolChain().getTriple().getOS() == llvm::Triple::Win32) CmdArgs.push_back("-std=c++11"); Args.AddLastArg(CmdArgs, options::OPT_trigraphs); } // GCC's behavior for -Wwrite-strings is a bit strange: // * In C, this "warning flag" changes the types of string literals from // 'char[N]' to 'const char[N]', and thus triggers an unrelated warning // for the discarded qualifier. // * In C++, this is just a normal warning flag. // // Implementing this warning correctly in C is hard, so we follow GCC's // behavior for now. FIXME: Directly diagnose uses of a string literal as // a non-const char* in C, rather than using this crude hack. if (!types::isCXX(InputType)) { DiagnosticsEngine::Level DiagLevel = D.getDiags().getDiagnosticLevel( diag::warn_deprecated_string_literal_conversion_c, SourceLocation()); if (DiagLevel > DiagnosticsEngine::Ignored) CmdArgs.push_back("-fconst-strings"); } // GCC provides a macro definition '__DEPRECATED' when -Wdeprecated is active // during C++ compilation, which it is by default. GCC keeps this define even // in the presence of '-w', match this behavior bug-for-bug. if (types::isCXX(InputType) && Args.hasFlag(options::OPT_Wdeprecated, options::OPT_Wno_deprecated, true)) { CmdArgs.push_back("-fdeprecated-macro"); } // Translate GCC's misnamer '-fasm' arguments to '-fgnu-keywords'. if (Arg *Asm = Args.getLastArg(options::OPT_fasm, options::OPT_fno_asm)) { if (Asm->getOption().matches(options::OPT_fasm)) CmdArgs.push_back("-fgnu-keywords"); else CmdArgs.push_back("-fno-gnu-keywords"); } if (ShouldDisableCFI(Args, getToolChain())) CmdArgs.push_back("-fno-dwarf2-cfi-asm"); if (ShouldDisableDwarfDirectory(Args, getToolChain())) CmdArgs.push_back("-fno-dwarf-directory-asm"); if (ShouldDisableAutolink(Args, getToolChain())) CmdArgs.push_back("-fno-autolink"); // Add in -fdebug-compilation-dir if necessary. addDebugCompDirArg(Args, CmdArgs); if (Arg *A = Args.getLastArg(options::OPT_ftemplate_depth_, options::OPT_ftemplate_depth_EQ)) { CmdArgs.push_back("-ftemplate-depth"); CmdArgs.push_back(A->getValue()); } if (Arg *A = Args.getLastArg(options::OPT_foperator_arrow_depth_EQ)) { CmdArgs.push_back("-foperator-arrow-depth"); CmdArgs.push_back(A->getValue()); } if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_depth_EQ)) { CmdArgs.push_back("-fconstexpr-depth"); CmdArgs.push_back(A->getValue()); } if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_steps_EQ)) { CmdArgs.push_back("-fconstexpr-steps"); CmdArgs.push_back(A->getValue()); } if (Arg *A = Args.getLastArg(options::OPT_fbracket_depth_EQ)) { CmdArgs.push_back("-fbracket-depth"); CmdArgs.push_back(A->getValue()); } if (Arg *A = Args.getLastArg(options::OPT_Wlarge_by_value_copy_EQ, options::OPT_Wlarge_by_value_copy_def)) { if (A->getNumValues()) { StringRef bytes = A->getValue(); CmdArgs.push_back(Args.MakeArgString("-Wlarge-by-value-copy=" + bytes)); } else CmdArgs.push_back("-Wlarge-by-value-copy=64"); // default value } if (Args.hasArg(options::OPT_relocatable_pch)) CmdArgs.push_back("-relocatable-pch"); if (Arg *A = Args.getLastArg(options::OPT_fconstant_string_class_EQ)) { CmdArgs.push_back("-fconstant-string-class"); CmdArgs.push_back(A->getValue()); } if (Arg *A = Args.getLastArg(options::OPT_ftabstop_EQ)) { CmdArgs.push_back("-ftabstop"); CmdArgs.push_back(A->getValue()); } CmdArgs.push_back("-ferror-limit"); if (Arg *A = Args.getLastArg(options::OPT_ferror_limit_EQ)) CmdArgs.push_back(A->getValue()); else CmdArgs.push_back("19"); if (Arg *A = Args.getLastArg(options::OPT_fmacro_backtrace_limit_EQ)) { CmdArgs.push_back("-fmacro-backtrace-limit"); CmdArgs.push_back(A->getValue()); } if (Arg *A = Args.getLastArg(options::OPT_ftemplate_backtrace_limit_EQ)) { CmdArgs.push_back("-ftemplate-backtrace-limit"); CmdArgs.push_back(A->getValue()); } if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_backtrace_limit_EQ)) { CmdArgs.push_back("-fconstexpr-backtrace-limit"); CmdArgs.push_back(A->getValue()); } // Pass -fmessage-length=. CmdArgs.push_back("-fmessage-length"); if (Arg *A = Args.getLastArg(options::OPT_fmessage_length_EQ)) { CmdArgs.push_back(A->getValue()); } else { // If -fmessage-length=N was not specified, determine whether this is a // terminal and, if so, implicitly define -fmessage-length appropriately. unsigned N = llvm::sys::Process::StandardErrColumns(); CmdArgs.push_back(Args.MakeArgString(Twine(N))); } // -fvisibility= and -fvisibility-ms-compat are of a piece. if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ, options::OPT_fvisibility_ms_compat)) { if (A->getOption().matches(options::OPT_fvisibility_EQ)) { CmdArgs.push_back("-fvisibility"); CmdArgs.push_back(A->getValue()); } else { assert(A->getOption().matches(options::OPT_fvisibility_ms_compat)); CmdArgs.push_back("-fvisibility"); CmdArgs.push_back("hidden"); CmdArgs.push_back("-ftype-visibility"); CmdArgs.push_back("default"); } } Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden); Args.AddLastArg(CmdArgs, options::OPT_ftlsmodel_EQ); // -fhosted is default. if (Args.hasFlag(options::OPT_ffreestanding, options::OPT_fhosted, false) || KernelOrKext) CmdArgs.push_back("-ffreestanding"); // Forward -f (flag) options which we can pass directly. Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls); Args.AddLastArg(CmdArgs, options::OPT_fformat_extensions); Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions); - Args.AddLastArg(CmdArgs, options::OPT_flimit_debug_info); - Args.AddLastArg(CmdArgs, options::OPT_fno_limit_debug_info); + Args.AddLastArg(CmdArgs, options::OPT_fstandalone_debug); + Args.AddLastArg(CmdArgs, options::OPT_fno_standalone_debug); Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names); // AltiVec language extensions aren't relevant for assembling. if (!isa(JA) || Output.getType() != types::TY_PP_Asm) Args.AddLastArg(CmdArgs, options::OPT_faltivec); Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_show_template_tree); Args.AddLastArg(CmdArgs, options::OPT_fno_elide_type); const SanitizerArgs &Sanitize = getToolChain().getSanitizerArgs(); Sanitize.addArgs(Args, CmdArgs); if (!Args.hasFlag(options::OPT_fsanitize_recover, options::OPT_fno_sanitize_recover, true)) CmdArgs.push_back("-fno-sanitize-recover"); if (Args.hasArg(options::OPT_fcatch_undefined_behavior) || Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error, options::OPT_fno_sanitize_undefined_trap_on_error, false)) CmdArgs.push_back("-fsanitize-undefined-trap-on-error"); // Report an error for -faltivec on anything other than PowerPC. if (const Arg *A = Args.getLastArg(options::OPT_faltivec)) if (!(getToolChain().getArch() == llvm::Triple::ppc || getToolChain().getArch() == llvm::Triple::ppc64 || getToolChain().getArch() == llvm::Triple::ppc64le)) D.Diag(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args) << "ppc/ppc64/ppc64le"; if (getToolChain().SupportsProfiling()) Args.AddLastArg(CmdArgs, options::OPT_pg); // -flax-vector-conversions is default. if (!Args.hasFlag(options::OPT_flax_vector_conversions, options::OPT_fno_lax_vector_conversions)) CmdArgs.push_back("-fno-lax-vector-conversions"); if (Args.getLastArg(options::OPT_fapple_kext)) CmdArgs.push_back("-fapple-kext"); if (Args.hasFlag(options::OPT_frewrite_includes, options::OPT_fno_rewrite_includes, false)) CmdArgs.push_back("-frewrite-includes"); Args.AddLastArg(CmdArgs, options::OPT_fobjc_sender_dependent_dispatch); Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_print_source_range_info); Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_parseable_fixits); Args.AddLastArg(CmdArgs, options::OPT_ftime_report); Args.AddLastArg(CmdArgs, options::OPT_ftrapv); if (Arg *A = Args.getLastArg(options::OPT_ftrapv_handler_EQ)) { CmdArgs.push_back("-ftrapv-handler"); CmdArgs.push_back(A->getValue()); } Args.AddLastArg(CmdArgs, options::OPT_ftrap_function_EQ); // -fno-strict-overflow implies -fwrapv if it isn't disabled, but // -fstrict-overflow won't turn off an explicitly enabled -fwrapv. if (Arg *A = Args.getLastArg(options::OPT_fwrapv, options::OPT_fno_wrapv)) { if (A->getOption().matches(options::OPT_fwrapv)) CmdArgs.push_back("-fwrapv"); } else if (Arg *A = Args.getLastArg(options::OPT_fstrict_overflow, options::OPT_fno_strict_overflow)) { if (A->getOption().matches(options::OPT_fno_strict_overflow)) CmdArgs.push_back("-fwrapv"); } if (Arg *A = Args.getLastArg(options::OPT_freroll_loops, options::OPT_fno_reroll_loops)) if (A->getOption().matches(options::OPT_freroll_loops)) CmdArgs.push_back("-freroll-loops"); Args.AddLastArg(CmdArgs, options::OPT_fwritable_strings); Args.AddLastArg(CmdArgs, options::OPT_funroll_loops, options::OPT_fno_unroll_loops); Args.AddLastArg(CmdArgs, options::OPT_pthread); // -stack-protector=0 is default. unsigned StackProtectorLevel = 0; if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector, options::OPT_fstack_protector_all, options::OPT_fstack_protector)) { if (A->getOption().matches(options::OPT_fstack_protector)) StackProtectorLevel = 1; else if (A->getOption().matches(options::OPT_fstack_protector_all)) StackProtectorLevel = 2; } else { StackProtectorLevel = getToolChain().GetDefaultStackProtectorLevel(KernelOrKext); } if (StackProtectorLevel) { CmdArgs.push_back("-stack-protector"); CmdArgs.push_back(Args.MakeArgString(Twine(StackProtectorLevel))); } // --param ssp-buffer-size= for (arg_iterator it = Args.filtered_begin(options::OPT__param), ie = Args.filtered_end(); it != ie; ++it) { StringRef Str((*it)->getValue()); if (Str.startswith("ssp-buffer-size=")) { if (StackProtectorLevel) { CmdArgs.push_back("-stack-protector-buffer-size"); // FIXME: Verify the argument is a valid integer. CmdArgs.push_back(Args.MakeArgString(Str.drop_front(16))); } (*it)->claim(); } } // Translate -mstackrealign if (Args.hasFlag(options::OPT_mstackrealign, options::OPT_mno_stackrealign, false)) { CmdArgs.push_back("-backend-option"); CmdArgs.push_back("-force-align-stack"); } if (!Args.hasFlag(options::OPT_mno_stackrealign, options::OPT_mstackrealign, false)) { CmdArgs.push_back(Args.MakeArgString("-mstackrealign")); } if (Args.hasArg(options::OPT_mstack_alignment)) { StringRef alignment = Args.getLastArgValue(options::OPT_mstack_alignment); CmdArgs.push_back(Args.MakeArgString("-mstack-alignment=" + alignment)); } // -mkernel implies -mstrict-align; don't add the redundant option. if (!KernelOrKext) { if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access, options::OPT_munaligned_access)) { if (A->getOption().matches(options::OPT_mno_unaligned_access)) { CmdArgs.push_back("-backend-option"); CmdArgs.push_back("-arm-strict-align"); } else { CmdArgs.push_back("-backend-option"); CmdArgs.push_back("-arm-no-strict-align"); } } } if (Arg *A = Args.getLastArg(options::OPT_mrestrict_it, options::OPT_mno_restrict_it)) { if (A->getOption().matches(options::OPT_mrestrict_it)) { CmdArgs.push_back("-backend-option"); CmdArgs.push_back("-arm-restrict-it"); } else { CmdArgs.push_back("-backend-option"); CmdArgs.push_back("-arm-no-restrict-it"); } } // Forward -f options with positive and negative forms; we translate // these by hand. if (Arg *A = Args.getLastArg(options::OPT_fprofile_sample_use_EQ)) { StringRef fname = A->getValue(); if (!llvm::sys::fs::exists(fname)) D.Diag(diag::err_drv_no_such_file) << fname; else A->render(Args, CmdArgs); } if (Args.hasArg(options::OPT_mkernel)) { if (!Args.hasArg(options::OPT_fapple_kext) && types::isCXX(InputType)) CmdArgs.push_back("-fapple-kext"); if (!Args.hasArg(options::OPT_fbuiltin)) CmdArgs.push_back("-fno-builtin"); Args.ClaimAllArgs(options::OPT_fno_builtin); } // -fbuiltin is default. else if (!Args.hasFlag(options::OPT_fbuiltin, options::OPT_fno_builtin)) CmdArgs.push_back("-fno-builtin"); if (!Args.hasFlag(options::OPT_fassume_sane_operator_new, options::OPT_fno_assume_sane_operator_new)) CmdArgs.push_back("-fno-assume-sane-operator-new"); // -fblocks=0 is default. if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks, getToolChain().IsBlocksDefault()) || (Args.hasArg(options::OPT_fgnu_runtime) && Args.hasArg(options::OPT_fobjc_nonfragile_abi) && !Args.hasArg(options::OPT_fno_blocks))) { CmdArgs.push_back("-fblocks"); if (!Args.hasArg(options::OPT_fgnu_runtime) && !getToolChain().hasBlocksRuntime()) CmdArgs.push_back("-fblocks-runtime-optional"); } // -fmodules enables modules (off by default). However, for C++/Objective-C++, // users must also pass -fcxx-modules. The latter flag will disappear once the // modules implementation is solid for C++/Objective-C++ programs as well. bool HaveModules = false; if (Args.hasFlag(options::OPT_fmodules, options::OPT_fno_modules, false)) { bool AllowedInCXX = Args.hasFlag(options::OPT_fcxx_modules, options::OPT_fno_cxx_modules, false); if (AllowedInCXX || !types::isCXX(InputType)) { CmdArgs.push_back("-fmodules"); HaveModules = true; } } // -fmodule-maps enables module map processing (off by default) for header // checking. It is implied by -fmodules. if (Args.hasFlag(options::OPT_fmodule_maps, options::OPT_fno_module_maps, false)) { CmdArgs.push_back("-fmodule-maps"); } // -fmodules-decluse checks that modules used are declared so (off by // default). if (Args.hasFlag(options::OPT_fmodules_decluse, options::OPT_fno_modules_decluse, false)) { CmdArgs.push_back("-fmodules-decluse"); } // -fmodule-name specifies the module that is currently being built (or // used for header checking by -fmodule-maps). if (Arg *A = Args.getLastArg(options::OPT_fmodule_name)) { A->claim(); A->render(Args, CmdArgs); } // -fmodule-map-file can be used to specify a file containing module // definitions. if (Arg *A = Args.getLastArg(options::OPT_fmodule_map_file)) { A->claim(); A->render(Args, CmdArgs); } // If a module path was provided, pass it along. Otherwise, use a temporary // directory. if (Arg *A = Args.getLastArg(options::OPT_fmodules_cache_path)) { A->claim(); if (HaveModules) { A->render(Args, CmdArgs); } } else if (HaveModules) { SmallString<128> DefaultModuleCache; llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false, DefaultModuleCache); llvm::sys::path::append(DefaultModuleCache, "org.llvm.clang"); llvm::sys::path::append(DefaultModuleCache, "ModuleCache"); const char Arg[] = "-fmodules-cache-path="; DefaultModuleCache.insert(DefaultModuleCache.begin(), Arg, Arg + strlen(Arg)); CmdArgs.push_back(Args.MakeArgString(DefaultModuleCache)); } // Pass through all -fmodules-ignore-macro arguments. Args.AddAllArgs(CmdArgs, options::OPT_fmodules_ignore_macro); Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_interval); Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_after); // -faccess-control is default. if (Args.hasFlag(options::OPT_fno_access_control, options::OPT_faccess_control, false)) CmdArgs.push_back("-fno-access-control"); // -felide-constructors is the default. if (Args.hasFlag(options::OPT_fno_elide_constructors, options::OPT_felide_constructors, false)) CmdArgs.push_back("-fno-elide-constructors"); // -frtti is default. if (!Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti) || KernelOrKext) { CmdArgs.push_back("-fno-rtti"); // -fno-rtti cannot usefully be combined with -fsanitize=vptr. if (Sanitize.sanitizesVptr()) { std::string NoRttiArg = Args.getLastArg(options::OPT_mkernel, options::OPT_fapple_kext, options::OPT_fno_rtti)->getAsString(Args); D.Diag(diag::err_drv_argument_not_allowed_with) << "-fsanitize=vptr" << NoRttiArg; } } // -fshort-enums=0 is default for all architectures except Hexagon. if (Args.hasFlag(options::OPT_fshort_enums, options::OPT_fno_short_enums, getToolChain().getArch() == llvm::Triple::hexagon)) CmdArgs.push_back("-fshort-enums"); // -fsigned-char is default. if (!Args.hasFlag(options::OPT_fsigned_char, options::OPT_funsigned_char, isSignedCharDefault(getToolChain().getTriple()))) CmdArgs.push_back("-fno-signed-char"); // -fthreadsafe-static is default. if (!Args.hasFlag(options::OPT_fthreadsafe_statics, options::OPT_fno_threadsafe_statics)) CmdArgs.push_back("-fno-threadsafe-statics"); // -fuse-cxa-atexit is default. if (!Args.hasFlag( options::OPT_fuse_cxa_atexit, options::OPT_fno_use_cxa_atexit, getToolChain().getTriple().getOS() != llvm::Triple::Cygwin && getToolChain().getTriple().getOS() != llvm::Triple::MinGW32 && getToolChain().getArch() != llvm::Triple::hexagon && getToolChain().getArch() != llvm::Triple::xcore) || KernelOrKext) CmdArgs.push_back("-fno-use-cxa-atexit"); // -fms-extensions=0 is default. if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions, getToolChain().getTriple().getOS() == llvm::Triple::Win32)) CmdArgs.push_back("-fms-extensions"); // -fms-compatibility=0 is default. if (Args.hasFlag(options::OPT_fms_compatibility, options::OPT_fno_ms_compatibility, (getToolChain().getTriple().getOS() == llvm::Triple::Win32 && Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions, true)))) CmdArgs.push_back("-fms-compatibility"); // -fmsc-version=1700 is default. if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions, getToolChain().getTriple().getOS() == llvm::Triple::Win32) || Args.hasArg(options::OPT_fmsc_version)) { StringRef msc_ver = Args.getLastArgValue(options::OPT_fmsc_version); if (msc_ver.empty()) CmdArgs.push_back("-fmsc-version=1700"); else CmdArgs.push_back(Args.MakeArgString("-fmsc-version=" + msc_ver)); } // -fno-borland-extensions is default. if (Args.hasFlag(options::OPT_fborland_extensions, options::OPT_fno_borland_extensions, false)) CmdArgs.push_back("-fborland-extensions"); // -fno-delayed-template-parsing is default, except for Windows where MSVC STL // needs it. if (Args.hasFlag(options::OPT_fdelayed_template_parsing, options::OPT_fno_delayed_template_parsing, getToolChain().getTriple().getOS() == llvm::Triple::Win32)) CmdArgs.push_back("-fdelayed-template-parsing"); // -fgnu-keywords default varies depending on language; only pass if // specified. if (Arg *A = Args.getLastArg(options::OPT_fgnu_keywords, options::OPT_fno_gnu_keywords)) A->render(Args, CmdArgs); if (Args.hasFlag(options::OPT_fgnu89_inline, options::OPT_fno_gnu89_inline, false)) CmdArgs.push_back("-fgnu89-inline"); if (Args.hasArg(options::OPT_fno_inline)) CmdArgs.push_back("-fno-inline"); if (Args.hasArg(options::OPT_fno_inline_functions)) CmdArgs.push_back("-fno-inline-functions"); ObjCRuntime objcRuntime = AddObjCRuntimeArgs(Args, CmdArgs, rewriteKind); // -fobjc-dispatch-method is only relevant with the nonfragile-abi, and // legacy is the default. Next runtime is always legacy dispatch and // -fno-objc-legacy-dispatch gets ignored silently. if (objcRuntime.isNonFragile() && !objcRuntime.isNeXTFamily()) { if (!Args.hasFlag(options::OPT_fobjc_legacy_dispatch, options::OPT_fno_objc_legacy_dispatch, objcRuntime.isLegacyDispatchDefaultForArch( getToolChain().getArch()))) { if (getToolChain().UseObjCMixedDispatch()) CmdArgs.push_back("-fobjc-dispatch-method=mixed"); else CmdArgs.push_back("-fobjc-dispatch-method=non-legacy"); } } // When ObjectiveC legacy runtime is in effect on MacOSX, // turn on the option to do Array/Dictionary subscripting // by default. if (getToolChain().getTriple().getArch() == llvm::Triple::x86 && getToolChain().getTriple().isMacOSX() && !getToolChain().getTriple().isMacOSXVersionLT(10, 7) && objcRuntime.getKind() == ObjCRuntime::FragileMacOSX && objcRuntime.isNeXTFamily()) CmdArgs.push_back("-fobjc-subscripting-legacy-runtime"); // -fencode-extended-block-signature=1 is default. if (getToolChain().IsEncodeExtendedBlockSignatureDefault()) { CmdArgs.push_back("-fencode-extended-block-signature"); } // Allow -fno-objc-arr to trump -fobjc-arr/-fobjc-arc. // NOTE: This logic is duplicated in ToolChains.cpp. bool ARC = isObjCAutoRefCount(Args); if (ARC) { getToolChain().CheckObjCARC(); CmdArgs.push_back("-fobjc-arc"); // FIXME: It seems like this entire block, and several around it should be // wrapped in isObjC, but for now we just use it here as this is where it // was being used previously. if (types::isCXX(InputType) && types::isObjC(InputType)) { if (getToolChain().GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) CmdArgs.push_back("-fobjc-arc-cxxlib=libc++"); else CmdArgs.push_back("-fobjc-arc-cxxlib=libstdc++"); } // Allow the user to enable full exceptions code emission. // We define off for Objective-CC, on for Objective-C++. if (Args.hasFlag(options::OPT_fobjc_arc_exceptions, options::OPT_fno_objc_arc_exceptions, /*default*/ types::isCXX(InputType))) CmdArgs.push_back("-fobjc-arc-exceptions"); } // -fobjc-infer-related-result-type is the default, except in the Objective-C // rewriter. if (rewriteKind != RK_None) CmdArgs.push_back("-fno-objc-infer-related-result-type"); // Handle -fobjc-gc and -fobjc-gc-only. They are exclusive, and -fobjc-gc-only // takes precedence. const Arg *GCArg = Args.getLastArg(options::OPT_fobjc_gc_only); if (!GCArg) GCArg = Args.getLastArg(options::OPT_fobjc_gc); if (GCArg) { if (ARC) { D.Diag(diag::err_drv_objc_gc_arr) << GCArg->getAsString(Args); } else if (getToolChain().SupportsObjCGC()) { GCArg->render(Args, CmdArgs); } else { // FIXME: We should move this to a hard error. D.Diag(diag::warn_drv_objc_gc_unsupported) << GCArg->getAsString(Args); } } // Add exception args. addExceptionArgs(Args, InputType, getToolChain().getTriple(), KernelOrKext, objcRuntime, CmdArgs); if (getToolChain().UseSjLjExceptions()) CmdArgs.push_back("-fsjlj-exceptions"); // C++ "sane" operator new. if (!Args.hasFlag(options::OPT_fassume_sane_operator_new, options::OPT_fno_assume_sane_operator_new)) CmdArgs.push_back("-fno-assume-sane-operator-new"); // -fconstant-cfstrings is default, and may be subject to argument translation // on Darwin. if (!Args.hasFlag(options::OPT_fconstant_cfstrings, options::OPT_fno_constant_cfstrings) || !Args.hasFlag(options::OPT_mconstant_cfstrings, options::OPT_mno_constant_cfstrings)) CmdArgs.push_back("-fno-constant-cfstrings"); // -fshort-wchar default varies depending on platform; only // pass if specified. if (Arg *A = Args.getLastArg(options::OPT_fshort_wchar)) A->render(Args, CmdArgs); // -fno-pascal-strings is default, only pass non-default. if (Args.hasFlag(options::OPT_fpascal_strings, options::OPT_fno_pascal_strings, false)) CmdArgs.push_back("-fpascal-strings"); // Honor -fpack-struct= and -fpack-struct, if given. Note that // -fno-pack-struct doesn't apply to -fpack-struct=. if (Arg *A = Args.getLastArg(options::OPT_fpack_struct_EQ)) { std::string PackStructStr = "-fpack-struct="; PackStructStr += A->getValue(); CmdArgs.push_back(Args.MakeArgString(PackStructStr)); } else if (Args.hasFlag(options::OPT_fpack_struct, options::OPT_fno_pack_struct, false)) { CmdArgs.push_back("-fpack-struct=1"); } if (KernelOrKext || isNoCommonDefault(getToolChain().getTriple())) { if (!Args.hasArg(options::OPT_fcommon)) CmdArgs.push_back("-fno-common"); Args.ClaimAllArgs(options::OPT_fno_common); } // -fcommon is default, only pass non-default. else if (!Args.hasFlag(options::OPT_fcommon, options::OPT_fno_common)) CmdArgs.push_back("-fno-common"); // -fsigned-bitfields is default, and clang doesn't yet support // -funsigned-bitfields. if (!Args.hasFlag(options::OPT_fsigned_bitfields, options::OPT_funsigned_bitfields)) D.Diag(diag::warn_drv_clang_unsupported) << Args.getLastArg(options::OPT_funsigned_bitfields)->getAsString(Args); // -fsigned-bitfields is default, and clang doesn't support -fno-for-scope. if (!Args.hasFlag(options::OPT_ffor_scope, options::OPT_fno_for_scope)) D.Diag(diag::err_drv_clang_unsupported) << Args.getLastArg(options::OPT_fno_for_scope)->getAsString(Args); // -fcaret-diagnostics is default. if (!Args.hasFlag(options::OPT_fcaret_diagnostics, options::OPT_fno_caret_diagnostics, true)) CmdArgs.push_back("-fno-caret-diagnostics"); // -fdiagnostics-fixit-info is default, only pass non-default. if (!Args.hasFlag(options::OPT_fdiagnostics_fixit_info, options::OPT_fno_diagnostics_fixit_info)) CmdArgs.push_back("-fno-diagnostics-fixit-info"); // Enable -fdiagnostics-show-option by default. if (Args.hasFlag(options::OPT_fdiagnostics_show_option, options::OPT_fno_diagnostics_show_option)) CmdArgs.push_back("-fdiagnostics-show-option"); if (const Arg *A = Args.getLastArg(options::OPT_fdiagnostics_show_category_EQ)) { CmdArgs.push_back("-fdiagnostics-show-category"); CmdArgs.push_back(A->getValue()); } if (const Arg *A = Args.getLastArg(options::OPT_fdiagnostics_format_EQ)) { CmdArgs.push_back("-fdiagnostics-format"); CmdArgs.push_back(A->getValue()); } if (Arg *A = Args.getLastArg( options::OPT_fdiagnostics_show_note_include_stack, options::OPT_fno_diagnostics_show_note_include_stack)) { if (A->getOption().matches( options::OPT_fdiagnostics_show_note_include_stack)) CmdArgs.push_back("-fdiagnostics-show-note-include-stack"); else CmdArgs.push_back("-fno-diagnostics-show-note-include-stack"); } // Color diagnostics are the default, unless the terminal doesn't support // them. // Support both clang's -f[no-]color-diagnostics and gcc's // -f[no-]diagnostics-colors[=never|always|auto]. enum { Colors_On, Colors_Off, Colors_Auto } ShowColors = Colors_Auto; for (ArgList::const_iterator it = Args.begin(), ie = Args.end(); it != ie; ++it) { const Option &O = (*it)->getOption(); if (!O.matches(options::OPT_fcolor_diagnostics) && !O.matches(options::OPT_fdiagnostics_color) && !O.matches(options::OPT_fno_color_diagnostics) && !O.matches(options::OPT_fno_diagnostics_color) && !O.matches(options::OPT_fdiagnostics_color_EQ)) continue; (*it)->claim(); if (O.matches(options::OPT_fcolor_diagnostics) || O.matches(options::OPT_fdiagnostics_color)) { ShowColors = Colors_On; } else if (O.matches(options::OPT_fno_color_diagnostics) || O.matches(options::OPT_fno_diagnostics_color)) { ShowColors = Colors_Off; } else { assert(O.matches(options::OPT_fdiagnostics_color_EQ)); StringRef value((*it)->getValue()); if (value == "always") ShowColors = Colors_On; else if (value == "never") ShowColors = Colors_Off; else if (value == "auto") ShowColors = Colors_Auto; else getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported) << ("-fdiagnostics-color=" + value).str(); } } if (ShowColors == Colors_On || (ShowColors == Colors_Auto && llvm::sys::Process::StandardErrHasColors())) CmdArgs.push_back("-fcolor-diagnostics"); if (Args.hasArg(options::OPT_fansi_escape_codes)) CmdArgs.push_back("-fansi-escape-codes"); if (!Args.hasFlag(options::OPT_fshow_source_location, options::OPT_fno_show_source_location)) CmdArgs.push_back("-fno-show-source-location"); if (!Args.hasFlag(options::OPT_fshow_column, options::OPT_fno_show_column, true)) CmdArgs.push_back("-fno-show-column"); if (!Args.hasFlag(options::OPT_fspell_checking, options::OPT_fno_spell_checking)) CmdArgs.push_back("-fno-spell-checking"); // -fno-asm-blocks is default. if (Args.hasFlag(options::OPT_fasm_blocks, options::OPT_fno_asm_blocks, false)) CmdArgs.push_back("-fasm-blocks"); // Enable vectorization per default according to the optimization level // selected. For optimization levels that want vectorization we use the alias // option to simplify the hasFlag logic. bool EnableVec = shouldEnableVectorizerAtOLevel(Args); OptSpecifier VectorizeAliasOption = EnableVec ? options::OPT_O_Group : options::OPT_fvectorize; if (Args.hasFlag(options::OPT_fvectorize, VectorizeAliasOption, options::OPT_fno_vectorize, EnableVec)) CmdArgs.push_back("-vectorize-loops"); // -fslp-vectorize is default. if (Args.hasFlag(options::OPT_fslp_vectorize, options::OPT_fno_slp_vectorize, true)) CmdArgs.push_back("-vectorize-slp"); // -fno-slp-vectorize-aggressive is default. if (Args.hasFlag(options::OPT_fslp_vectorize_aggressive, options::OPT_fno_slp_vectorize_aggressive, false)) CmdArgs.push_back("-vectorize-slp-aggressive"); if (Arg *A = Args.getLastArg(options::OPT_fshow_overloads_EQ)) A->render(Args, CmdArgs); // -fdollars-in-identifiers default varies depending on platform and // language; only pass if specified. if (Arg *A = Args.getLastArg(options::OPT_fdollars_in_identifiers, options::OPT_fno_dollars_in_identifiers)) { if (A->getOption().matches(options::OPT_fdollars_in_identifiers)) CmdArgs.push_back("-fdollars-in-identifiers"); else CmdArgs.push_back("-fno-dollars-in-identifiers"); } // -funit-at-a-time is default, and we don't support -fno-unit-at-a-time for // practical purposes. if (Arg *A = Args.getLastArg(options::OPT_funit_at_a_time, options::OPT_fno_unit_at_a_time)) { if (A->getOption().matches(options::OPT_fno_unit_at_a_time)) D.Diag(diag::warn_drv_clang_unsupported) << A->getAsString(Args); } if (Args.hasFlag(options::OPT_fapple_pragma_pack, options::OPT_fno_apple_pragma_pack, false)) CmdArgs.push_back("-fapple-pragma-pack"); // le32-specific flags: // -fno-math-builtin: clang should not convert math builtins to intrinsics // by default. if (getToolChain().getArch() == llvm::Triple::le32) { CmdArgs.push_back("-fno-math-builtin"); } // Default to -fno-builtin-str{cat,cpy} on Darwin for ARM. // // FIXME: This is disabled until clang -cc1 supports -fno-builtin-foo. PR4941. #if 0 if (getToolChain().getTriple().isOSDarwin() && (getToolChain().getArch() == llvm::Triple::arm || getToolChain().getArch() == llvm::Triple::thumb)) { if (!Args.hasArg(options::OPT_fbuiltin_strcat)) CmdArgs.push_back("-fno-builtin-strcat"); if (!Args.hasArg(options::OPT_fbuiltin_strcpy)) CmdArgs.push_back("-fno-builtin-strcpy"); } #endif // Only allow -traditional or -traditional-cpp outside in preprocessing modes. if (Arg *A = Args.getLastArg(options::OPT_traditional, options::OPT_traditional_cpp)) { if (isa(JA)) CmdArgs.push_back("-traditional-cpp"); else D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); } Args.AddLastArg(CmdArgs, options::OPT_dM); Args.AddLastArg(CmdArgs, options::OPT_dD); // Handle serialized diagnostics. if (Arg *A = Args.getLastArg(options::OPT__serialize_diags)) { CmdArgs.push_back("-serialize-diagnostic-file"); CmdArgs.push_back(Args.MakeArgString(A->getValue())); } if (Args.hasArg(options::OPT_fretain_comments_from_system_headers)) CmdArgs.push_back("-fretain-comments-from-system-headers"); // Forward -fcomment-block-commands to -cc1. Args.AddAllArgs(CmdArgs, options::OPT_fcomment_block_commands); // Forward -fparse-all-comments to -cc1. Args.AddAllArgs(CmdArgs, options::OPT_fparse_all_comments); // Forward -Xclang arguments to -cc1, and -mllvm arguments to the LLVM option // parser. Args.AddAllArgValues(CmdArgs, options::OPT_Xclang); for (arg_iterator it = Args.filtered_begin(options::OPT_mllvm), ie = Args.filtered_end(); it != ie; ++it) { (*it)->claim(); // We translate this by hand to the -cc1 argument, since nightly test uses // it and developers have been trained to spell it with -mllvm. if (StringRef((*it)->getValue(0)) == "-disable-llvm-optzns") CmdArgs.push_back("-disable-llvm-optzns"); else (*it)->render(Args, CmdArgs); } if (Output.getType() == types::TY_Dependencies) { // Handled with other dependency code. } else if (Output.isFilename()) { CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); } else { assert(Output.isNothing() && "Invalid output."); } for (InputInfoList::const_iterator it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { const InputInfo &II = *it; CmdArgs.push_back("-x"); if (Args.hasArg(options::OPT_rewrite_objc)) CmdArgs.push_back(types::getTypeName(types::TY_PP_ObjCXX)); else CmdArgs.push_back(types::getTypeName(II.getType())); if (II.isFilename()) CmdArgs.push_back(II.getFilename()); else II.getInputArg().renderAsInput(Args, CmdArgs); } Args.AddAllArgs(CmdArgs, options::OPT_undef); const char *Exec = getToolChain().getDriver().getClangProgramPath(); // Optionally embed the -cc1 level arguments into the debug info, for build // analysis. if (getToolChain().UseDwarfDebugFlags()) { ArgStringList OriginalArgs; for (ArgList::const_iterator it = Args.begin(), ie = Args.end(); it != ie; ++it) (*it)->render(Args, OriginalArgs); SmallString<256> Flags; Flags += Exec; for (unsigned i = 0, e = OriginalArgs.size(); i != e; ++i) { Flags += " "; Flags += OriginalArgs[i]; } CmdArgs.push_back("-dwarf-debug-flags"); CmdArgs.push_back(Args.MakeArgString(Flags.str())); } // Add the split debug info name to the command lines here so we // can propagate it to the backend. bool SplitDwarf = Args.hasArg(options::OPT_gsplit_dwarf) && getToolChain().getTriple().isOSLinux() && (isa(JA) || isa(JA)); const char *SplitDwarfOut; if (SplitDwarf) { CmdArgs.push_back("-split-dwarf-file"); SplitDwarfOut = SplitDebugName(Args, Inputs); CmdArgs.push_back(SplitDwarfOut); } // Finally add the compile command to the compilation. if (Args.hasArg(options::OPT__SLASH_fallback)) { tools::visualstudio::Compile CL(getToolChain()); Command *CLCommand = CL.GetCommand(C, JA, Output, Inputs, Args, LinkingOutput); C.addCommand(new FallbackCommand(JA, *this, Exec, CmdArgs, CLCommand)); } else { C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } // Handle the debug info splitting at object creation time if we're // creating an object. // TODO: Currently only works on linux with newer objcopy. if (SplitDwarf && !isa(JA)) SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, SplitDwarfOut); if (Arg *A = Args.getLastArg(options::OPT_pg)) if (Args.hasArg(options::OPT_fomit_frame_pointer)) D.Diag(diag::err_drv_argument_not_allowed_with) << "-fomit-frame-pointer" << A->getAsString(Args); // Claim some arguments which clang supports automatically. // -fpch-preprocess is used with gcc to add a special marker in the output to // include the PCH file. Clang's PTH solution is completely transparent, so we // do not need to deal with it at all. Args.ClaimAllArgs(options::OPT_fpch_preprocess); // Claim some arguments which clang doesn't support, but we don't // care to warn the user about. Args.ClaimAllArgs(options::OPT_clang_ignored_f_Group); Args.ClaimAllArgs(options::OPT_clang_ignored_m_Group); // Disable warnings for clang -E -emit-llvm foo.c Args.ClaimAllArgs(options::OPT_emit_llvm); } /// Add options related to the Objective-C runtime/ABI. /// /// Returns true if the runtime is non-fragile. ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args, ArgStringList &cmdArgs, RewriteKind rewriteKind) const { // Look for the controlling runtime option. Arg *runtimeArg = args.getLastArg(options::OPT_fnext_runtime, options::OPT_fgnu_runtime, options::OPT_fobjc_runtime_EQ); // Just forward -fobjc-runtime= to the frontend. This supercedes // options about fragility. if (runtimeArg && runtimeArg->getOption().matches(options::OPT_fobjc_runtime_EQ)) { ObjCRuntime runtime; StringRef value = runtimeArg->getValue(); if (runtime.tryParse(value)) { getToolChain().getDriver().Diag(diag::err_drv_unknown_objc_runtime) << value; } runtimeArg->render(args, cmdArgs); return runtime; } // Otherwise, we'll need the ABI "version". Version numbers are // slightly confusing for historical reasons: // 1 - Traditional "fragile" ABI // 2 - Non-fragile ABI, version 1 // 3 - Non-fragile ABI, version 2 unsigned objcABIVersion = 1; // If -fobjc-abi-version= is present, use that to set the version. if (Arg *abiArg = args.getLastArg(options::OPT_fobjc_abi_version_EQ)) { StringRef value = abiArg->getValue(); if (value == "1") objcABIVersion = 1; else if (value == "2") objcABIVersion = 2; else if (value == "3") objcABIVersion = 3; else getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported) << value; } else { // Otherwise, determine if we are using the non-fragile ABI. bool nonFragileABIIsDefault = (rewriteKind == RK_NonFragile || (rewriteKind == RK_None && getToolChain().IsObjCNonFragileABIDefault())); if (args.hasFlag(options::OPT_fobjc_nonfragile_abi, options::OPT_fno_objc_nonfragile_abi, nonFragileABIIsDefault)) { // Determine the non-fragile ABI version to use. #ifdef DISABLE_DEFAULT_NONFRAGILEABI_TWO unsigned nonFragileABIVersion = 1; #else unsigned nonFragileABIVersion = 2; #endif if (Arg *abiArg = args.getLastArg( options::OPT_fobjc_nonfragile_abi_version_EQ)) { StringRef value = abiArg->getValue(); if (value == "1") nonFragileABIVersion = 1; else if (value == "2") nonFragileABIVersion = 2; else getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported) << value; } objcABIVersion = 1 + nonFragileABIVersion; } else { objcABIVersion = 1; } } // We don't actually care about the ABI version other than whether // it's non-fragile. bool isNonFragile = objcABIVersion != 1; // If we have no runtime argument, ask the toolchain for its default runtime. // However, the rewriter only really supports the Mac runtime, so assume that. ObjCRuntime runtime; if (!runtimeArg) { switch (rewriteKind) { case RK_None: runtime = getToolChain().getDefaultObjCRuntime(isNonFragile); break; case RK_Fragile: runtime = ObjCRuntime(ObjCRuntime::FragileMacOSX, VersionTuple()); break; case RK_NonFragile: runtime = ObjCRuntime(ObjCRuntime::MacOSX, VersionTuple()); break; } // -fnext-runtime } else if (runtimeArg->getOption().matches(options::OPT_fnext_runtime)) { // On Darwin, make this use the default behavior for the toolchain. if (getToolChain().getTriple().isOSDarwin()) { runtime = getToolChain().getDefaultObjCRuntime(isNonFragile); // Otherwise, build for a generic macosx port. } else { runtime = ObjCRuntime(ObjCRuntime::MacOSX, VersionTuple()); } // -fgnu-runtime } else { assert(runtimeArg->getOption().matches(options::OPT_fgnu_runtime)); // Legacy behaviour is to target the gnustep runtime if we are i // non-fragile mode or the GCC runtime in fragile mode. if (isNonFragile) runtime = ObjCRuntime(ObjCRuntime::GNUstep, VersionTuple(1,6)); else runtime = ObjCRuntime(ObjCRuntime::GCC, VersionTuple()); } cmdArgs.push_back(args.MakeArgString( "-fobjc-runtime=" + runtime.getAsString())); return runtime; } void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const { unsigned RTOptionID = options::OPT__SLASH_MT; if (Args.hasArg(options::OPT__SLASH_LDd)) // The /LDd option implies /MTd. The dependent lib part can be overridden, // but defining _DEBUG is sticky. RTOptionID = options::OPT__SLASH_MTd; if (Arg *A = Args.getLastArg(options::OPT__SLASH_M_Group)) RTOptionID = A->getOption().getID(); switch(RTOptionID) { case options::OPT__SLASH_MD: if (Args.hasArg(options::OPT__SLASH_LDd)) CmdArgs.push_back("-D_DEBUG"); CmdArgs.push_back("-D_MT"); CmdArgs.push_back("-D_DLL"); CmdArgs.push_back("--dependent-lib=msvcrt"); break; case options::OPT__SLASH_MDd: CmdArgs.push_back("-D_DEBUG"); CmdArgs.push_back("-D_MT"); CmdArgs.push_back("-D_DLL"); CmdArgs.push_back("--dependent-lib=msvcrtd"); break; case options::OPT__SLASH_MT: if (Args.hasArg(options::OPT__SLASH_LDd)) CmdArgs.push_back("-D_DEBUG"); CmdArgs.push_back("-D_MT"); CmdArgs.push_back("--dependent-lib=libcmt"); break; case options::OPT__SLASH_MTd: CmdArgs.push_back("-D_DEBUG"); CmdArgs.push_back("-D_MT"); CmdArgs.push_back("--dependent-lib=libcmtd"); break; default: llvm_unreachable("Unexpected option ID."); } // This provides POSIX compatibility (maps 'open' to '_open'), which most // users want. The /Za flag to cl.exe turns this off, but it's not // implemented in clang. CmdArgs.push_back("--dependent-lib=oldnames"); // FIXME: Make this default for the win32 triple. CmdArgs.push_back("-cxx-abi"); CmdArgs.push_back("microsoft"); if (Arg *A = Args.getLastArg(options::OPT_show_includes)) A->render(Args, CmdArgs); if (!Args.hasArg(options::OPT_fdiagnostics_format_EQ)) { CmdArgs.push_back("-fdiagnostics-format"); if (Args.hasArg(options::OPT__SLASH_fallback)) CmdArgs.push_back("msvc-fallback"); else CmdArgs.push_back("msvc"); } } void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { ArgStringList CmdArgs; assert(Inputs.size() == 1 && "Unexpected number of inputs."); const InputInfo &Input = Inputs[0]; // Don't warn about "clang -w -c foo.s" Args.ClaimAllArgs(options::OPT_w); // and "clang -emit-llvm -c foo.s" Args.ClaimAllArgs(options::OPT_emit_llvm); // Invoke ourselves in -cc1as mode. // // FIXME: Implement custom jobs for internal actions. CmdArgs.push_back("-cc1as"); // Add the "effective" target triple. CmdArgs.push_back("-triple"); std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args, Input.getType()); CmdArgs.push_back(Args.MakeArgString(TripleStr)); // Set the output mode, we currently only expect to be used as a real // assembler. CmdArgs.push_back("-filetype"); CmdArgs.push_back("obj"); // Set the main file name, so that debug info works even with // -save-temps or preprocessed assembly. CmdArgs.push_back("-main-file-name"); CmdArgs.push_back(Clang::getBaseInputName(Args, Inputs)); // Add the target cpu const llvm::Triple &Triple = getToolChain().getTriple(); std::string CPU = getCPUName(Args, Triple); if (!CPU.empty()) { CmdArgs.push_back("-target-cpu"); CmdArgs.push_back(Args.MakeArgString(CPU)); } // Add the target features const Driver &D = getToolChain().getDriver(); getTargetFeatures(D, Triple, Args, CmdArgs); // Ignore explicit -force_cpusubtype_ALL option. (void) Args.hasArg(options::OPT_force__cpusubtype__ALL); // Determine the original source input. const Action *SourceAction = &JA; while (SourceAction->getKind() != Action::InputClass) { assert(!SourceAction->getInputs().empty() && "unexpected root action!"); SourceAction = SourceAction->getInputs()[0]; } // Forward -g and handle debug info related flags, assuming we are dealing // with an actual assembly file. if (SourceAction->getType() == types::TY_Asm || SourceAction->getType() == types::TY_PP_Asm) { Args.ClaimAllArgs(options::OPT_g_Group); if (Arg *A = Args.getLastArg(options::OPT_g_Group)) if (!A->getOption().matches(options::OPT_g0)) CmdArgs.push_back("-g"); // Add the -fdebug-compilation-dir flag if needed. addDebugCompDirArg(Args, CmdArgs); // Set the AT_producer to the clang version when using the integrated // assembler on assembly source files. CmdArgs.push_back("-dwarf-debug-producer"); CmdArgs.push_back(Args.MakeArgString(getClangFullVersion())); } // Optionally embed the -cc1as level arguments into the debug info, for build // analysis. if (getToolChain().UseDwarfDebugFlags()) { ArgStringList OriginalArgs; for (ArgList::const_iterator it = Args.begin(), ie = Args.end(); it != ie; ++it) (*it)->render(Args, OriginalArgs); SmallString<256> Flags; const char *Exec = getToolChain().getDriver().getClangProgramPath(); Flags += Exec; for (unsigned i = 0, e = OriginalArgs.size(); i != e; ++i) { Flags += " "; Flags += OriginalArgs[i]; } CmdArgs.push_back("-dwarf-debug-flags"); CmdArgs.push_back(Args.MakeArgString(Flags.str())); } // FIXME: Add -static support, once we have it. CollectArgsForIntegratedAssembler(C, Args, CmdArgs, getToolChain().getDriver()); Args.AddAllArgs(CmdArgs, options::OPT_mllvm); assert(Output.isFilename() && "Unexpected lipo output."); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); assert(Input.isFilename() && "Invalid input."); CmdArgs.push_back(Input.getFilename()); const char *Exec = getToolChain().getDriver().getClangProgramPath(); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); // Handle the debug info splitting at object creation time if we're // creating an object. // TODO: Currently only works on linux with newer objcopy. if (Args.hasArg(options::OPT_gsplit_dwarf) && getToolChain().getTriple().isOSLinux()) SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, SplitDebugName(Args, Inputs)); } void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { const Driver &D = getToolChain().getDriver(); ArgStringList CmdArgs; for (ArgList::const_iterator it = Args.begin(), ie = Args.end(); it != ie; ++it) { Arg *A = *it; if (forwardToGCC(A->getOption())) { // Don't forward any -g arguments to assembly steps. if (isa(JA) && A->getOption().matches(options::OPT_g_Group)) continue; // Don't forward any -W arguments to assembly and link steps. if ((isa(JA) || isa(JA)) && A->getOption().matches(options::OPT_W_Group)) continue; // It is unfortunate that we have to claim here, as this means // we will basically never report anything interesting for // platforms using a generic gcc, even if we are just using gcc // to get to the assembler. A->claim(); A->render(Args, CmdArgs); } } RenderExtraToolArgs(JA, CmdArgs); // If using a driver driver, force the arch. llvm::Triple::ArchType Arch = getToolChain().getArch(); if (getToolChain().getTriple().isOSDarwin()) { CmdArgs.push_back("-arch"); // FIXME: Remove these special cases. if (Arch == llvm::Triple::ppc) CmdArgs.push_back("ppc"); else if (Arch == llvm::Triple::ppc64) CmdArgs.push_back("ppc64"); else if (Arch == llvm::Triple::ppc64le) CmdArgs.push_back("ppc64le"); else CmdArgs.push_back(Args.MakeArgString(getToolChain().getArchName())); } // Try to force gcc to match the tool chain we want, if we recognize // the arch. // // FIXME: The triple class should directly provide the information we want // here. if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::ppc) CmdArgs.push_back("-m32"); else if (Arch == llvm::Triple::x86_64 || Arch == llvm::Triple::ppc64 || Arch == llvm::Triple::ppc64le) CmdArgs.push_back("-m64"); if (Output.isFilename()) { CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); } else { assert(Output.isNothing() && "Unexpected output"); CmdArgs.push_back("-fsyntax-only"); } Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); // Only pass -x if gcc will understand it; otherwise hope gcc // understands the suffix correctly. The main use case this would go // wrong in is for linker inputs if they happened to have an odd // suffix; really the only way to get this to happen is a command // like '-x foobar a.c' which will treat a.c like a linker input. // // FIXME: For the linker case specifically, can we safely convert // inputs into '-Wl,' options? for (InputInfoList::const_iterator it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { const InputInfo &II = *it; // Don't try to pass LLVM or AST inputs to a generic gcc. if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR || II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC) D.Diag(diag::err_drv_no_linker_llvm_support) << getToolChain().getTripleString(); else if (II.getType() == types::TY_AST) D.Diag(diag::err_drv_no_ast_support) << getToolChain().getTripleString(); else if (II.getType() == types::TY_ModuleFile) D.Diag(diag::err_drv_no_module_support) << getToolChain().getTripleString(); if (types::canTypeBeUserSpecified(II.getType())) { CmdArgs.push_back("-x"); CmdArgs.push_back(types::getTypeName(II.getType())); } if (II.isFilename()) CmdArgs.push_back(II.getFilename()); else { const Arg &A = II.getInputArg(); // Reverse translate some rewritten options. if (A.getOption().matches(options::OPT_Z_reserved_lib_stdcxx)) { CmdArgs.push_back("-lstdc++"); continue; } // Don't render as input, we need gcc to do the translations. A.render(Args, CmdArgs); } } const std::string customGCCName = D.getCCCGenericGCCName(); const char *GCCName; if (!customGCCName.empty()) GCCName = customGCCName.c_str(); else if (D.CCCIsCXX()) { GCCName = "g++"; } else GCCName = "gcc"; const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(GCCName)); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } void gcc::Preprocess::RenderExtraToolArgs(const JobAction &JA, ArgStringList &CmdArgs) const { CmdArgs.push_back("-E"); } void gcc::Precompile::RenderExtraToolArgs(const JobAction &JA, ArgStringList &CmdArgs) const { // The type is good enough. } void gcc::Compile::RenderExtraToolArgs(const JobAction &JA, ArgStringList &CmdArgs) const { const Driver &D = getToolChain().getDriver(); // If -flto, etc. are present then make sure not to force assembly output. if (JA.getType() == types::TY_LLVM_IR || JA.getType() == types::TY_LTO_IR || JA.getType() == types::TY_LLVM_BC || JA.getType() == types::TY_LTO_BC) CmdArgs.push_back("-c"); else { if (JA.getType() != types::TY_PP_Asm) D.Diag(diag::err_drv_invalid_gcc_output_type) << getTypeName(JA.getType()); CmdArgs.push_back("-S"); } } void gcc::Assemble::RenderExtraToolArgs(const JobAction &JA, ArgStringList &CmdArgs) const { CmdArgs.push_back("-c"); } void gcc::Link::RenderExtraToolArgs(const JobAction &JA, ArgStringList &CmdArgs) const { // The types are (hopefully) good enough. } // Hexagon tools start. void hexagon::Assemble::RenderExtraToolArgs(const JobAction &JA, ArgStringList &CmdArgs) const { } void hexagon::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { const Driver &D = getToolChain().getDriver(); ArgStringList CmdArgs; std::string MarchString = "-march="; MarchString += toolchains::Hexagon_TC::GetTargetCPU(Args); CmdArgs.push_back(Args.MakeArgString(MarchString)); RenderExtraToolArgs(JA, CmdArgs); if (Output.isFilename()) { CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); } else { assert(Output.isNothing() && "Unexpected output"); CmdArgs.push_back("-fsyntax-only"); } std::string SmallDataThreshold = GetHexagonSmallDataThresholdValue(Args); if (!SmallDataThreshold.empty()) CmdArgs.push_back( Args.MakeArgString(std::string("-G") + SmallDataThreshold)); Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); // Only pass -x if gcc will understand it; otherwise hope gcc // understands the suffix correctly. The main use case this would go // wrong in is for linker inputs if they happened to have an odd // suffix; really the only way to get this to happen is a command // like '-x foobar a.c' which will treat a.c like a linker input. // // FIXME: For the linker case specifically, can we safely convert // inputs into '-Wl,' options? for (InputInfoList::const_iterator it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { const InputInfo &II = *it; // Don't try to pass LLVM or AST inputs to a generic gcc. if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR || II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC) D.Diag(clang::diag::err_drv_no_linker_llvm_support) << getToolChain().getTripleString(); else if (II.getType() == types::TY_AST) D.Diag(clang::diag::err_drv_no_ast_support) << getToolChain().getTripleString(); else if (II.getType() == types::TY_ModuleFile) D.Diag(diag::err_drv_no_module_support) << getToolChain().getTripleString(); if (II.isFilename()) CmdArgs.push_back(II.getFilename()); else // Don't render as input, we need gcc to do the translations. FIXME: Pranav: What is this ? II.getInputArg().render(Args, CmdArgs); } const char *GCCName = "hexagon-as"; const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(GCCName)); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } void hexagon::Link::RenderExtraToolArgs(const JobAction &JA, ArgStringList &CmdArgs) const { // The types are (hopefully) good enough. } void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { const toolchains::Hexagon_TC& ToolChain = static_cast(getToolChain()); const Driver &D = ToolChain.getDriver(); ArgStringList CmdArgs; //---------------------------------------------------------------------------- // //---------------------------------------------------------------------------- bool hasStaticArg = Args.hasArg(options::OPT_static); bool buildingLib = Args.hasArg(options::OPT_shared); bool buildPIE = Args.hasArg(options::OPT_pie); bool incStdLib = !Args.hasArg(options::OPT_nostdlib); bool incStartFiles = !Args.hasArg(options::OPT_nostartfiles); bool incDefLibs = !Args.hasArg(options::OPT_nodefaultlibs); bool useShared = buildingLib && !hasStaticArg; //---------------------------------------------------------------------------- // Silence warnings for various options //---------------------------------------------------------------------------- Args.ClaimAllArgs(options::OPT_g_Group); Args.ClaimAllArgs(options::OPT_emit_llvm); Args.ClaimAllArgs(options::OPT_w); // Other warning options are already // handled somewhere else. Args.ClaimAllArgs(options::OPT_static_libgcc); //---------------------------------------------------------------------------- // //---------------------------------------------------------------------------- for (std::vector::const_iterator i = ToolChain.ExtraOpts.begin(), e = ToolChain.ExtraOpts.end(); i != e; ++i) CmdArgs.push_back(i->c_str()); std::string MarchString = toolchains::Hexagon_TC::GetTargetCPU(Args); CmdArgs.push_back(Args.MakeArgString("-m" + MarchString)); if (buildingLib) { CmdArgs.push_back("-shared"); CmdArgs.push_back("-call_shared"); // should be the default, but doing as // hexagon-gcc does } if (hasStaticArg) CmdArgs.push_back("-static"); if (buildPIE && !buildingLib) CmdArgs.push_back("-pie"); std::string SmallDataThreshold = GetHexagonSmallDataThresholdValue(Args); if (!SmallDataThreshold.empty()) { CmdArgs.push_back( Args.MakeArgString(std::string("-G") + SmallDataThreshold)); } //---------------------------------------------------------------------------- // //---------------------------------------------------------------------------- CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); const std::string MarchSuffix = "/" + MarchString; const std::string G0Suffix = "/G0"; const std::string MarchG0Suffix = MarchSuffix + G0Suffix; const std::string RootDir = toolchains::Hexagon_TC::GetGnuDir(D.InstalledDir) + "/"; const std::string StartFilesDir = RootDir + "hexagon/lib" + (buildingLib ? MarchG0Suffix : MarchSuffix); //---------------------------------------------------------------------------- // moslib //---------------------------------------------------------------------------- std::vector oslibs; bool hasStandalone= false; for (arg_iterator it = Args.filtered_begin(options::OPT_moslib_EQ), ie = Args.filtered_end(); it != ie; ++it) { (*it)->claim(); oslibs.push_back((*it)->getValue()); hasStandalone = hasStandalone || (oslibs.back() == "standalone"); } if (oslibs.empty()) { oslibs.push_back("standalone"); hasStandalone = true; } //---------------------------------------------------------------------------- // Start Files //---------------------------------------------------------------------------- if (incStdLib && incStartFiles) { if (!buildingLib) { if (hasStandalone) { CmdArgs.push_back( Args.MakeArgString(StartFilesDir + "/crt0_standalone.o")); } CmdArgs.push_back(Args.MakeArgString(StartFilesDir + "/crt0.o")); } std::string initObj = useShared ? "/initS.o" : "/init.o"; CmdArgs.push_back(Args.MakeArgString(StartFilesDir + initObj)); } //---------------------------------------------------------------------------- // Library Search Paths //---------------------------------------------------------------------------- const ToolChain::path_list &LibPaths = ToolChain.getFilePaths(); for (ToolChain::path_list::const_iterator i = LibPaths.begin(), e = LibPaths.end(); i != e; ++i) CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + *i)); //---------------------------------------------------------------------------- // //---------------------------------------------------------------------------- Args.AddAllArgs(CmdArgs, options::OPT_T_Group); Args.AddAllArgs(CmdArgs, options::OPT_e); Args.AddAllArgs(CmdArgs, options::OPT_s); Args.AddAllArgs(CmdArgs, options::OPT_t); Args.AddAllArgs(CmdArgs, options::OPT_u_Group); AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs); //---------------------------------------------------------------------------- // Libraries //---------------------------------------------------------------------------- if (incStdLib && incDefLibs) { if (D.CCCIsCXX()) { ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); CmdArgs.push_back("-lm"); } CmdArgs.push_back("--start-group"); if (!buildingLib) { for(std::vector::iterator i = oslibs.begin(), e = oslibs.end(); i != e; ++i) CmdArgs.push_back(Args.MakeArgString("-l" + *i)); CmdArgs.push_back("-lc"); } CmdArgs.push_back("-lgcc"); CmdArgs.push_back("--end-group"); } //---------------------------------------------------------------------------- // End files //---------------------------------------------------------------------------- if (incStdLib && incStartFiles) { std::string finiObj = useShared ? "/finiS.o" : "/fini.o"; CmdArgs.push_back(Args.MakeArgString(StartFilesDir + finiObj)); } std::string Linker = ToolChain.GetProgramPath("hexagon-ld"); C.addCommand(new Command(JA, *this, Args.MakeArgString(Linker), CmdArgs)); } // Hexagon tools end. llvm::Triple::ArchType darwin::getArchTypeForDarwinArchName(StringRef Str) { // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for // archs which Darwin doesn't use. // The matching this routine does is fairly pointless, since it is neither the // complete architecture list, nor a reasonable subset. The problem is that // historically the driver driver accepts this and also ties its -march= // handling to the architecture name, so we need to be careful before removing // support for it. // This code must be kept in sync with Clang's Darwin specific argument // translation. return llvm::StringSwitch(Str) .Cases("ppc", "ppc601", "ppc603", "ppc604", "ppc604e", llvm::Triple::ppc) .Cases("ppc750", "ppc7400", "ppc7450", "ppc970", llvm::Triple::ppc) .Case("ppc64", llvm::Triple::ppc64) .Cases("i386", "i486", "i486SX", "i586", "i686", llvm::Triple::x86) .Cases("pentium", "pentpro", "pentIIm3", "pentIIm5", "pentium4", llvm::Triple::x86) .Cases("x86_64", "x86_64h", llvm::Triple::x86_64) // This is derived from the driver driver. .Cases("arm", "armv4t", "armv5", "armv6", "armv6m", llvm::Triple::arm) .Cases("armv7", "armv7em", "armv7f", "armv7k", "armv7m", llvm::Triple::arm) .Cases("armv7s", "xscale", llvm::Triple::arm) .Case("r600", llvm::Triple::r600) .Case("nvptx", llvm::Triple::nvptx) .Case("nvptx64", llvm::Triple::nvptx64) .Case("amdil", llvm::Triple::amdil) .Case("spir", llvm::Triple::spir) .Default(llvm::Triple::UnknownArch); } const char *Clang::getBaseInputName(const ArgList &Args, const InputInfoList &Inputs) { return Args.MakeArgString( llvm::sys::path::filename(Inputs[0].getBaseInput())); } const char *Clang::getBaseInputStem(const ArgList &Args, const InputInfoList &Inputs) { const char *Str = getBaseInputName(Args, Inputs); if (const char *End = strrchr(Str, '.')) return Args.MakeArgString(std::string(Str, End)); return Str; } const char *Clang::getDependencyFileName(const ArgList &Args, const InputInfoList &Inputs) { // FIXME: Think about this more. std::string Res; if (Arg *OutputOpt = Args.getLastArg(options::OPT_o)) { std::string Str(OutputOpt->getValue()); Res = Str.substr(0, Str.rfind('.')); } else { Res = getBaseInputStem(Args, Inputs); } return Args.MakeArgString(Res + ".d"); } void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { ArgStringList CmdArgs; assert(Inputs.size() == 1 && "Unexpected number of inputs."); const InputInfo &Input = Inputs[0]; // Determine the original source input. const Action *SourceAction = &JA; while (SourceAction->getKind() != Action::InputClass) { assert(!SourceAction->getInputs().empty() && "unexpected root action!"); SourceAction = SourceAction->getInputs()[0]; } // If -no_integrated_as is used add -Q to the darwin assember driver to make // sure it runs its system assembler not clang's integrated assembler. // Applicable to darwin11+ and Xcode 4+. darwin<10 lacked integrated-as. // FIXME: at run-time detect assembler capabilities or rely on version // information forwarded by -target-assembler-version (future) if (Args.hasArg(options::OPT_no_integrated_as)) { const llvm::Triple& t(getToolChain().getTriple()); if (!(t.isMacOSX() && t.isMacOSXVersionLT(10, 7))) CmdArgs.push_back("-Q"); } // Forward -g, assuming we are dealing with an actual assembly file. if (SourceAction->getType() == types::TY_Asm || SourceAction->getType() == types::TY_PP_Asm) { if (Args.hasArg(options::OPT_gstabs)) CmdArgs.push_back("--gstabs"); else if (Args.hasArg(options::OPT_g_Group)) CmdArgs.push_back("-g"); } // Derived from asm spec. AddDarwinArch(Args, CmdArgs); // Use -force_cpusubtype_ALL on x86 by default. if (getToolChain().getArch() == llvm::Triple::x86 || getToolChain().getArch() == llvm::Triple::x86_64 || Args.hasArg(options::OPT_force__cpusubtype__ALL)) CmdArgs.push_back("-force_cpusubtype_ALL"); if (getToolChain().getArch() != llvm::Triple::x86_64 && (((Args.hasArg(options::OPT_mkernel) || Args.hasArg(options::OPT_fapple_kext)) && (!getDarwinToolChain().isTargetIPhoneOS() || getDarwinToolChain().isIPhoneOSVersionLT(6, 0))) || Args.hasArg(options::OPT_static))) CmdArgs.push_back("-static"); Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); assert(Output.isFilename() && "Unexpected lipo output."); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); assert(Input.isFilename() && "Invalid input."); CmdArgs.push_back(Input.getFilename()); // asm_final spec is empty. const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } void darwin::DarwinTool::anchor() {} void darwin::DarwinTool::AddDarwinArch(const ArgList &Args, ArgStringList &CmdArgs) const { StringRef ArchName = getDarwinToolChain().getDarwinArchName(Args); // Derived from darwin_arch spec. CmdArgs.push_back("-arch"); CmdArgs.push_back(Args.MakeArgString(ArchName)); // FIXME: Is this needed anymore? if (ArchName == "arm") CmdArgs.push_back("-force_cpusubtype_ALL"); } bool darwin::Link::NeedsTempPath(const InputInfoList &Inputs) const { // We only need to generate a temp path for LTO if we aren't compiling object // files. When compiling source files, we run 'dsymutil' after linking. We // don't run 'dsymutil' when compiling object files. for (InputInfoList::const_iterator it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) if (it->getType() != types::TY_Object) return true; return false; } void darwin::Link::AddLinkArgs(Compilation &C, const ArgList &Args, ArgStringList &CmdArgs, const InputInfoList &Inputs) const { const Driver &D = getToolChain().getDriver(); const toolchains::Darwin &DarwinTC = getDarwinToolChain(); unsigned Version[3] = { 0, 0, 0 }; if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) { bool HadExtra; if (!Driver::GetReleaseVersion(A->getValue(), Version[0], Version[1], Version[2], HadExtra) || HadExtra) D.Diag(diag::err_drv_invalid_version_number) << A->getAsString(Args); } // Newer linkers support -demangle, pass it if supported and not disabled by // the user. if (Version[0] >= 100 && !Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) { // Don't pass -demangle to ld_classic. // // FIXME: This is a temporary workaround, ld should be handling this. bool UsesLdClassic = (getToolChain().getArch() == llvm::Triple::x86 && Args.hasArg(options::OPT_static)); if (getToolChain().getArch() == llvm::Triple::x86) { for (arg_iterator it = Args.filtered_begin(options::OPT_Xlinker, options::OPT_Wl_COMMA), ie = Args.filtered_end(); it != ie; ++it) { const Arg *A = *it; for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) if (StringRef(A->getValue(i)) == "-kext") UsesLdClassic = true; } } if (!UsesLdClassic) CmdArgs.push_back("-demangle"); } if (Args.hasArg(options::OPT_rdynamic) && Version[0] >= 137) CmdArgs.push_back("-export_dynamic"); // If we are using LTO, then automatically create a temporary file path for // the linker to use, so that it's lifetime will extend past a possible // dsymutil step. if (Version[0] >= 116 && D.IsUsingLTO(Args) && NeedsTempPath(Inputs)) { const char *TmpPath = C.getArgs().MakeArgString( D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object))); C.addTempFile(TmpPath); CmdArgs.push_back("-object_path_lto"); CmdArgs.push_back(TmpPath); } // Derived from the "link" spec. Args.AddAllArgs(CmdArgs, options::OPT_static); if (!Args.hasArg(options::OPT_static)) CmdArgs.push_back("-dynamic"); if (Args.hasArg(options::OPT_fgnu_runtime)) { // FIXME: gcc replaces -lobjc in forward args with -lobjc-gnu // here. How do we wish to handle such things? } if (!Args.hasArg(options::OPT_dynamiclib)) { AddDarwinArch(Args, CmdArgs); // FIXME: Why do this only on this path? Args.AddLastArg(CmdArgs, options::OPT_force__cpusubtype__ALL); Args.AddLastArg(CmdArgs, options::OPT_bundle); Args.AddAllArgs(CmdArgs, options::OPT_bundle__loader); Args.AddAllArgs(CmdArgs, options::OPT_client__name); Arg *A; if ((A = Args.getLastArg(options::OPT_compatibility__version)) || (A = Args.getLastArg(options::OPT_current__version)) || (A = Args.getLastArg(options::OPT_install__name))) D.Diag(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args) << "-dynamiclib"; Args.AddLastArg(CmdArgs, options::OPT_force__flat__namespace); Args.AddLastArg(CmdArgs, options::OPT_keep__private__externs); Args.AddLastArg(CmdArgs, options::OPT_private__bundle); } else { CmdArgs.push_back("-dylib"); Arg *A; if ((A = Args.getLastArg(options::OPT_bundle)) || (A = Args.getLastArg(options::OPT_bundle__loader)) || (A = Args.getLastArg(options::OPT_client__name)) || (A = Args.getLastArg(options::OPT_force__flat__namespace)) || (A = Args.getLastArg(options::OPT_keep__private__externs)) || (A = Args.getLastArg(options::OPT_private__bundle))) D.Diag(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args) << "-dynamiclib"; Args.AddAllArgsTranslated(CmdArgs, options::OPT_compatibility__version, "-dylib_compatibility_version"); Args.AddAllArgsTranslated(CmdArgs, options::OPT_current__version, "-dylib_current_version"); AddDarwinArch(Args, CmdArgs); Args.AddAllArgsTranslated(CmdArgs, options::OPT_install__name, "-dylib_install_name"); } Args.AddLastArg(CmdArgs, options::OPT_all__load); Args.AddAllArgs(CmdArgs, options::OPT_allowable__client); Args.AddLastArg(CmdArgs, options::OPT_bind__at__load); if (DarwinTC.isTargetIPhoneOS()) Args.AddLastArg(CmdArgs, options::OPT_arch__errors__fatal); Args.AddLastArg(CmdArgs, options::OPT_dead__strip); Args.AddLastArg(CmdArgs, options::OPT_no__dead__strip__inits__and__terms); Args.AddAllArgs(CmdArgs, options::OPT_dylib__file); Args.AddLastArg(CmdArgs, options::OPT_dynamic); Args.AddAllArgs(CmdArgs, options::OPT_exported__symbols__list); Args.AddLastArg(CmdArgs, options::OPT_flat__namespace); Args.AddAllArgs(CmdArgs, options::OPT_force__load); Args.AddAllArgs(CmdArgs, options::OPT_headerpad__max__install__names); Args.AddAllArgs(CmdArgs, options::OPT_image__base); Args.AddAllArgs(CmdArgs, options::OPT_init); // Add the deployment target. VersionTuple TargetVersion = DarwinTC.getTargetVersion(); // If we had an explicit -mios-simulator-version-min argument, honor that, // otherwise use the traditional deployment targets. We can't just check the // is-sim attribute because existing code follows this path, and the linker // may not handle the argument. // // FIXME: We may be able to remove this, once we can verify no one depends on // it. if (Args.hasArg(options::OPT_mios_simulator_version_min_EQ)) CmdArgs.push_back("-ios_simulator_version_min"); else if (DarwinTC.isTargetIPhoneOS()) CmdArgs.push_back("-iphoneos_version_min"); else CmdArgs.push_back("-macosx_version_min"); CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString())); Args.AddLastArg(CmdArgs, options::OPT_nomultidefs); Args.AddLastArg(CmdArgs, options::OPT_multi__module); Args.AddLastArg(CmdArgs, options::OPT_single__module); Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined); Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined__unused); if (const Arg *A = Args.getLastArg(options::OPT_fpie, options::OPT_fPIE, options::OPT_fno_pie, options::OPT_fno_PIE)) { if (A->getOption().matches(options::OPT_fpie) || A->getOption().matches(options::OPT_fPIE)) CmdArgs.push_back("-pie"); else CmdArgs.push_back("-no_pie"); } Args.AddLastArg(CmdArgs, options::OPT_prebind); Args.AddLastArg(CmdArgs, options::OPT_noprebind); Args.AddLastArg(CmdArgs, options::OPT_nofixprebinding); Args.AddLastArg(CmdArgs, options::OPT_prebind__all__twolevel__modules); Args.AddLastArg(CmdArgs, options::OPT_read__only__relocs); Args.AddAllArgs(CmdArgs, options::OPT_sectcreate); Args.AddAllArgs(CmdArgs, options::OPT_sectorder); Args.AddAllArgs(CmdArgs, options::OPT_seg1addr); Args.AddAllArgs(CmdArgs, options::OPT_segprot); Args.AddAllArgs(CmdArgs, options::OPT_segaddr); Args.AddAllArgs(CmdArgs, options::OPT_segs__read__only__addr); Args.AddAllArgs(CmdArgs, options::OPT_segs__read__write__addr); Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table); Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table__filename); Args.AddAllArgs(CmdArgs, options::OPT_sub__library); Args.AddAllArgs(CmdArgs, options::OPT_sub__umbrella); // Give --sysroot= preference, over the Apple specific behavior to also use // --isysroot as the syslibroot. StringRef sysroot = C.getSysRoot(); if (sysroot != "") { CmdArgs.push_back("-syslibroot"); CmdArgs.push_back(C.getArgs().MakeArgString(sysroot)); } else if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) { CmdArgs.push_back("-syslibroot"); CmdArgs.push_back(A->getValue()); } Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace); Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace__hints); Args.AddAllArgs(CmdArgs, options::OPT_umbrella); Args.AddAllArgs(CmdArgs, options::OPT_undefined); Args.AddAllArgs(CmdArgs, options::OPT_unexported__symbols__list); Args.AddAllArgs(CmdArgs, options::OPT_weak__reference__mismatches); Args.AddLastArg(CmdArgs, options::OPT_X_Flag); Args.AddAllArgs(CmdArgs, options::OPT_y); Args.AddLastArg(CmdArgs, options::OPT_w); Args.AddAllArgs(CmdArgs, options::OPT_pagezero__size); Args.AddAllArgs(CmdArgs, options::OPT_segs__read__); Args.AddLastArg(CmdArgs, options::OPT_seglinkedit); Args.AddLastArg(CmdArgs, options::OPT_noseglinkedit); Args.AddAllArgs(CmdArgs, options::OPT_sectalign); Args.AddAllArgs(CmdArgs, options::OPT_sectobjectsymbols); Args.AddAllArgs(CmdArgs, options::OPT_segcreate); Args.AddLastArg(CmdArgs, options::OPT_whyload); Args.AddLastArg(CmdArgs, options::OPT_whatsloaded); Args.AddAllArgs(CmdArgs, options::OPT_dylinker__install__name); Args.AddLastArg(CmdArgs, options::OPT_dylinker); Args.AddLastArg(CmdArgs, options::OPT_Mach); } void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { assert(Output.getType() == types::TY_Image && "Invalid linker output type."); // The logic here is derived from gcc's behavior; most of which // comes from specs (starting with link_command). Consult gcc for // more information. ArgStringList CmdArgs; /// Hack(tm) to ignore linking errors when we are doing ARC migration. if (Args.hasArg(options::OPT_ccc_arcmt_check, options::OPT_ccc_arcmt_migrate)) { for (ArgList::const_iterator I = Args.begin(), E = Args.end(); I != E; ++I) (*I)->claim(); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("touch")); CmdArgs.push_back(Output.getFilename()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); return; } // I'm not sure why this particular decomposition exists in gcc, but // we follow suite for ease of comparison. AddLinkArgs(C, Args, CmdArgs, Inputs); Args.AddAllArgs(CmdArgs, options::OPT_d_Flag); Args.AddAllArgs(CmdArgs, options::OPT_s); Args.AddAllArgs(CmdArgs, options::OPT_t); Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag); Args.AddAllArgs(CmdArgs, options::OPT_u_Group); Args.AddLastArg(CmdArgs, options::OPT_e); Args.AddAllArgs(CmdArgs, options::OPT_r); // Forward -ObjC when either -ObjC or -ObjC++ is used, to force loading // members of static archive libraries which implement Objective-C classes or // categories. if (Args.hasArg(options::OPT_ObjC) || Args.hasArg(options::OPT_ObjCXX)) CmdArgs.push_back("-ObjC"); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { // Derived from startfile spec. if (Args.hasArg(options::OPT_dynamiclib)) { // Derived from darwin_dylib1 spec. if (getDarwinToolChain().isTargetIOSSimulator()) { // The simulator doesn't have a versioned crt1 file. CmdArgs.push_back("-ldylib1.o"); } else if (getDarwinToolChain().isTargetIPhoneOS()) { if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1)) CmdArgs.push_back("-ldylib1.o"); } else { if (getDarwinToolChain().isMacosxVersionLT(10, 5)) CmdArgs.push_back("-ldylib1.o"); else if (getDarwinToolChain().isMacosxVersionLT(10, 6)) CmdArgs.push_back("-ldylib1.10.5.o"); } } else { if (Args.hasArg(options::OPT_bundle)) { if (!Args.hasArg(options::OPT_static)) { // Derived from darwin_bundle1 spec. if (getDarwinToolChain().isTargetIOSSimulator()) { // The simulator doesn't have a versioned crt1 file. CmdArgs.push_back("-lbundle1.o"); } else if (getDarwinToolChain().isTargetIPhoneOS()) { if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1)) CmdArgs.push_back("-lbundle1.o"); } else { if (getDarwinToolChain().isMacosxVersionLT(10, 6)) CmdArgs.push_back("-lbundle1.o"); } } } else { if (Args.hasArg(options::OPT_pg) && getToolChain().SupportsProfiling()) { if (Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_object) || Args.hasArg(options::OPT_preload)) { CmdArgs.push_back("-lgcrt0.o"); } else { CmdArgs.push_back("-lgcrt1.o"); // darwin_crt2 spec is empty. } // By default on OS X 10.8 and later, we don't link with a crt1.o // file and the linker knows to use _main as the entry point. But, // when compiling with -pg, we need to link with the gcrt1.o file, // so pass the -no_new_main option to tell the linker to use the // "start" symbol as the entry point. if (getDarwinToolChain().isTargetMacOS() && !getDarwinToolChain().isMacosxVersionLT(10, 8)) CmdArgs.push_back("-no_new_main"); } else { if (Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_object) || Args.hasArg(options::OPT_preload)) { CmdArgs.push_back("-lcrt0.o"); } else { // Derived from darwin_crt1 spec. if (getDarwinToolChain().isTargetIOSSimulator()) { // The simulator doesn't have a versioned crt1 file. CmdArgs.push_back("-lcrt1.o"); } else if (getDarwinToolChain().isTargetIPhoneOS()) { if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1)) CmdArgs.push_back("-lcrt1.o"); else if (getDarwinToolChain().isIPhoneOSVersionLT(6, 0)) CmdArgs.push_back("-lcrt1.3.1.o"); } else { if (getDarwinToolChain().isMacosxVersionLT(10, 5)) CmdArgs.push_back("-lcrt1.o"); else if (getDarwinToolChain().isMacosxVersionLT(10, 6)) CmdArgs.push_back("-lcrt1.10.5.o"); else if (getDarwinToolChain().isMacosxVersionLT(10, 8)) CmdArgs.push_back("-lcrt1.10.6.o"); // darwin_crt2 spec is empty. } } } } } if (!getDarwinToolChain().isTargetIPhoneOS() && Args.hasArg(options::OPT_shared_libgcc) && getDarwinToolChain().isMacosxVersionLT(10, 5)) { const char *Str = Args.MakeArgString(getToolChain().GetFilePath("crt3.o")); CmdArgs.push_back(Str); } } Args.AddAllArgs(CmdArgs, options::OPT_L); if (Args.hasArg(options::OPT_fopenmp)) // This is more complicated in gcc... CmdArgs.push_back("-lgomp"); AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); if (isObjCRuntimeLinked(Args) && !Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { // Avoid linking compatibility stubs on i386 mac. if (!getDarwinToolChain().isTargetMacOS() || getDarwinToolChain().getArch() != llvm::Triple::x86) { // If we don't have ARC or subscripting runtime support, link in the // runtime stubs. We have to do this *before* adding any of the normal // linker inputs so that its initializer gets run first. ObjCRuntime runtime = getDarwinToolChain().getDefaultObjCRuntime(/*nonfragile*/ true); // We use arclite library for both ARC and subscripting support. if ((!runtime.hasNativeARC() && isObjCAutoRefCount(Args)) || !runtime.hasSubscripting()) getDarwinToolChain().AddLinkARCArgs(Args, CmdArgs); } CmdArgs.push_back("-framework"); CmdArgs.push_back("Foundation"); // Link libobj. CmdArgs.push_back("-lobjc"); } if (LinkingOutput) { CmdArgs.push_back("-arch_multiple"); CmdArgs.push_back("-final_output"); CmdArgs.push_back(LinkingOutput); } if (Args.hasArg(options::OPT_fnested_functions)) CmdArgs.push_back("-allow_stack_execute"); if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { if (getToolChain().getDriver().CCCIsCXX()) getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); // link_ssp spec is empty. // Let the tool chain choose which runtime library to link. getDarwinToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs); } if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { // endfile_spec is empty. } Args.AddAllArgs(CmdArgs, options::OPT_T_Group); Args.AddAllArgs(CmdArgs, options::OPT_F); const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { ArgStringList CmdArgs; CmdArgs.push_back("-create"); assert(Output.isFilename() && "Unexpected lipo output."); CmdArgs.push_back("-output"); CmdArgs.push_back(Output.getFilename()); for (InputInfoList::const_iterator it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { const InputInfo &II = *it; assert(II.isFilename() && "Unexpected lipo input."); CmdArgs.push_back(II.getFilename()); } const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("lipo")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { ArgStringList CmdArgs; CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); assert(Inputs.size() == 1 && "Unable to handle multiple inputs."); const InputInfo &Input = Inputs[0]; assert(Input.isFilename() && "Unexpected dsymutil input."); CmdArgs.push_back(Input.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("dsymutil")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { ArgStringList CmdArgs; CmdArgs.push_back("--verify"); CmdArgs.push_back("--debug-info"); CmdArgs.push_back("--eh-frame"); CmdArgs.push_back("--quiet"); assert(Inputs.size() == 1 && "Unable to handle multiple inputs."); const InputInfo &Input = Inputs[0]; assert(Input.isFilename() && "Unexpected verify input"); // Grabbing the output of the earlier dsymutil run. CmdArgs.push_back(Input.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("dwarfdump")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } void solaris::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { ArgStringList CmdArgs; Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); for (InputInfoList::const_iterator it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { const InputInfo &II = *it; CmdArgs.push_back(II.getFilename()); } const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } void solaris::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { // FIXME: Find a real GCC, don't hard-code versions here std::string GCCLibPath = "/usr/gcc/4.5/lib/gcc/"; const llvm::Triple &T = getToolChain().getTriple(); std::string LibPath = "/usr/lib/"; llvm::Triple::ArchType Arch = T.getArch(); switch (Arch) { case llvm::Triple::x86: GCCLibPath += ("i386-" + T.getVendorName() + "-" + T.getOSName()).str() + "/4.5.2/"; break; case llvm::Triple::x86_64: GCCLibPath += ("i386-" + T.getVendorName() + "-" + T.getOSName()).str(); GCCLibPath += "/4.5.2/amd64/"; LibPath += "amd64/"; break; default: llvm_unreachable("Unsupported architecture"); } ArgStringList CmdArgs; // Demangle C++ names in errors CmdArgs.push_back("-C"); if ((!Args.hasArg(options::OPT_nostdlib)) && (!Args.hasArg(options::OPT_shared))) { CmdArgs.push_back("-e"); CmdArgs.push_back("_start"); } if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-Bstatic"); CmdArgs.push_back("-dn"); } else { CmdArgs.push_back("-Bdynamic"); if (Args.hasArg(options::OPT_shared)) { CmdArgs.push_back("-shared"); } else { CmdArgs.push_back("--dynamic-linker"); CmdArgs.push_back(Args.MakeArgString(LibPath + "ld.so.1")); } } if (Output.isFilename()) { CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); } else { assert(Output.isNothing() && "Invalid output."); } if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { if (!Args.hasArg(options::OPT_shared)) { CmdArgs.push_back(Args.MakeArgString(LibPath + "crt1.o")); CmdArgs.push_back(Args.MakeArgString(LibPath + "crti.o")); CmdArgs.push_back(Args.MakeArgString(LibPath + "values-Xa.o")); CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtbegin.o")); } else { CmdArgs.push_back(Args.MakeArgString(LibPath + "crti.o")); CmdArgs.push_back(Args.MakeArgString(LibPath + "values-Xa.o")); CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtbegin.o")); } if (getToolChain().getDriver().CCCIsCXX()) CmdArgs.push_back(Args.MakeArgString(LibPath + "cxa_finalize.o")); } CmdArgs.push_back(Args.MakeArgString("-L" + GCCLibPath)); Args.AddAllArgs(CmdArgs, options::OPT_L); Args.AddAllArgs(CmdArgs, options::OPT_T_Group); Args.AddAllArgs(CmdArgs, options::OPT_e); Args.AddAllArgs(CmdArgs, options::OPT_r); AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { if (getToolChain().getDriver().CCCIsCXX()) getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); CmdArgs.push_back("-lgcc_s"); if (!Args.hasArg(options::OPT_shared)) { CmdArgs.push_back("-lgcc"); CmdArgs.push_back("-lc"); CmdArgs.push_back("-lm"); } } if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtend.o")); } CmdArgs.push_back(Args.MakeArgString(LibPath + "crtn.o")); addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } void auroraux::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { ArgStringList CmdArgs; Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); for (InputInfoList::const_iterator it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { const InputInfo &II = *it; CmdArgs.push_back(II.getFilename()); } const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("gas")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { ArgStringList CmdArgs; if ((!Args.hasArg(options::OPT_nostdlib)) && (!Args.hasArg(options::OPT_shared))) { CmdArgs.push_back("-e"); CmdArgs.push_back("_start"); } if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-Bstatic"); CmdArgs.push_back("-dn"); } else { // CmdArgs.push_back("--eh-frame-hdr"); CmdArgs.push_back("-Bdynamic"); if (Args.hasArg(options::OPT_shared)) { CmdArgs.push_back("-shared"); } else { CmdArgs.push_back("--dynamic-linker"); CmdArgs.push_back("/lib/ld.so.1"); // 64Bit Path /lib/amd64/ld.so.1 } } if (Output.isFilename()) { CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); } else { assert(Output.isNothing() && "Invalid output."); } if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { if (!Args.hasArg(options::OPT_shared)) { CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crt1.o"))); CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crti.o"))); CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crtbegin.o"))); } else { CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crti.o"))); } CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crtn.o"))); } CmdArgs.push_back(Args.MakeArgString("-L/opt/gcc4/lib/gcc/" + getToolChain().getTripleString() + "/4.2.4")); Args.AddAllArgs(CmdArgs, options::OPT_L); Args.AddAllArgs(CmdArgs, options::OPT_T_Group); Args.AddAllArgs(CmdArgs, options::OPT_e); AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { // FIXME: For some reason GCC passes -lgcc before adding // the default system libraries. Just mimic this for now. CmdArgs.push_back("-lgcc"); if (Args.hasArg(options::OPT_pthread)) CmdArgs.push_back("-pthread"); if (!Args.hasArg(options::OPT_shared)) CmdArgs.push_back("-lc"); CmdArgs.push_back("-lgcc"); } if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { if (!Args.hasArg(options::OPT_shared)) CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crtend.o"))); } addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { ArgStringList CmdArgs; // When building 32-bit code on OpenBSD/amd64, we have to explicitly // instruct as in the base system to assemble 32-bit code. if (getToolChain().getArch() == llvm::Triple::x86) CmdArgs.push_back("--32"); else if (getToolChain().getArch() == llvm::Triple::ppc) { CmdArgs.push_back("-mppc"); CmdArgs.push_back("-many"); } else if (getToolChain().getArch() == llvm::Triple::mips64 || getToolChain().getArch() == llvm::Triple::mips64el) { StringRef CPUName; StringRef ABIName; getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName); CmdArgs.push_back("-mabi"); CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data()); if (getToolChain().getArch() == llvm::Triple::mips64) CmdArgs.push_back("-EB"); else CmdArgs.push_back("-EL"); Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, options::OPT_fpic, options::OPT_fno_pic, options::OPT_fPIE, options::OPT_fno_PIE, options::OPT_fpie, options::OPT_fno_pie); if (LastPICArg && (LastPICArg->getOption().matches(options::OPT_fPIC) || LastPICArg->getOption().matches(options::OPT_fpic) || LastPICArg->getOption().matches(options::OPT_fPIE) || LastPICArg->getOption().matches(options::OPT_fpie))) { CmdArgs.push_back("-KPIC"); } } Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); for (InputInfoList::const_iterator it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { const InputInfo &II = *it; CmdArgs.push_back(II.getFilename()); } const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { const Driver &D = getToolChain().getDriver(); ArgStringList CmdArgs; // Silence warning for "clang -g foo.o -o foo" Args.ClaimAllArgs(options::OPT_g_Group); // and "clang -emit-llvm foo.o -o foo" Args.ClaimAllArgs(options::OPT_emit_llvm); // and for "clang -w foo.o -o foo". Other warning options are already // handled somewhere else. Args.ClaimAllArgs(options::OPT_w); if (getToolChain().getArch() == llvm::Triple::mips64) CmdArgs.push_back("-EB"); else if (getToolChain().getArch() == llvm::Triple::mips64el) CmdArgs.push_back("-EL"); if ((!Args.hasArg(options::OPT_nostdlib)) && (!Args.hasArg(options::OPT_shared))) { CmdArgs.push_back("-e"); CmdArgs.push_back("__start"); } if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-Bstatic"); } else { if (Args.hasArg(options::OPT_rdynamic)) CmdArgs.push_back("-export-dynamic"); CmdArgs.push_back("--eh-frame-hdr"); CmdArgs.push_back("-Bdynamic"); if (Args.hasArg(options::OPT_shared)) { CmdArgs.push_back("-shared"); } else { CmdArgs.push_back("-dynamic-linker"); CmdArgs.push_back("/usr/libexec/ld.so"); } } if (Args.hasArg(options::OPT_nopie)) CmdArgs.push_back("-nopie"); if (Output.isFilename()) { CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); } else { assert(Output.isNothing() && "Invalid output."); } if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { if (!Args.hasArg(options::OPT_shared)) { if (Args.hasArg(options::OPT_pg)) CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("gcrt0.o"))); else CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crt0.o"))); CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crtbegin.o"))); } else { CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crtbeginS.o"))); } } std::string Triple = getToolChain().getTripleString(); if (Triple.substr(0, 6) == "x86_64") Triple.replace(0, 6, "amd64"); CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc-lib/" + Triple + "/4.2.1")); Args.AddAllArgs(CmdArgs, options::OPT_L); Args.AddAllArgs(CmdArgs, options::OPT_T_Group); Args.AddAllArgs(CmdArgs, options::OPT_e); Args.AddAllArgs(CmdArgs, options::OPT_s); Args.AddAllArgs(CmdArgs, options::OPT_t); Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag); Args.AddAllArgs(CmdArgs, options::OPT_r); AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { if (D.CCCIsCXX()) { getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); if (Args.hasArg(options::OPT_pg)) CmdArgs.push_back("-lm_p"); else CmdArgs.push_back("-lm"); } // FIXME: For some reason GCC passes -lgcc before adding // the default system libraries. Just mimic this for now. CmdArgs.push_back("-lgcc"); if (Args.hasArg(options::OPT_pthread)) { if (!Args.hasArg(options::OPT_shared) && Args.hasArg(options::OPT_pg)) CmdArgs.push_back("-lpthread_p"); else CmdArgs.push_back("-lpthread"); } if (!Args.hasArg(options::OPT_shared)) { if (Args.hasArg(options::OPT_pg)) CmdArgs.push_back("-lc_p"); else CmdArgs.push_back("-lc"); } CmdArgs.push_back("-lgcc"); } if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { if (!Args.hasArg(options::OPT_shared)) CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crtend.o"))); else CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crtendS.o"))); } const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } void bitrig::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { ArgStringList CmdArgs; Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); for (InputInfoList::const_iterator it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { const InputInfo &II = *it; CmdArgs.push_back(II.getFilename()); } const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } void bitrig::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { const Driver &D = getToolChain().getDriver(); ArgStringList CmdArgs; if ((!Args.hasArg(options::OPT_nostdlib)) && (!Args.hasArg(options::OPT_shared))) { CmdArgs.push_back("-e"); CmdArgs.push_back("__start"); } if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-Bstatic"); } else { if (Args.hasArg(options::OPT_rdynamic)) CmdArgs.push_back("-export-dynamic"); CmdArgs.push_back("--eh-frame-hdr"); CmdArgs.push_back("-Bdynamic"); if (Args.hasArg(options::OPT_shared)) { CmdArgs.push_back("-shared"); } else { CmdArgs.push_back("-dynamic-linker"); CmdArgs.push_back("/usr/libexec/ld.so"); } } if (Output.isFilename()) { CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); } else { assert(Output.isNothing() && "Invalid output."); } if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { if (!Args.hasArg(options::OPT_shared)) { if (Args.hasArg(options::OPT_pg)) CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("gcrt0.o"))); else CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crt0.o"))); CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crtbegin.o"))); } else { CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crtbeginS.o"))); } } Args.AddAllArgs(CmdArgs, options::OPT_L); Args.AddAllArgs(CmdArgs, options::OPT_T_Group); Args.AddAllArgs(CmdArgs, options::OPT_e); AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { if (D.CCCIsCXX()) { getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); if (Args.hasArg(options::OPT_pg)) CmdArgs.push_back("-lm_p"); else CmdArgs.push_back("-lm"); } if (Args.hasArg(options::OPT_pthread)) { if (!Args.hasArg(options::OPT_shared) && Args.hasArg(options::OPT_pg)) CmdArgs.push_back("-lpthread_p"); else CmdArgs.push_back("-lpthread"); } if (!Args.hasArg(options::OPT_shared)) { if (Args.hasArg(options::OPT_pg)) CmdArgs.push_back("-lc_p"); else CmdArgs.push_back("-lc"); } StringRef MyArch; switch (getToolChain().getTriple().getArch()) { case llvm::Triple::arm: MyArch = "arm"; break; case llvm::Triple::x86: MyArch = "i386"; break; case llvm::Triple::x86_64: MyArch = "amd64"; break; default: llvm_unreachable("Unsupported architecture"); } CmdArgs.push_back(Args.MakeArgString("-lclang_rt." + MyArch)); } if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { if (!Args.hasArg(options::OPT_shared)) CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crtend.o"))); else CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crtendS.o"))); } const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { ArgStringList CmdArgs; // When building 32-bit code on FreeBSD/amd64, we have to explicitly // instruct as in the base system to assemble 32-bit code. if (getToolChain().getArch() == llvm::Triple::x86) CmdArgs.push_back("--32"); else if (getToolChain().getArch() == llvm::Triple::ppc) CmdArgs.push_back("-a32"); else if (getToolChain().getArch() == llvm::Triple::mips || getToolChain().getArch() == llvm::Triple::mipsel || getToolChain().getArch() == llvm::Triple::mips64 || getToolChain().getArch() == llvm::Triple::mips64el) { StringRef CPUName; StringRef ABIName; getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName); CmdArgs.push_back("-march"); CmdArgs.push_back(CPUName.data()); CmdArgs.push_back("-mabi"); CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data()); if (getToolChain().getArch() == llvm::Triple::mips || getToolChain().getArch() == llvm::Triple::mips64) CmdArgs.push_back("-EB"); else CmdArgs.push_back("-EL"); Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, options::OPT_fpic, options::OPT_fno_pic, options::OPT_fPIE, options::OPT_fno_PIE, options::OPT_fpie, options::OPT_fno_pie); if (LastPICArg && (LastPICArg->getOption().matches(options::OPT_fPIC) || LastPICArg->getOption().matches(options::OPT_fpic) || LastPICArg->getOption().matches(options::OPT_fPIE) || LastPICArg->getOption().matches(options::OPT_fpie))) { CmdArgs.push_back("-KPIC"); } } else if (getToolChain().getArch() == llvm::Triple::arm || getToolChain().getArch() == llvm::Triple::thumb) { CmdArgs.push_back("-mfpu=softvfp"); switch(getToolChain().getTriple().getEnvironment()) { case llvm::Triple::GNUEABI: case llvm::Triple::EABI: CmdArgs.push_back("-meabi=5"); break; default: CmdArgs.push_back("-matpcs"); } } else if (getToolChain().getArch() == llvm::Triple::sparc || getToolChain().getArch() == llvm::Triple::sparcv9) { if (getToolChain().getArch() == llvm::Triple::sparc) CmdArgs.push_back("-Av8plusa"); else CmdArgs.push_back("-Av9a"); Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, options::OPT_fpic, options::OPT_fno_pic, options::OPT_fPIE, options::OPT_fno_PIE, options::OPT_fpie, options::OPT_fno_pie); if (LastPICArg && (LastPICArg->getOption().matches(options::OPT_fPIC) || LastPICArg->getOption().matches(options::OPT_fpic) || LastPICArg->getOption().matches(options::OPT_fPIE) || LastPICArg->getOption().matches(options::OPT_fpie))) { CmdArgs.push_back("-KPIC"); } } Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); for (InputInfoList::const_iterator it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { const InputInfo &II = *it; CmdArgs.push_back(II.getFilename()); } const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { const toolchains::FreeBSD& ToolChain = static_cast(getToolChain()); const Driver &D = ToolChain.getDriver(); ArgStringList CmdArgs; // Silence warning for "clang -g foo.o -o foo" Args.ClaimAllArgs(options::OPT_g_Group); // and "clang -emit-llvm foo.o -o foo" Args.ClaimAllArgs(options::OPT_emit_llvm); // and for "clang -w foo.o -o foo". Other warning options are already // handled somewhere else. Args.ClaimAllArgs(options::OPT_w); if (!D.SysRoot.empty()) CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); if (Args.hasArg(options::OPT_pie)) CmdArgs.push_back("-pie"); if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-Bstatic"); } else { if (Args.hasArg(options::OPT_rdynamic)) CmdArgs.push_back("-export-dynamic"); CmdArgs.push_back("--eh-frame-hdr"); if (Args.hasArg(options::OPT_shared)) { CmdArgs.push_back("-Bshareable"); } else { CmdArgs.push_back("-dynamic-linker"); CmdArgs.push_back("/libexec/ld-elf.so.1"); } if (ToolChain.getTriple().getOSMajorVersion() >= 9) { llvm::Triple::ArchType Arch = ToolChain.getArch(); if (Arch == llvm::Triple::arm || Arch == llvm::Triple::sparc || Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) { CmdArgs.push_back("--hash-style=both"); } } CmdArgs.push_back("--enable-new-dtags"); } // When building 32-bit code on FreeBSD/amd64, we have to explicitly // instruct ld in the base system to link 32-bit code. if (ToolChain.getArch() == llvm::Triple::x86) { CmdArgs.push_back("-m"); CmdArgs.push_back("elf_i386_fbsd"); } if (ToolChain.getArch() == llvm::Triple::ppc) { CmdArgs.push_back("-m"); CmdArgs.push_back("elf32ppc"); } if (Output.isFilename()) { CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); } else { assert(Output.isNothing() && "Invalid output."); } if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { const char *crt1 = NULL; if (!Args.hasArg(options::OPT_shared)) { if (Args.hasArg(options::OPT_pg)) crt1 = "gcrt1.o"; else if (Args.hasArg(options::OPT_pie)) crt1 = "Scrt1.o"; else crt1 = "crt1.o"; } if (crt1) CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1))); CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o"))); const char *crtbegin = NULL; if (Args.hasArg(options::OPT_static)) crtbegin = "crtbeginT.o"; else if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) crtbegin = "crtbeginS.o"; else crtbegin = "crtbegin.o"; CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin))); } Args.AddAllArgs(CmdArgs, options::OPT_L); const ToolChain::path_list Paths = ToolChain.getFilePaths(); for (ToolChain::path_list::const_iterator i = Paths.begin(), e = Paths.end(); i != e; ++i) CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + *i)); Args.AddAllArgs(CmdArgs, options::OPT_T_Group); Args.AddAllArgs(CmdArgs, options::OPT_e); Args.AddAllArgs(CmdArgs, options::OPT_s); Args.AddAllArgs(CmdArgs, options::OPT_t); Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag); Args.AddAllArgs(CmdArgs, options::OPT_r); // Tell the linker to load the plugin. This has to come before AddLinkerInputs // as gold requires -plugin to come before any -plugin-opt that -Wl might // forward. if (D.IsUsingLTO(Args)) { CmdArgs.push_back("-plugin"); std::string Plugin = ToolChain.getDriver().Dir + "/../lib/LLVMgold.so"; CmdArgs.push_back(Args.MakeArgString(Plugin)); // Try to pass driver level flags relevant to LTO code generation down to // the plugin. // Handle flags for selecting CPU variants. std::string CPU = getCPUName(Args, ToolChain.getTriple()); if (!CPU.empty()) { CmdArgs.push_back( Args.MakeArgString(Twine("-plugin-opt=mcpu=") + CPU)); } } AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { if (D.CCCIsCXX()) { ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); if (Args.hasArg(options::OPT_pg)) CmdArgs.push_back("-lm_p"); else CmdArgs.push_back("-lm"); } // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding // the default system libraries. Just mimic this for now. if (Args.hasArg(options::OPT_pg)) CmdArgs.push_back("-lgcc_p"); else CmdArgs.push_back("-lgcc"); if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-lgcc_eh"); } else if (Args.hasArg(options::OPT_pg)) { CmdArgs.push_back("-lgcc_eh_p"); } else { CmdArgs.push_back("--as-needed"); CmdArgs.push_back("-lgcc_s"); CmdArgs.push_back("--no-as-needed"); } if (Args.hasArg(options::OPT_pthread)) { if (Args.hasArg(options::OPT_pg)) CmdArgs.push_back("-lpthread_p"); else CmdArgs.push_back("-lpthread"); } if (Args.hasArg(options::OPT_pg)) { if (Args.hasArg(options::OPT_shared)) CmdArgs.push_back("-lc"); else CmdArgs.push_back("-lc_p"); CmdArgs.push_back("-lgcc_p"); } else { CmdArgs.push_back("-lc"); CmdArgs.push_back("-lgcc"); } if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-lgcc_eh"); } else if (Args.hasArg(options::OPT_pg)) { CmdArgs.push_back("-lgcc_eh_p"); } else { CmdArgs.push_back("--as-needed"); CmdArgs.push_back("-lgcc_s"); CmdArgs.push_back("--no-as-needed"); } } if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtendS.o"))); else CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o"))); CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o"))); } addProfileRT(ToolChain, Args, CmdArgs, ToolChain.getTriple()); const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { ArgStringList CmdArgs; // When building 32-bit code on NetBSD/amd64, we have to explicitly // instruct as in the base system to assemble 32-bit code. if (getToolChain().getArch() == llvm::Triple::x86) CmdArgs.push_back("--32"); // Pass the target CPU to GNU as for ARM, since the source code might // not have the correct .cpu annotation. if (getToolChain().getArch() == llvm::Triple::arm) { std::string MArch(getARMTargetCPU(Args, getToolChain().getTriple())); CmdArgs.push_back(Args.MakeArgString("-mcpu=" + MArch)); } if (getToolChain().getArch() == llvm::Triple::mips || getToolChain().getArch() == llvm::Triple::mipsel || getToolChain().getArch() == llvm::Triple::mips64 || getToolChain().getArch() == llvm::Triple::mips64el) { StringRef CPUName; StringRef ABIName; getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName); CmdArgs.push_back("-march"); CmdArgs.push_back(CPUName.data()); CmdArgs.push_back("-mabi"); CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data()); if (getToolChain().getArch() == llvm::Triple::mips || getToolChain().getArch() == llvm::Triple::mips64) CmdArgs.push_back("-EB"); else CmdArgs.push_back("-EL"); Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, options::OPT_fpic, options::OPT_fno_pic, options::OPT_fPIE, options::OPT_fno_PIE, options::OPT_fpie, options::OPT_fno_pie); if (LastPICArg && (LastPICArg->getOption().matches(options::OPT_fPIC) || LastPICArg->getOption().matches(options::OPT_fpic) || LastPICArg->getOption().matches(options::OPT_fPIE) || LastPICArg->getOption().matches(options::OPT_fpie))) { CmdArgs.push_back("-KPIC"); } } Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); for (InputInfoList::const_iterator it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { const InputInfo &II = *it; CmdArgs.push_back(II.getFilename()); } const char *Exec = Args.MakeArgString((getToolChain().GetProgramPath("as"))); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { const Driver &D = getToolChain().getDriver(); ArgStringList CmdArgs; if (!D.SysRoot.empty()) CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-Bstatic"); } else { if (Args.hasArg(options::OPT_rdynamic)) CmdArgs.push_back("-export-dynamic"); CmdArgs.push_back("--eh-frame-hdr"); if (Args.hasArg(options::OPT_shared)) { CmdArgs.push_back("-Bshareable"); } else { CmdArgs.push_back("-dynamic-linker"); CmdArgs.push_back("/libexec/ld.elf_so"); } } // When building 32-bit code on NetBSD/amd64, we have to explicitly // instruct ld in the base system to link 32-bit code. if (getToolChain().getArch() == llvm::Triple::x86) { CmdArgs.push_back("-m"); CmdArgs.push_back("elf_i386"); } if (Output.isFilename()) { CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); } else { assert(Output.isNothing() && "Invalid output."); } if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { if (!Args.hasArg(options::OPT_shared)) { CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crt0.o"))); CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crti.o"))); CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crtbegin.o"))); } else { CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crti.o"))); CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crtbeginS.o"))); } } Args.AddAllArgs(CmdArgs, options::OPT_L); Args.AddAllArgs(CmdArgs, options::OPT_T_Group); Args.AddAllArgs(CmdArgs, options::OPT_e); Args.AddAllArgs(CmdArgs, options::OPT_s); Args.AddAllArgs(CmdArgs, options::OPT_t); Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag); Args.AddAllArgs(CmdArgs, options::OPT_r); AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); unsigned Major, Minor, Micro; getToolChain().getTriple().getOSVersion(Major, Minor, Micro); bool useLibgcc = true; if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 23) || Major == 0) { if (getToolChain().getArch() == llvm::Triple::x86 || getToolChain().getArch() == llvm::Triple::x86_64) useLibgcc = false; } if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { if (D.CCCIsCXX()) { getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); CmdArgs.push_back("-lm"); } if (Args.hasArg(options::OPT_pthread)) CmdArgs.push_back("-lpthread"); CmdArgs.push_back("-lc"); if (useLibgcc) { if (Args.hasArg(options::OPT_static)) { // libgcc_eh depends on libc, so resolve as much as possible, // pull in any new requirements from libc and then get the rest // of libgcc. CmdArgs.push_back("-lgcc_eh"); CmdArgs.push_back("-lc"); CmdArgs.push_back("-lgcc"); } else { CmdArgs.push_back("-lgcc"); CmdArgs.push_back("--as-needed"); CmdArgs.push_back("-lgcc_s"); CmdArgs.push_back("--no-as-needed"); } } } if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { if (!Args.hasArg(options::OPT_shared)) CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath( "crtend.o"))); else CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath( "crtendS.o"))); CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath( "crtn.o"))); } addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { ArgStringList CmdArgs; bool NeedsKPIC = false; // Add --32/--64 to make sure we get the format we want. // This is incomplete if (getToolChain().getArch() == llvm::Triple::x86) { CmdArgs.push_back("--32"); } else if (getToolChain().getArch() == llvm::Triple::x86_64) { CmdArgs.push_back("--64"); } else if (getToolChain().getArch() == llvm::Triple::ppc) { CmdArgs.push_back("-a32"); CmdArgs.push_back("-mppc"); CmdArgs.push_back("-many"); } else if (getToolChain().getArch() == llvm::Triple::ppc64) { CmdArgs.push_back("-a64"); CmdArgs.push_back("-mppc64"); CmdArgs.push_back("-many"); } else if (getToolChain().getArch() == llvm::Triple::ppc64le) { CmdArgs.push_back("-a64"); CmdArgs.push_back("-mppc64le"); CmdArgs.push_back("-many"); } else if (getToolChain().getArch() == llvm::Triple::sparc) { CmdArgs.push_back("-32"); CmdArgs.push_back("-Av8plusa"); NeedsKPIC = true; } else if (getToolChain().getArch() == llvm::Triple::sparcv9) { CmdArgs.push_back("-64"); CmdArgs.push_back("-Av9a"); NeedsKPIC = true; } else if (getToolChain().getArch() == llvm::Triple::arm) { StringRef MArch = getToolChain().getArchName(); if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a") CmdArgs.push_back("-mfpu=neon"); if (MArch == "armv8" || MArch == "armv8a" || MArch == "armv8-a") CmdArgs.push_back("-mfpu=crypto-neon-fp-armv8"); StringRef ARMFloatABI = getARMFloatABI(getToolChain().getDriver(), Args, getToolChain().getTriple()); CmdArgs.push_back(Args.MakeArgString("-mfloat-abi=" + ARMFloatABI)); Args.AddLastArg(CmdArgs, options::OPT_march_EQ); Args.AddLastArg(CmdArgs, options::OPT_mcpu_EQ); Args.AddLastArg(CmdArgs, options::OPT_mfpu_EQ); } else if (getToolChain().getArch() == llvm::Triple::mips || getToolChain().getArch() == llvm::Triple::mipsel || getToolChain().getArch() == llvm::Triple::mips64 || getToolChain().getArch() == llvm::Triple::mips64el) { StringRef CPUName; StringRef ABIName; getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName); CmdArgs.push_back("-march"); CmdArgs.push_back(CPUName.data()); CmdArgs.push_back("-mabi"); CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data()); if (getToolChain().getArch() == llvm::Triple::mips || getToolChain().getArch() == llvm::Triple::mips64) CmdArgs.push_back("-EB"); else CmdArgs.push_back("-EL"); if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) { if (StringRef(A->getValue()) == "2008") CmdArgs.push_back(Args.MakeArgString("-mnan=2008")); } if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfp64)) { if (A->getOption().matches(options::OPT_mfp32)) CmdArgs.push_back(Args.MakeArgString("-mfp32")); else CmdArgs.push_back(Args.MakeArgString("-mfp64")); } Args.AddLastArg(CmdArgs, options::OPT_mips16, options::OPT_mno_mips16); Args.AddLastArg(CmdArgs, options::OPT_mmicromips, options::OPT_mno_micromips); Args.AddLastArg(CmdArgs, options::OPT_mdsp, options::OPT_mno_dsp); Args.AddLastArg(CmdArgs, options::OPT_mdspr2, options::OPT_mno_dspr2); if (Arg *A = Args.getLastArg(options::OPT_mmsa, options::OPT_mno_msa)) { // Do not use AddLastArg because not all versions of MIPS assembler // support -mmsa / -mno-msa options. if (A->getOption().matches(options::OPT_mmsa)) CmdArgs.push_back(Args.MakeArgString("-mmsa")); } NeedsKPIC = true; } else if (getToolChain().getArch() == llvm::Triple::systemz) { // Always pass an -march option, since our default of z10 is later // than the GNU assembler's default. StringRef CPUName = getSystemZTargetCPU(Args); CmdArgs.push_back(Args.MakeArgString("-march=" + CPUName)); } if (NeedsKPIC) { Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, options::OPT_fpic, options::OPT_fno_pic, options::OPT_fPIE, options::OPT_fno_PIE, options::OPT_fpie, options::OPT_fno_pie); if (LastPICArg && (LastPICArg->getOption().matches(options::OPT_fPIC) || LastPICArg->getOption().matches(options::OPT_fpic) || LastPICArg->getOption().matches(options::OPT_fPIE) || LastPICArg->getOption().matches(options::OPT_fpie))) { CmdArgs.push_back("-KPIC"); } } Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); for (InputInfoList::const_iterator it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { const InputInfo &II = *it; CmdArgs.push_back(II.getFilename()); } const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); // Handle the debug info splitting at object creation time if we're // creating an object. // TODO: Currently only works on linux with newer objcopy. if (Args.hasArg(options::OPT_gsplit_dwarf) && getToolChain().getTriple().isOSLinux()) SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, SplitDebugName(Args, Inputs)); } static void AddLibgcc(llvm::Triple Triple, const Driver &D, ArgStringList &CmdArgs, const ArgList &Args) { bool isAndroid = Triple.getEnvironment() == llvm::Triple::Android; bool StaticLibgcc = Args.hasArg(options::OPT_static_libgcc) || Args.hasArg(options::OPT_static); if (!D.CCCIsCXX()) CmdArgs.push_back("-lgcc"); if (StaticLibgcc || isAndroid) { if (D.CCCIsCXX()) CmdArgs.push_back("-lgcc"); } else { if (!D.CCCIsCXX()) CmdArgs.push_back("--as-needed"); CmdArgs.push_back("-lgcc_s"); if (!D.CCCIsCXX()) CmdArgs.push_back("--no-as-needed"); } if (StaticLibgcc && !isAndroid) CmdArgs.push_back("-lgcc_eh"); else if (!Args.hasArg(options::OPT_shared) && D.CCCIsCXX()) CmdArgs.push_back("-lgcc"); // According to Android ABI, we have to link with libdl if we are // linking with non-static libgcc. // // NOTE: This fixes a link error on Android MIPS as well. The non-static // libgcc for MIPS relies on _Unwind_Find_FDE and dl_iterate_phdr from libdl. if (isAndroid && !StaticLibgcc) CmdArgs.push_back("-ldl"); } static bool hasMipsN32ABIArg(const ArgList &Args) { Arg *A = Args.getLastArg(options::OPT_mabi_EQ); return A && (A->getValue() == StringRef("n32")); } static StringRef getLinuxDynamicLinker(const ArgList &Args, const toolchains::Linux &ToolChain) { if (ToolChain.getTriple().getEnvironment() == llvm::Triple::Android) return "/system/bin/linker"; else if (ToolChain.getArch() == llvm::Triple::x86 || ToolChain.getArch() == llvm::Triple::sparc) return "/lib/ld-linux.so.2"; else if (ToolChain.getArch() == llvm::Triple::aarch64) return "/lib/ld-linux-aarch64.so.1"; else if (ToolChain.getArch() == llvm::Triple::arm || ToolChain.getArch() == llvm::Triple::thumb) { if (ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUEABIHF) return "/lib/ld-linux-armhf.so.3"; else return "/lib/ld-linux.so.3"; } else if (ToolChain.getArch() == llvm::Triple::mips || ToolChain.getArch() == llvm::Triple::mipsel) return "/lib/ld.so.1"; else if (ToolChain.getArch() == llvm::Triple::mips64 || ToolChain.getArch() == llvm::Triple::mips64el) { if (hasMipsN32ABIArg(Args)) return "/lib32/ld.so.1"; else return "/lib64/ld.so.1"; } else if (ToolChain.getArch() == llvm::Triple::ppc) return "/lib/ld.so.1"; else if (ToolChain.getArch() == llvm::Triple::ppc64 || ToolChain.getArch() == llvm::Triple::ppc64le || ToolChain.getArch() == llvm::Triple::systemz) return "/lib64/ld64.so.1"; else if (ToolChain.getArch() == llvm::Triple::sparcv9) return "/lib64/ld-linux.so.2"; else return "/lib64/ld-linux-x86-64.so.2"; } void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { const toolchains::Linux& ToolChain = static_cast(getToolChain()); const Driver &D = ToolChain.getDriver(); const bool isAndroid = ToolChain.getTriple().getEnvironment() == llvm::Triple::Android; const SanitizerArgs &Sanitize = ToolChain.getSanitizerArgs(); const bool IsPIE = !Args.hasArg(options::OPT_shared) && (Args.hasArg(options::OPT_pie) || Sanitize.hasZeroBaseShadow()); ArgStringList CmdArgs; // Silence warning for "clang -g foo.o -o foo" Args.ClaimAllArgs(options::OPT_g_Group); // and "clang -emit-llvm foo.o -o foo" Args.ClaimAllArgs(options::OPT_emit_llvm); // and for "clang -w foo.o -o foo". Other warning options are already // handled somewhere else. Args.ClaimAllArgs(options::OPT_w); if (!D.SysRoot.empty()) CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); if (IsPIE) CmdArgs.push_back("-pie"); if (Args.hasArg(options::OPT_rdynamic)) CmdArgs.push_back("-export-dynamic"); if (Args.hasArg(options::OPT_s)) CmdArgs.push_back("-s"); for (std::vector::const_iterator i = ToolChain.ExtraOpts.begin(), e = ToolChain.ExtraOpts.end(); i != e; ++i) CmdArgs.push_back(i->c_str()); if (!Args.hasArg(options::OPT_static)) { CmdArgs.push_back("--eh-frame-hdr"); } CmdArgs.push_back("-m"); if (ToolChain.getArch() == llvm::Triple::x86) CmdArgs.push_back("elf_i386"); else if (ToolChain.getArch() == llvm::Triple::aarch64) CmdArgs.push_back("aarch64linux"); else if (ToolChain.getArch() == llvm::Triple::arm || ToolChain.getArch() == llvm::Triple::thumb) CmdArgs.push_back("armelf_linux_eabi"); else if (ToolChain.getArch() == llvm::Triple::ppc) CmdArgs.push_back("elf32ppclinux"); else if (ToolChain.getArch() == llvm::Triple::ppc64) CmdArgs.push_back("elf64ppc"); else if (ToolChain.getArch() == llvm::Triple::sparc) CmdArgs.push_back("elf32_sparc"); else if (ToolChain.getArch() == llvm::Triple::sparcv9) CmdArgs.push_back("elf64_sparc"); else if (ToolChain.getArch() == llvm::Triple::mips) CmdArgs.push_back("elf32btsmip"); else if (ToolChain.getArch() == llvm::Triple::mipsel) CmdArgs.push_back("elf32ltsmip"); else if (ToolChain.getArch() == llvm::Triple::mips64) { if (hasMipsN32ABIArg(Args)) CmdArgs.push_back("elf32btsmipn32"); else CmdArgs.push_back("elf64btsmip"); } else if (ToolChain.getArch() == llvm::Triple::mips64el) { if (hasMipsN32ABIArg(Args)) CmdArgs.push_back("elf32ltsmipn32"); else CmdArgs.push_back("elf64ltsmip"); } else if (ToolChain.getArch() == llvm::Triple::systemz) CmdArgs.push_back("elf64_s390"); else CmdArgs.push_back("elf_x86_64"); if (Args.hasArg(options::OPT_static)) { if (ToolChain.getArch() == llvm::Triple::arm || ToolChain.getArch() == llvm::Triple::thumb) CmdArgs.push_back("-Bstatic"); else CmdArgs.push_back("-static"); } else if (Args.hasArg(options::OPT_shared)) { CmdArgs.push_back("-shared"); if (isAndroid) { CmdArgs.push_back("-Bsymbolic"); } } if (ToolChain.getArch() == llvm::Triple::arm || ToolChain.getArch() == llvm::Triple::thumb || (!Args.hasArg(options::OPT_static) && !Args.hasArg(options::OPT_shared))) { CmdArgs.push_back("-dynamic-linker"); CmdArgs.push_back(Args.MakeArgString( D.DyldPrefix + getLinuxDynamicLinker(Args, ToolChain))); } CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { if (!isAndroid) { const char *crt1 = NULL; if (!Args.hasArg(options::OPT_shared)){ if (Args.hasArg(options::OPT_pg)) crt1 = "gcrt1.o"; else if (IsPIE) crt1 = "Scrt1.o"; else crt1 = "crt1.o"; } if (crt1) CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1))); CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o"))); } const char *crtbegin; if (Args.hasArg(options::OPT_static)) crtbegin = isAndroid ? "crtbegin_static.o" : "crtbeginT.o"; else if (Args.hasArg(options::OPT_shared)) crtbegin = isAndroid ? "crtbegin_so.o" : "crtbeginS.o"; else if (IsPIE) crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbeginS.o"; else crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbegin.o"; CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin))); // Add crtfastmath.o if available and fast math is enabled. ToolChain.AddFastMathRuntimeIfAvailable(Args, CmdArgs); } Args.AddAllArgs(CmdArgs, options::OPT_L); const ToolChain::path_list Paths = ToolChain.getFilePaths(); for (ToolChain::path_list::const_iterator i = Paths.begin(), e = Paths.end(); i != e; ++i) CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + *i)); // Tell the linker to load the plugin. This has to come before AddLinkerInputs // as gold requires -plugin to come before any -plugin-opt that -Wl might // forward. if (D.IsUsingLTO(Args)) { CmdArgs.push_back("-plugin"); std::string Plugin = ToolChain.getDriver().Dir + "/../lib/LLVMgold.so"; CmdArgs.push_back(Args.MakeArgString(Plugin)); // Try to pass driver level flags relevant to LTO code generation down to // the plugin. // Handle flags for selecting CPU variants. std::string CPU = getCPUName(Args, ToolChain.getTriple()); if (!CPU.empty()) { CmdArgs.push_back( Args.MakeArgString(Twine("-plugin-opt=mcpu=") + CPU)); } } if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) CmdArgs.push_back("--no-demangle"); AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs); // Call these before we add the C++ ABI library. if (Sanitize.needsUbsanRt()) addUbsanRTLinux(getToolChain(), Args, CmdArgs, D.CCCIsCXX(), Sanitize.needsAsanRt() || Sanitize.needsTsanRt() || Sanitize.needsMsanRt() || Sanitize.needsLsanRt()); if (Sanitize.needsAsanRt()) addAsanRTLinux(getToolChain(), Args, CmdArgs); if (Sanitize.needsTsanRt()) addTsanRTLinux(getToolChain(), Args, CmdArgs); if (Sanitize.needsMsanRt()) addMsanRTLinux(getToolChain(), Args, CmdArgs); if (Sanitize.needsLsanRt()) addLsanRTLinux(getToolChain(), Args, CmdArgs); if (Sanitize.needsDfsanRt()) addDfsanRTLinux(getToolChain(), Args, CmdArgs); // The profile runtime also needs access to system libraries. addProfileRTLinux(getToolChain(), Args, CmdArgs); if (D.CCCIsCXX() && !Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) && !Args.hasArg(options::OPT_static); if (OnlyLibstdcxxStatic) CmdArgs.push_back("-Bstatic"); ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); if (OnlyLibstdcxxStatic) CmdArgs.push_back("-Bdynamic"); CmdArgs.push_back("-lm"); } if (!Args.hasArg(options::OPT_nostdlib)) { if (!Args.hasArg(options::OPT_nodefaultlibs)) { if (Args.hasArg(options::OPT_static)) CmdArgs.push_back("--start-group"); bool OpenMP = Args.hasArg(options::OPT_fopenmp); if (OpenMP) { CmdArgs.push_back("-lgomp"); // FIXME: Exclude this for platforms whith libgomp that doesn't require // librt. Most modern Linux platfroms require it, but some may not. CmdArgs.push_back("-lrt"); } AddLibgcc(ToolChain.getTriple(), D, CmdArgs, Args); if (Args.hasArg(options::OPT_pthread) || Args.hasArg(options::OPT_pthreads) || OpenMP) CmdArgs.push_back("-lpthread"); CmdArgs.push_back("-lc"); if (Args.hasArg(options::OPT_static)) CmdArgs.push_back("--end-group"); else AddLibgcc(ToolChain.getTriple(), D, CmdArgs, Args); } if (!Args.hasArg(options::OPT_nostartfiles)) { const char *crtend; if (Args.hasArg(options::OPT_shared)) crtend = isAndroid ? "crtend_so.o" : "crtendS.o"; else if (IsPIE) crtend = isAndroid ? "crtend_android.o" : "crtendS.o"; else crtend = isAndroid ? "crtend_android.o" : "crtend.o"; CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend))); if (!isAndroid) CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o"))); } } C.addCommand(new Command(JA, *this, ToolChain.Linker.c_str(), CmdArgs)); } void minix::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { ArgStringList CmdArgs; Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); for (InputInfoList::const_iterator it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { const InputInfo &II = *it; CmdArgs.push_back(II.getFilename()); } const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } void minix::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { const Driver &D = getToolChain().getDriver(); ArgStringList CmdArgs; if (Output.isFilename()) { CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); } else { assert(Output.isNothing() && "Invalid output."); } if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crt1.o"))); CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crti.o"))); CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o"))); CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o"))); } Args.AddAllArgs(CmdArgs, options::OPT_L); Args.AddAllArgs(CmdArgs, options::OPT_T_Group); Args.AddAllArgs(CmdArgs, options::OPT_e); AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { if (D.CCCIsCXX()) { getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); CmdArgs.push_back("-lm"); } } if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { if (Args.hasArg(options::OPT_pthread)) CmdArgs.push_back("-lpthread"); CmdArgs.push_back("-lc"); CmdArgs.push_back("-lCompilerRT-Generic"); CmdArgs.push_back("-L/usr/pkg/compiler-rt/lib"); CmdArgs.push_back( Args.MakeArgString(getToolChain().GetFilePath("crtend.o"))); } const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } /// DragonFly Tools // For now, DragonFly Assemble does just about the same as for // FreeBSD, but this may change soon. void dragonfly::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { ArgStringList CmdArgs; // When building 32-bit code on DragonFly/pc64, we have to explicitly // instruct as in the base system to assemble 32-bit code. if (getToolChain().getArch() == llvm::Triple::x86) CmdArgs.push_back("--32"); Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); for (InputInfoList::const_iterator it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { const InputInfo &II = *it; CmdArgs.push_back(II.getFilename()); } const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { bool UseGCC47 = false; const Driver &D = getToolChain().getDriver(); ArgStringList CmdArgs; if (llvm::sys::fs::exists("/usr/lib/gcc47", UseGCC47)) UseGCC47 = false; if (!D.SysRoot.empty()) CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); CmdArgs.push_back("--eh-frame-hdr"); if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-Bstatic"); } else { if (Args.hasArg(options::OPT_rdynamic)) CmdArgs.push_back("-export-dynamic"); if (Args.hasArg(options::OPT_shared)) CmdArgs.push_back("-Bshareable"); else { CmdArgs.push_back("-dynamic-linker"); CmdArgs.push_back("/usr/libexec/ld-elf.so.2"); } CmdArgs.push_back("--hash-style=both"); } // When building 32-bit code on DragonFly/pc64, we have to explicitly // instruct ld in the base system to link 32-bit code. if (getToolChain().getArch() == llvm::Triple::x86) { CmdArgs.push_back("-m"); CmdArgs.push_back("elf_i386"); } if (Output.isFilename()) { CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); } else { assert(Output.isNothing() && "Invalid output."); } if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { if (!Args.hasArg(options::OPT_shared)) { if (Args.hasArg(options::OPT_pg)) CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("gcrt1.o"))); else { if (Args.hasArg(options::OPT_pie)) CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("Scrt1.o"))); else CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crt1.o"))); } } CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crti.o"))); if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crtbeginS.o"))); else CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crtbegin.o"))); } Args.AddAllArgs(CmdArgs, options::OPT_L); Args.AddAllArgs(CmdArgs, options::OPT_T_Group); Args.AddAllArgs(CmdArgs, options::OPT_e); AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { // FIXME: GCC passes on -lgcc, -lgcc_pic and a whole lot of // rpaths if (UseGCC47) CmdArgs.push_back("-L/usr/lib/gcc47"); else CmdArgs.push_back("-L/usr/lib/gcc44"); if (!Args.hasArg(options::OPT_static)) { if (UseGCC47) { CmdArgs.push_back("-rpath"); CmdArgs.push_back("/usr/lib/gcc47"); } else { CmdArgs.push_back("-rpath"); CmdArgs.push_back("/usr/lib/gcc44"); } } if (D.CCCIsCXX()) { getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); CmdArgs.push_back("-lm"); } if (Args.hasArg(options::OPT_pthread)) CmdArgs.push_back("-lpthread"); if (!Args.hasArg(options::OPT_nolibc)) { CmdArgs.push_back("-lc"); } if (UseGCC47) { if (Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_static_libgcc)) { CmdArgs.push_back("-lgcc"); CmdArgs.push_back("-lgcc_eh"); } else { if (Args.hasArg(options::OPT_shared_libgcc)) { CmdArgs.push_back("-lgcc_pic"); if (!Args.hasArg(options::OPT_shared)) CmdArgs.push_back("-lgcc"); } else { CmdArgs.push_back("-lgcc"); CmdArgs.push_back("--as-needed"); CmdArgs.push_back("-lgcc_pic"); CmdArgs.push_back("--no-as-needed"); } } } else { if (Args.hasArg(options::OPT_shared)) { CmdArgs.push_back("-lgcc_pic"); } else { CmdArgs.push_back("-lgcc"); } } } if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crtendS.o"))); else CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crtend.o"))); CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crtn.o"))); } addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { ArgStringList CmdArgs; if (Output.isFilename()) { CmdArgs.push_back(Args.MakeArgString(std::string("-out:") + Output.getFilename())); } else { assert(Output.isNothing() && "Invalid output."); } if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles) && !C.getDriver().IsCLMode()) { CmdArgs.push_back("-defaultlib:libcmt"); } CmdArgs.push_back("-nologo"); bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd); if (DLL) { CmdArgs.push_back(Args.MakeArgString("-dll")); SmallString<128> ImplibName(Output.getFilename()); llvm::sys::path::replace_extension(ImplibName, "lib"); CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") + ImplibName.str())); } if (getToolChain().getSanitizerArgs().needsAsanRt()) { CmdArgs.push_back(Args.MakeArgString("-debug")); CmdArgs.push_back(Args.MakeArgString("-incremental:no")); SmallString<128> LibSanitizer(getToolChain().getDriver().ResourceDir); llvm::sys::path::append(LibSanitizer, "lib", "windows"); if (DLL) { llvm::sys::path::append(LibSanitizer, "clang_rt.asan_dll_thunk-i386.lib"); } else { llvm::sys::path::append(LibSanitizer, "clang_rt.asan-i386.lib"); } // FIXME: Handle 64-bit. CmdArgs.push_back(Args.MakeArgString(LibSanitizer)); } Args.AddAllArgValues(CmdArgs, options::OPT_l); Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link); // Add filenames immediately. for (InputInfoList::const_iterator it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { if (it->isFilename()) CmdArgs.push_back(it->getFilename()); else it->getInputArg().renderAsInput(Args, CmdArgs); } const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("link.exe")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } void visualstudio::Compile::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { C.addCommand(GetCommand(C, JA, Output, Inputs, Args, LinkingOutput)); } // Try to find FallbackName on PATH that is not identical to ClangProgramPath. // If one cannot be found, return FallbackName. // We do this special search to prevent clang-cl from falling back onto itself // if it's available as cl.exe on the path. static std::string FindFallback(const char *FallbackName, const char *ClangProgramPath) { llvm::Optional OptPath = llvm::sys::Process::GetEnv("PATH"); if (!OptPath.hasValue()) return FallbackName; #ifdef LLVM_ON_WIN32 const StringRef PathSeparators = ";"; #else const StringRef PathSeparators = ":"; #endif SmallVector PathSegments; llvm::SplitString(OptPath.getValue(), PathSegments, PathSeparators); for (size_t i = 0, e = PathSegments.size(); i != e; ++i) { const StringRef &PathSegment = PathSegments[i]; if (PathSegment.empty()) continue; SmallString<128> FilePath(PathSegment); llvm::sys::path::append(FilePath, FallbackName); if (llvm::sys::fs::can_execute(Twine(FilePath)) && !llvm::sys::fs::equivalent(Twine(FilePath), ClangProgramPath)) return FilePath.str(); } return FallbackName; } Command *visualstudio::Compile::GetCommand(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { ArgStringList CmdArgs; CmdArgs.push_back("/nologo"); CmdArgs.push_back("/c"); // Compile only. CmdArgs.push_back("/W0"); // No warnings. // The goal is to be able to invoke this tool correctly based on // any flag accepted by clang-cl. // These are spelled the same way in clang and cl.exe,. Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U); Args.AddAllArgs(CmdArgs, options::OPT_I); // Optimization level. if (Arg *A = Args.getLastArg(options::OPT_O, options::OPT_O0)) { if (A->getOption().getID() == options::OPT_O0) { CmdArgs.push_back("/Od"); } else { StringRef OptLevel = A->getValue(); if (OptLevel == "1" || OptLevel == "2" || OptLevel == "s") A->render(Args, CmdArgs); else if (OptLevel == "3") CmdArgs.push_back("/Ox"); } } // Flags for which clang-cl have an alias. // FIXME: How can we ensure this stays in sync with relevant clang-cl options? if (Arg *A = Args.getLastArg(options::OPT_frtti, options::OPT_fno_rtti)) CmdArgs.push_back(A->getOption().getID() == options::OPT_frtti ? "/GR" : "/GR-"); if (Args.hasArg(options::OPT_fsyntax_only)) CmdArgs.push_back("/Zs"); std::vector Includes = Args.getAllArgValues(options::OPT_include); for (size_t I = 0, E = Includes.size(); I != E; ++I) CmdArgs.push_back(Args.MakeArgString(std::string("/FI") + Includes[I])); // Flags that can simply be passed through. Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LD); Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LDd); // The order of these flags is relevant, so pick the last one. if (Arg *A = Args.getLastArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd, options::OPT__SLASH_MT, options::OPT__SLASH_MTd)) A->render(Args, CmdArgs); // Input filename. assert(Inputs.size() == 1); const InputInfo &II = Inputs[0]; assert(II.getType() == types::TY_C || II.getType() == types::TY_CXX); CmdArgs.push_back(II.getType() == types::TY_C ? "/Tc" : "/Tp"); if (II.isFilename()) CmdArgs.push_back(II.getFilename()); else II.getInputArg().renderAsInput(Args, CmdArgs); // Output filename. assert(Output.getType() == types::TY_Object); const char *Fo = Args.MakeArgString(std::string("/Fo") + Output.getFilename()); CmdArgs.push_back(Fo); const Driver &D = getToolChain().getDriver(); std::string Exec = FindFallback("cl.exe", D.getClangProgramPath()); return new Command(JA, *this, Args.MakeArgString(Exec), CmdArgs); } /// XCore Tools // We pass assemble and link construction to the xcc tool. void XCore::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { ArgStringList CmdArgs; CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); CmdArgs.push_back("-c"); if (Args.hasArg(options::OPT_g_Group)) { CmdArgs.push_back("-g"); } Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); for (InputInfoList::const_iterator it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { const InputInfo &II = *it; CmdArgs.push_back(II.getFilename()); } const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } void XCore::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { ArgStringList CmdArgs; if (Output.isFilename()) { CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); } else { assert(Output.isNothing() && "Invalid output."); } AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } Index: stable/9/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp =================================================================== --- stable/9/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp (revision 283018) +++ stable/9/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp (revision 283019) @@ -1,1829 +1,1835 @@ //===--- CompilerInvocation.cpp -------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "clang/Frontend/CompilerInvocation.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/Version.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" #include "clang/Driver/Util.h" #include "clang/Frontend/LangStandard.h" #include "clang/Frontend/Utils.h" #include "clang/Lex/HeaderSearchOptions.h" #include "clang/Serialization/ASTReader.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/OptTable.h" #include "llvm/Option/Option.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" #include "llvm/Support/system_error.h" #include using namespace clang; //===----------------------------------------------------------------------===// // Initialization. //===----------------------------------------------------------------------===// CompilerInvocationBase::CompilerInvocationBase() : LangOpts(new LangOptions()), TargetOpts(new TargetOptions()), DiagnosticOpts(new DiagnosticOptions()), HeaderSearchOpts(new HeaderSearchOptions()), PreprocessorOpts(new PreprocessorOptions()) {} CompilerInvocationBase::CompilerInvocationBase(const CompilerInvocationBase &X) : RefCountedBase(), LangOpts(new LangOptions(*X.getLangOpts())), TargetOpts(new TargetOptions(X.getTargetOpts())), DiagnosticOpts(new DiagnosticOptions(X.getDiagnosticOpts())), HeaderSearchOpts(new HeaderSearchOptions(X.getHeaderSearchOpts())), PreprocessorOpts(new PreprocessorOptions(X.getPreprocessorOpts())) {} //===----------------------------------------------------------------------===// // Deserialization (from args) //===----------------------------------------------------------------------===// using namespace clang::driver; using namespace clang::driver::options; using namespace llvm::opt; // static unsigned getOptimizationLevel(ArgList &Args, InputKind IK, DiagnosticsEngine &Diags) { unsigned DefaultOpt = 0; if (IK == IK_OpenCL && !Args.hasArg(OPT_cl_opt_disable)) DefaultOpt = 2; if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { if (A->getOption().matches(options::OPT_O0)) return 0; if (A->getOption().matches(options::OPT_Ofast)) return 3; assert (A->getOption().matches(options::OPT_O)); StringRef S(A->getValue()); if (S == "s" || S == "z" || S.empty()) return 2; return getLastArgIntValue(Args, OPT_O, DefaultOpt, Diags); } return DefaultOpt; } static unsigned getOptimizationLevelSize(ArgList &Args) { if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { if (A->getOption().matches(options::OPT_O)) { switch (A->getValue()[0]) { default: return 0; case 's': return 1; case 'z': return 2; } } } return 0; } static void addWarningArgs(ArgList &Args, std::vector &Warnings) { for (arg_iterator I = Args.filtered_begin(OPT_W_Group), E = Args.filtered_end(); I != E; ++I) { Arg *A = *I; // If the argument is a pure flag, add its name (minus the "W" at the beginning) // to the warning list. Else, add its value (for the OPT_W case). if (A->getOption().getKind() == Option::FlagClass) { Warnings.push_back(A->getOption().getName().substr(1)); } else { for (unsigned Idx = 0, End = A->getNumValues(); Idx < End; ++Idx) { StringRef V = A->getValue(Idx); // "-Wl," and such are not warning options. // FIXME: Should be handled by putting these in separate flags. if (V.startswith("l,") || V.startswith("a,") || V.startswith("p,")) continue; Warnings.push_back(V); } } } } static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, DiagnosticsEngine &Diags) { using namespace options; bool Success = true; if (Arg *A = Args.getLastArg(OPT_analyzer_store)) { StringRef Name = A->getValue(); AnalysisStores Value = llvm::StringSwitch(Name) #define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) \ .Case(CMDFLAG, NAME##Model) #include "clang/StaticAnalyzer/Core/Analyses.def" .Default(NumStores); if (Value == NumStores) { Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name; Success = false; } else { Opts.AnalysisStoreOpt = Value; } } if (Arg *A = Args.getLastArg(OPT_analyzer_constraints)) { StringRef Name = A->getValue(); AnalysisConstraints Value = llvm::StringSwitch(Name) #define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \ .Case(CMDFLAG, NAME##Model) #include "clang/StaticAnalyzer/Core/Analyses.def" .Default(NumConstraints); if (Value == NumConstraints) { Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name; Success = false; } else { Opts.AnalysisConstraintsOpt = Value; } } if (Arg *A = Args.getLastArg(OPT_analyzer_output)) { StringRef Name = A->getValue(); AnalysisDiagClients Value = llvm::StringSwitch(Name) #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) \ .Case(CMDFLAG, PD_##NAME) #include "clang/StaticAnalyzer/Core/Analyses.def" .Default(NUM_ANALYSIS_DIAG_CLIENTS); if (Value == NUM_ANALYSIS_DIAG_CLIENTS) { Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name; Success = false; } else { Opts.AnalysisDiagOpt = Value; } } if (Arg *A = Args.getLastArg(OPT_analyzer_purge)) { StringRef Name = A->getValue(); AnalysisPurgeMode Value = llvm::StringSwitch(Name) #define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) \ .Case(CMDFLAG, NAME) #include "clang/StaticAnalyzer/Core/Analyses.def" .Default(NumPurgeModes); if (Value == NumPurgeModes) { Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name; Success = false; } else { Opts.AnalysisPurgeOpt = Value; } } if (Arg *A = Args.getLastArg(OPT_analyzer_inlining_mode)) { StringRef Name = A->getValue(); AnalysisInliningMode Value = llvm::StringSwitch(Name) #define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) \ .Case(CMDFLAG, NAME) #include "clang/StaticAnalyzer/Core/Analyses.def" .Default(NumInliningModes); if (Value == NumInliningModes) { Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name; Success = false; } else { Opts.InliningMode = Value; } } Opts.ShowCheckerHelp = Args.hasArg(OPT_analyzer_checker_help); Opts.visualizeExplodedGraphWithGraphViz = Args.hasArg(OPT_analyzer_viz_egraph_graphviz); Opts.visualizeExplodedGraphWithUbiGraph = Args.hasArg(OPT_analyzer_viz_egraph_ubigraph); Opts.NoRetryExhausted = Args.hasArg(OPT_analyzer_disable_retry_exhausted); Opts.AnalyzeAll = Args.hasArg(OPT_analyzer_opt_analyze_headers); Opts.AnalyzerDisplayProgress = Args.hasArg(OPT_analyzer_display_progress); Opts.AnalyzeNestedBlocks = Args.hasArg(OPT_analyzer_opt_analyze_nested_blocks); Opts.eagerlyAssumeBinOpBifurcation = Args.hasArg(OPT_analyzer_eagerly_assume); Opts.AnalyzeSpecificFunction = Args.getLastArgValue(OPT_analyze_function); Opts.UnoptimizedCFG = Args.hasArg(OPT_analysis_UnoptimizedCFG); Opts.TrimGraph = Args.hasArg(OPT_trim_egraph); Opts.maxBlockVisitOnPath = getLastArgIntValue(Args, OPT_analyzer_max_loop, 4, Diags); Opts.PrintStats = Args.hasArg(OPT_analyzer_stats); Opts.InlineMaxStackDepth = getLastArgIntValue(Args, OPT_analyzer_inline_max_stack_depth, Opts.InlineMaxStackDepth, Diags); Opts.CheckersControlList.clear(); for (arg_iterator it = Args.filtered_begin(OPT_analyzer_checker, OPT_analyzer_disable_checker), ie = Args.filtered_end(); it != ie; ++it) { const Arg *A = *it; A->claim(); bool enable = (A->getOption().getID() == OPT_analyzer_checker); // We can have a list of comma separated checker names, e.g: // '-analyzer-checker=cocoa,unix' StringRef checkerList = A->getValue(); SmallVector checkers; checkerList.split(checkers, ","); for (unsigned i = 0, e = checkers.size(); i != e; ++i) Opts.CheckersControlList.push_back(std::make_pair(checkers[i], enable)); } // Go through the analyzer configuration options. for (arg_iterator it = Args.filtered_begin(OPT_analyzer_config), ie = Args.filtered_end(); it != ie; ++it) { const Arg *A = *it; A->claim(); // We can have a list of comma separated config names, e.g: // '-analyzer-config key1=val1,key2=val2' StringRef configList = A->getValue(); SmallVector configVals; configList.split(configVals, ","); for (unsigned i = 0, e = configVals.size(); i != e; ++i) { StringRef key, val; llvm::tie(key, val) = configVals[i].split("="); if (val.empty()) { Diags.Report(SourceLocation(), diag::err_analyzer_config_no_value) << configVals[i]; Success = false; break; } if (val.find('=') != StringRef::npos) { Diags.Report(SourceLocation(), diag::err_analyzer_config_multiple_values) << configVals[i]; Success = false; break; } Opts.Config[key] = val; } } return Success; } static bool ParseMigratorArgs(MigratorOptions &Opts, ArgList &Args) { Opts.NoNSAllocReallocError = Args.hasArg(OPT_migrator_no_nsalloc_error); Opts.NoFinalizeRemoval = Args.hasArg(OPT_migrator_no_finalize_removal); return true; } static void ParseCommentArgs(CommentOptions &Opts, ArgList &Args) { Opts.BlockCommandNames = Args.getAllArgValues(OPT_fcomment_block_commands); Opts.ParseAllComments = Args.hasArg(OPT_fparse_all_comments); } static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, - DiagnosticsEngine &Diags) { + DiagnosticsEngine &Diags, + const TargetOptions &TargetOpts) { using namespace options; bool Success = true; Opts.OptimizationLevel = getOptimizationLevel(Args, IK, Diags); // TODO: This could be done in Driver unsigned MaxOptLevel = 3; if (Opts.OptimizationLevel > MaxOptLevel) { // If the optimization level is not supported, fall back on the default optimization Diags.Report(diag::warn_drv_optimization_value) << Args.getLastArg(OPT_O)->getAsString(Args) << "-O" << MaxOptLevel; Opts.OptimizationLevel = MaxOptLevel; } // We must always run at least the always inlining pass. Opts.setInlining( (Opts.OptimizationLevel > 1) ? CodeGenOptions::NormalInlining : CodeGenOptions::OnlyAlwaysInlining); // -fno-inline-functions overrides OptimizationLevel > 1. Opts.NoInline = Args.hasArg(OPT_fno_inline); Opts.setInlining(Args.hasArg(OPT_fno_inline_functions) ? CodeGenOptions::OnlyAlwaysInlining : Opts.getInlining()); if (Args.hasArg(OPT_gline_tables_only)) { Opts.setDebugInfo(CodeGenOptions::DebugLineTablesOnly); } else if (Args.hasArg(OPT_g_Flag) || Args.hasArg(OPT_gdwarf_2) || Args.hasArg(OPT_gdwarf_3) || Args.hasArg(OPT_gdwarf_4)) { - if (Args.hasFlag(OPT_flimit_debug_info, OPT_fno_limit_debug_info, true)) - Opts.setDebugInfo(CodeGenOptions::LimitedDebugInfo); - else + bool Default = false; + // Until dtrace (via CTF) can deal with distributed debug info, + // Darwin defaults to standalone/full debug info. + if (llvm::Triple(TargetOpts.Triple).isOSDarwin()) + Default = true; + + if (Args.hasFlag(OPT_fstandalone_debug, OPT_fno_standalone_debug, Default)) Opts.setDebugInfo(CodeGenOptions::FullDebugInfo); + else + Opts.setDebugInfo(CodeGenOptions::LimitedDebugInfo); } Opts.DebugColumnInfo = Args.hasArg(OPT_dwarf_column_info); Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file); if (Args.hasArg(OPT_gdwarf_2)) Opts.DwarfVersion = 2; else if (Args.hasArg(OPT_gdwarf_3)) Opts.DwarfVersion = 3; else if (Args.hasArg(OPT_gdwarf_4)) Opts.DwarfVersion = 4; else if (Opts.getDebugInfo() != CodeGenOptions::NoDebugInfo) // Default Dwarf version is 4 if we are generating debug information. Opts.DwarfVersion = 4; Opts.DisableLLVMOpts = Args.hasArg(OPT_disable_llvm_optzns); Opts.DisableRedZone = Args.hasArg(OPT_disable_red_zone); Opts.ForbidGuardVariables = Args.hasArg(OPT_fforbid_guard_variables); Opts.UseRegisterSizedBitfieldAccess = Args.hasArg( OPT_fuse_register_sized_bitfield_access); Opts.RelaxedAliasing = Args.hasArg(OPT_relaxed_aliasing); Opts.StructPathTBAA = !Args.hasArg(OPT_no_struct_path_tbaa); Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags); Opts.MergeAllConstants = !Args.hasArg(OPT_fno_merge_all_constants); Opts.NoCommon = Args.hasArg(OPT_fno_common); Opts.NoImplicitFloat = Args.hasArg(OPT_no_implicit_float); Opts.OptimizeSize = getOptimizationLevelSize(Args); Opts.SimplifyLibCalls = !(Args.hasArg(OPT_fno_builtin) || Args.hasArg(OPT_ffreestanding)); Opts.UnrollLoops = Args.hasFlag(OPT_funroll_loops, OPT_fno_unroll_loops, (Opts.OptimizationLevel > 1 && !Opts.OptimizeSize)); Opts.RerollLoops = Args.hasArg(OPT_freroll_loops); Opts.Autolink = !Args.hasArg(OPT_fno_autolink); Opts.SampleProfileFile = Args.getLastArgValue(OPT_fprofile_sample_use_EQ); Opts.AsmVerbose = Args.hasArg(OPT_masm_verbose); Opts.ObjCAutoRefCountExceptions = Args.hasArg(OPT_fobjc_arc_exceptions); Opts.CUDAIsDevice = Args.hasArg(OPT_fcuda_is_device); Opts.CXAAtExit = !Args.hasArg(OPT_fno_use_cxa_atexit); Opts.CXXCtorDtorAliases = Args.hasArg(OPT_mconstructor_aliases); Opts.CodeModel = Args.getLastArgValue(OPT_mcode_model); Opts.DebugPass = Args.getLastArgValue(OPT_mdebug_pass); Opts.DisableFPElim = Args.hasArg(OPT_mdisable_fp_elim); Opts.DisableFree = Args.hasArg(OPT_disable_free); Opts.DisableTailCalls = Args.hasArg(OPT_mdisable_tail_calls); Opts.FloatABI = Args.getLastArgValue(OPT_mfloat_abi); Opts.HiddenWeakVTables = Args.hasArg(OPT_fhidden_weak_vtables); Opts.LessPreciseFPMAD = Args.hasArg(OPT_cl_mad_enable); Opts.LimitFloatPrecision = Args.getLastArgValue(OPT_mlimit_float_precision); Opts.NoInfsFPMath = (Args.hasArg(OPT_menable_no_infinities) || Args.hasArg(OPT_cl_finite_math_only)|| Args.hasArg(OPT_cl_fast_relaxed_math)); Opts.NoNaNsFPMath = (Args.hasArg(OPT_menable_no_nans) || Args.hasArg(OPT_cl_finite_math_only)|| Args.hasArg(OPT_cl_fast_relaxed_math)); Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss); Opts.BackendOptions = Args.getAllArgValues(OPT_backend_option); Opts.NumRegisterParameters = getLastArgIntValue(Args, OPT_mregparm, 0, Diags); Opts.NoGlobalMerge = Args.hasArg(OPT_mno_global_merge); Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack); Opts.EnableSegmentedStacks = Args.hasArg(OPT_split_stacks); Opts.RelaxAll = Args.hasArg(OPT_mrelax_all); Opts.OmitLeafFramePointer = Args.hasArg(OPT_momit_leaf_frame_pointer); Opts.SaveTempLabels = Args.hasArg(OPT_msave_temp_labels); Opts.NoDwarf2CFIAsm = Args.hasArg(OPT_fno_dwarf2_cfi_asm); Opts.NoDwarfDirectoryAsm = Args.hasArg(OPT_fno_dwarf_directory_asm); Opts.SoftFloat = Args.hasArg(OPT_msoft_float); Opts.StrictEnums = Args.hasArg(OPT_fstrict_enums); Opts.UnsafeFPMath = Args.hasArg(OPT_menable_unsafe_fp_math) || Args.hasArg(OPT_cl_unsafe_math_optimizations) || Args.hasArg(OPT_cl_fast_relaxed_math); Opts.UnwindTables = Args.hasArg(OPT_munwind_tables); Opts.RelocationModel = Args.getLastArgValue(OPT_mrelocation_model, "pic"); Opts.TrapFuncName = Args.getLastArgValue(OPT_ftrap_function_EQ); Opts.UseInitArray = Args.hasArg(OPT_fuse_init_array); Opts.FunctionSections = Args.hasFlag(OPT_ffunction_sections, OPT_fno_function_sections, false); Opts.DataSections = Args.hasFlag(OPT_fdata_sections, OPT_fno_data_sections, false); Opts.VectorizeBB = Args.hasArg(OPT_vectorize_slp_aggressive); Opts.VectorizeLoop = Args.hasArg(OPT_vectorize_loops); Opts.VectorizeSLP = Args.hasArg(OPT_vectorize_slp); Opts.MainFileName = Args.getLastArgValue(OPT_main_file_name); Opts.VerifyModule = !Args.hasArg(OPT_disable_llvm_verifier); Opts.SanitizeRecover = !Args.hasArg(OPT_fno_sanitize_recover); Opts.DisableGCov = Args.hasArg(OPT_test_coverage); Opts.EmitGcovArcs = Args.hasArg(OPT_femit_coverage_data); Opts.EmitGcovNotes = Args.hasArg(OPT_femit_coverage_notes); if (Opts.EmitGcovArcs || Opts.EmitGcovNotes) { Opts.CoverageFile = Args.getLastArgValue(OPT_coverage_file); Opts.CoverageExtraChecksum = Args.hasArg(OPT_coverage_cfg_checksum); Opts.CoverageNoFunctionNamesInData = Args.hasArg(OPT_coverage_no_function_names_in_data); if (Args.hasArg(OPT_coverage_version_EQ)) { StringRef CoverageVersion = Args.getLastArgValue(OPT_coverage_version_EQ); if (CoverageVersion.size() != 4) { Diags.Report(diag::err_drv_invalid_value) << Args.getLastArg(OPT_coverage_version_EQ)->getAsString(Args) << CoverageVersion; } else { memcpy(Opts.CoverageVersion, CoverageVersion.data(), 4); } } } Opts.InstrumentFunctions = Args.hasArg(OPT_finstrument_functions); Opts.InstrumentForProfiling = Args.hasArg(OPT_pg); Opts.EmitOpenCLArgMetadata = Args.hasArg(OPT_cl_kernel_arg_info); Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir); Opts.LinkBitcodeFile = Args.getLastArgValue(OPT_mlink_bitcode_file); Opts.SanitizerBlacklistFile = Args.getLastArgValue(OPT_fsanitize_blacklist); Opts.SanitizeMemoryTrackOrigins = Args.hasArg(OPT_fsanitize_memory_track_origins); Opts.SanitizeAddressZeroBaseShadow = Args.hasArg(OPT_fsanitize_address_zero_base_shadow); Opts.SanitizeUndefinedTrapOnError = Args.hasArg(OPT_fsanitize_undefined_trap_on_error); Opts.SSPBufferSize = getLastArgIntValue(Args, OPT_stack_protector_buffer_size, 8, Diags); Opts.StackRealignment = Args.hasArg(OPT_mstackrealign); if (Arg *A = Args.getLastArg(OPT_mstack_alignment)) { StringRef Val = A->getValue(); unsigned StackAlignment = Opts.StackAlignment; Val.getAsInteger(10, StackAlignment); Opts.StackAlignment = StackAlignment; } if (Arg *A = Args.getLastArg(OPT_fobjc_dispatch_method_EQ)) { StringRef Name = A->getValue(); unsigned Method = llvm::StringSwitch(Name) .Case("legacy", CodeGenOptions::Legacy) .Case("non-legacy", CodeGenOptions::NonLegacy) .Case("mixed", CodeGenOptions::Mixed) .Default(~0U); if (Method == ~0U) { Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name; Success = false; } else { Opts.setObjCDispatchMethod( static_cast(Method)); } } if (Arg *A = Args.getLastArg(OPT_ftlsmodel_EQ)) { StringRef Name = A->getValue(); unsigned Model = llvm::StringSwitch(Name) .Case("global-dynamic", CodeGenOptions::GeneralDynamicTLSModel) .Case("local-dynamic", CodeGenOptions::LocalDynamicTLSModel) .Case("initial-exec", CodeGenOptions::InitialExecTLSModel) .Case("local-exec", CodeGenOptions::LocalExecTLSModel) .Default(~0U); if (Model == ~0U) { Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name; Success = false; } else { Opts.setDefaultTLSModel(static_cast(Model)); } } if (Arg *A = Args.getLastArg(OPT_ffp_contract)) { StringRef Val = A->getValue(); if (Val == "fast") Opts.setFPContractMode(CodeGenOptions::FPC_Fast); else if (Val == "on") Opts.setFPContractMode(CodeGenOptions::FPC_On); else if (Val == "off") Opts.setFPContractMode(CodeGenOptions::FPC_Off); else Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val; } if (Arg *A = Args.getLastArg(OPT_fpcc_struct_return, OPT_freg_struct_return)) { if (A->getOption().matches(OPT_fpcc_struct_return)) { Opts.setStructReturnConvention(CodeGenOptions::SRCK_OnStack); } else { assert(A->getOption().matches(OPT_freg_struct_return)); Opts.setStructReturnConvention(CodeGenOptions::SRCK_InRegs); } } Opts.DependentLibraries = Args.getAllArgValues(OPT_dependent_lib); return Success; } static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts, ArgList &Args) { using namespace options; Opts.OutputFile = Args.getLastArgValue(OPT_dependency_file); Opts.Targets = Args.getAllArgValues(OPT_MT); Opts.IncludeSystemHeaders = Args.hasArg(OPT_sys_header_deps); Opts.UsePhonyTargets = Args.hasArg(OPT_MP); Opts.ShowHeaderIncludes = Args.hasArg(OPT_H); Opts.HeaderIncludeOutputFile = Args.getLastArgValue(OPT_header_include_file); Opts.AddMissingHeaderDeps = Args.hasArg(OPT_MG); Opts.PrintShowIncludes = Args.hasArg(OPT_show_includes); Opts.DOTOutputFile = Args.getLastArgValue(OPT_dependency_dot); } bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, DiagnosticsEngine *Diags) { using namespace options; bool Success = true; Opts.DiagnosticLogFile = Args.getLastArgValue(OPT_diagnostic_log_file); Opts.DiagnosticSerializationFile = Args.getLastArgValue(OPT_diagnostic_serialized_file); Opts.IgnoreWarnings = Args.hasArg(OPT_w); Opts.NoRewriteMacros = Args.hasArg(OPT_Wno_rewrite_macros); Opts.Pedantic = Args.hasArg(OPT_pedantic); Opts.PedanticErrors = Args.hasArg(OPT_pedantic_errors); Opts.ShowCarets = !Args.hasArg(OPT_fno_caret_diagnostics); Opts.ShowColors = Args.hasArg(OPT_fcolor_diagnostics); Opts.ShowColumn = Args.hasFlag(OPT_fshow_column, OPT_fno_show_column, /*Default=*/true); Opts.ShowFixits = !Args.hasArg(OPT_fno_diagnostics_fixit_info); Opts.ShowLocation = !Args.hasArg(OPT_fno_show_source_location); Opts.ShowOptionNames = Args.hasArg(OPT_fdiagnostics_show_option); llvm::sys::Process::UseANSIEscapeCodes(Args.hasArg(OPT_fansi_escape_codes)); // Default behavior is to not to show note include stacks. Opts.ShowNoteIncludeStack = false; if (Arg *A = Args.getLastArg(OPT_fdiagnostics_show_note_include_stack, OPT_fno_diagnostics_show_note_include_stack)) if (A->getOption().matches(OPT_fdiagnostics_show_note_include_stack)) Opts.ShowNoteIncludeStack = true; StringRef ShowOverloads = Args.getLastArgValue(OPT_fshow_overloads_EQ, "all"); if (ShowOverloads == "best") Opts.setShowOverloads(Ovl_Best); else if (ShowOverloads == "all") Opts.setShowOverloads(Ovl_All); else { Success = false; if (Diags) Diags->Report(diag::err_drv_invalid_value) << Args.getLastArg(OPT_fshow_overloads_EQ)->getAsString(Args) << ShowOverloads; } StringRef ShowCategory = Args.getLastArgValue(OPT_fdiagnostics_show_category, "none"); if (ShowCategory == "none") Opts.ShowCategories = 0; else if (ShowCategory == "id") Opts.ShowCategories = 1; else if (ShowCategory == "name") Opts.ShowCategories = 2; else { Success = false; if (Diags) Diags->Report(diag::err_drv_invalid_value) << Args.getLastArg(OPT_fdiagnostics_show_category)->getAsString(Args) << ShowCategory; } StringRef Format = Args.getLastArgValue(OPT_fdiagnostics_format, "clang"); if (Format == "clang") Opts.setFormat(DiagnosticOptions::Clang); else if (Format == "msvc") Opts.setFormat(DiagnosticOptions::Msvc); else if (Format == "msvc-fallback") { Opts.setFormat(DiagnosticOptions::Msvc); Opts.CLFallbackMode = true; } else if (Format == "vi") Opts.setFormat(DiagnosticOptions::Vi); else { Success = false; if (Diags) Diags->Report(diag::err_drv_invalid_value) << Args.getLastArg(OPT_fdiagnostics_format)->getAsString(Args) << Format; } Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info); Opts.ShowParseableFixits = Args.hasArg(OPT_fdiagnostics_parseable_fixits); Opts.ShowPresumedLoc = !Args.hasArg(OPT_fno_diagnostics_use_presumed_location); Opts.VerifyDiagnostics = Args.hasArg(OPT_verify); Opts.ElideType = !Args.hasArg(OPT_fno_elide_type); Opts.ShowTemplateTree = Args.hasArg(OPT_fdiagnostics_show_template_tree); Opts.ErrorLimit = getLastArgIntValue(Args, OPT_ferror_limit, 0, Diags); Opts.MacroBacktraceLimit = getLastArgIntValue(Args, OPT_fmacro_backtrace_limit, DiagnosticOptions::DefaultMacroBacktraceLimit, Diags); Opts.TemplateBacktraceLimit = getLastArgIntValue( Args, OPT_ftemplate_backtrace_limit, DiagnosticOptions::DefaultTemplateBacktraceLimit, Diags); Opts.ConstexprBacktraceLimit = getLastArgIntValue( Args, OPT_fconstexpr_backtrace_limit, DiagnosticOptions::DefaultConstexprBacktraceLimit, Diags); Opts.TabStop = getLastArgIntValue(Args, OPT_ftabstop, DiagnosticOptions::DefaultTabStop, Diags); if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) { Opts.TabStop = DiagnosticOptions::DefaultTabStop; if (Diags) Diags->Report(diag::warn_ignoring_ftabstop_value) << Opts.TabStop << DiagnosticOptions::DefaultTabStop; } Opts.MessageLength = getLastArgIntValue(Args, OPT_fmessage_length, 0, Diags); addWarningArgs(Args, Opts.Warnings); return Success; } static void ParseFileSystemArgs(FileSystemOptions &Opts, ArgList &Args) { Opts.WorkingDir = Args.getLastArgValue(OPT_working_directory); } static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, DiagnosticsEngine &Diags) { using namespace options; Opts.ProgramAction = frontend::ParseSyntaxOnly; if (const Arg *A = Args.getLastArg(OPT_Action_Group)) { switch (A->getOption().getID()) { default: llvm_unreachable("Invalid option in group!"); case OPT_ast_list: Opts.ProgramAction = frontend::ASTDeclList; break; case OPT_ast_dump: Opts.ProgramAction = frontend::ASTDump; break; case OPT_ast_print: Opts.ProgramAction = frontend::ASTPrint; break; case OPT_ast_view: Opts.ProgramAction = frontend::ASTView; break; case OPT_dump_raw_tokens: Opts.ProgramAction = frontend::DumpRawTokens; break; case OPT_dump_tokens: Opts.ProgramAction = frontend::DumpTokens; break; case OPT_S: Opts.ProgramAction = frontend::EmitAssembly; break; case OPT_emit_llvm_bc: Opts.ProgramAction = frontend::EmitBC; break; case OPT_emit_html: Opts.ProgramAction = frontend::EmitHTML; break; case OPT_emit_llvm: Opts.ProgramAction = frontend::EmitLLVM; break; case OPT_emit_llvm_only: Opts.ProgramAction = frontend::EmitLLVMOnly; break; case OPT_emit_codegen_only: Opts.ProgramAction = frontend::EmitCodeGenOnly; break; case OPT_emit_obj: Opts.ProgramAction = frontend::EmitObj; break; case OPT_fixit_EQ: Opts.FixItSuffix = A->getValue(); // fall-through! case OPT_fixit: Opts.ProgramAction = frontend::FixIt; break; case OPT_emit_module: Opts.ProgramAction = frontend::GenerateModule; break; case OPT_emit_pch: Opts.ProgramAction = frontend::GeneratePCH; break; case OPT_emit_pth: Opts.ProgramAction = frontend::GeneratePTH; break; case OPT_init_only: Opts.ProgramAction = frontend::InitOnly; break; case OPT_fsyntax_only: Opts.ProgramAction = frontend::ParseSyntaxOnly; break; case OPT_module_file_info: Opts.ProgramAction = frontend::ModuleFileInfo; break; case OPT_print_decl_contexts: Opts.ProgramAction = frontend::PrintDeclContext; break; case OPT_print_preamble: Opts.ProgramAction = frontend::PrintPreamble; break; case OPT_E: Opts.ProgramAction = frontend::PrintPreprocessedInput; break; case OPT_rewrite_macros: Opts.ProgramAction = frontend::RewriteMacros; break; case OPT_rewrite_objc: Opts.ProgramAction = frontend::RewriteObjC; break; case OPT_rewrite_test: Opts.ProgramAction = frontend::RewriteTest; break; case OPT_analyze: Opts.ProgramAction = frontend::RunAnalysis; break; case OPT_migrate: Opts.ProgramAction = frontend::MigrateSource; break; case OPT_Eonly: Opts.ProgramAction = frontend::RunPreprocessorOnly; break; } } if (const Arg* A = Args.getLastArg(OPT_plugin)) { Opts.Plugins.push_back(A->getValue(0)); Opts.ProgramAction = frontend::PluginAction; Opts.ActionName = A->getValue(); for (arg_iterator it = Args.filtered_begin(OPT_plugin_arg), end = Args.filtered_end(); it != end; ++it) { if ((*it)->getValue(0) == Opts.ActionName) Opts.PluginArgs.push_back((*it)->getValue(1)); } } Opts.AddPluginActions = Args.getAllArgValues(OPT_add_plugin); Opts.AddPluginArgs.resize(Opts.AddPluginActions.size()); for (int i = 0, e = Opts.AddPluginActions.size(); i != e; ++i) { for (arg_iterator it = Args.filtered_begin(OPT_plugin_arg), end = Args.filtered_end(); it != end; ++it) { if ((*it)->getValue(0) == Opts.AddPluginActions[i]) Opts.AddPluginArgs[i].push_back((*it)->getValue(1)); } } if (const Arg *A = Args.getLastArg(OPT_code_completion_at)) { Opts.CodeCompletionAt = ParsedSourceLocation::FromString(A->getValue()); if (Opts.CodeCompletionAt.FileName.empty()) Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << A->getValue(); } Opts.DisableFree = Args.hasArg(OPT_disable_free); Opts.OutputFile = Args.getLastArgValue(OPT_o); Opts.Plugins = Args.getAllArgValues(OPT_load); Opts.RelocatablePCH = Args.hasArg(OPT_relocatable_pch); Opts.ShowHelp = Args.hasArg(OPT_help); Opts.ShowStats = Args.hasArg(OPT_print_stats); Opts.ShowTimers = Args.hasArg(OPT_ftime_report); Opts.ShowVersion = Args.hasArg(OPT_version); Opts.ASTMergeFiles = Args.getAllArgValues(OPT_ast_merge); Opts.LLVMArgs = Args.getAllArgValues(OPT_mllvm); Opts.FixWhatYouCan = Args.hasArg(OPT_fix_what_you_can); Opts.FixOnlyWarnings = Args.hasArg(OPT_fix_only_warnings); Opts.FixAndRecompile = Args.hasArg(OPT_fixit_recompile); Opts.FixToTemporaries = Args.hasArg(OPT_fixit_to_temp); Opts.ASTDumpFilter = Args.getLastArgValue(OPT_ast_dump_filter); Opts.ASTDumpLookups = Args.hasArg(OPT_ast_dump_lookups); Opts.UseGlobalModuleIndex = !Args.hasArg(OPT_fno_modules_global_index); Opts.GenerateGlobalModuleIndex = Opts.UseGlobalModuleIndex; Opts.CodeCompleteOpts.IncludeMacros = Args.hasArg(OPT_code_completion_macros); Opts.CodeCompleteOpts.IncludeCodePatterns = Args.hasArg(OPT_code_completion_patterns); Opts.CodeCompleteOpts.IncludeGlobals = !Args.hasArg(OPT_no_code_completion_globals); Opts.CodeCompleteOpts.IncludeBriefComments = Args.hasArg(OPT_code_completion_brief_comments); Opts.OverrideRecordLayoutsFile = Args.getLastArgValue(OPT_foverride_record_layout_EQ); if (const Arg *A = Args.getLastArg(OPT_arcmt_check, OPT_arcmt_modify, OPT_arcmt_migrate)) { switch (A->getOption().getID()) { default: llvm_unreachable("missed a case"); case OPT_arcmt_check: Opts.ARCMTAction = FrontendOptions::ARCMT_Check; break; case OPT_arcmt_modify: Opts.ARCMTAction = FrontendOptions::ARCMT_Modify; break; case OPT_arcmt_migrate: Opts.ARCMTAction = FrontendOptions::ARCMT_Migrate; break; } } Opts.MTMigrateDir = Args.getLastArgValue(OPT_mt_migrate_directory); Opts.ARCMTMigrateReportOut = Args.getLastArgValue(OPT_arcmt_migrate_report_output); Opts.ARCMTMigrateEmitARCErrors = Args.hasArg(OPT_arcmt_migrate_emit_arc_errors); if (Args.hasArg(OPT_objcmt_migrate_literals)) Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Literals; if (Args.hasArg(OPT_objcmt_migrate_subscripting)) Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Subscripting; if (Args.hasArg(OPT_objcmt_migrate_property)) Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Property; if (Args.hasArg(OPT_objcmt_migrate_readonly_property)) Opts.ObjCMTAction |= FrontendOptions::ObjCMT_ReadonlyProperty; if (Args.hasArg(OPT_objcmt_migrate_readwrite_property)) Opts.ObjCMTAction |= FrontendOptions::ObjCMT_ReadwriteProperty; if (Args.hasArg(OPT_objcmt_migrate_annotation)) Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Annotation; if (Args.hasArg(OPT_objcmt_returns_innerpointer_property)) Opts.ObjCMTAction |= FrontendOptions::ObjCMT_ReturnsInnerPointerProperty; if (Args.hasArg(OPT_objcmt_migrate_instancetype)) Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Instancetype; if (Args.hasArg(OPT_objcmt_migrate_nsmacros)) Opts.ObjCMTAction |= FrontendOptions::ObjCMT_NsMacros; if (Args.hasArg(OPT_objcmt_migrate_protocol_conformance)) Opts.ObjCMTAction |= FrontendOptions::ObjCMT_ProtocolConformance; if (Args.hasArg(OPT_objcmt_atomic_property)) Opts.ObjCMTAction |= FrontendOptions::ObjCMT_AtomicProperty; if (Args.hasArg(OPT_objcmt_ns_nonatomic_iosonly)) Opts.ObjCMTAction |= FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty; if (Args.hasArg(OPT_objcmt_migrate_all)) Opts.ObjCMTAction |= FrontendOptions::ObjCMT_MigrateDecls; Opts.ObjCMTWhiteListPath = Args.getLastArgValue(OPT_objcmt_white_list_dir_path); if (Opts.ARCMTAction != FrontendOptions::ARCMT_None && Opts.ObjCMTAction != FrontendOptions::ObjCMT_None) { Diags.Report(diag::err_drv_argument_not_allowed_with) << "ARC migration" << "ObjC migration"; } InputKind DashX = IK_None; if (const Arg *A = Args.getLastArg(OPT_x)) { DashX = llvm::StringSwitch(A->getValue()) .Case("c", IK_C) .Case("cl", IK_OpenCL) .Case("cuda", IK_CUDA) .Case("c++", IK_CXX) .Case("objective-c", IK_ObjC) .Case("objective-c++", IK_ObjCXX) .Case("cpp-output", IK_PreprocessedC) .Case("assembler-with-cpp", IK_Asm) .Case("c++-cpp-output", IK_PreprocessedCXX) .Case("objective-c-cpp-output", IK_PreprocessedObjC) .Case("objc-cpp-output", IK_PreprocessedObjC) .Case("objective-c++-cpp-output", IK_PreprocessedObjCXX) .Case("objc++-cpp-output", IK_PreprocessedObjCXX) .Case("c-header", IK_C) .Case("cl-header", IK_OpenCL) .Case("objective-c-header", IK_ObjC) .Case("c++-header", IK_CXX) .Case("objective-c++-header", IK_ObjCXX) .Cases("ast", "pcm", IK_AST) .Case("ir", IK_LLVM_IR) .Default(IK_None); if (DashX == IK_None) Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << A->getValue(); } // '-' is the default input if none is given. std::vector Inputs = Args.getAllArgValues(OPT_INPUT); Opts.Inputs.clear(); if (Inputs.empty()) Inputs.push_back("-"); for (unsigned i = 0, e = Inputs.size(); i != e; ++i) { InputKind IK = DashX; if (IK == IK_None) { IK = FrontendOptions::getInputKindForExtension( StringRef(Inputs[i]).rsplit('.').second); // FIXME: Remove this hack. if (i == 0) DashX = IK; } Opts.Inputs.push_back(FrontendInputFile(Inputs[i], IK)); } return DashX; } std::string CompilerInvocation::GetResourcesPath(const char *Argv0, void *MainAddr) { SmallString<128> P(llvm::sys::fs::getMainExecutable(Argv0, MainAddr)); if (!P.empty()) { llvm::sys::path::remove_filename(P); // Remove /clang from foo/bin/clang llvm::sys::path::remove_filename(P); // Remove /bin from foo/bin // Get foo/lib/clang//include llvm::sys::path::append(P, "lib", "clang", CLANG_VERSION_STRING); } return P.str(); } static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) { using namespace options; Opts.Sysroot = Args.getLastArgValue(OPT_isysroot, "/"); Opts.Verbose = Args.hasArg(OPT_v); Opts.UseBuiltinIncludes = !Args.hasArg(OPT_nobuiltininc); Opts.UseStandardSystemIncludes = !Args.hasArg(OPT_nostdsysteminc); Opts.UseStandardCXXIncludes = !Args.hasArg(OPT_nostdincxx); if (const Arg *A = Args.getLastArg(OPT_stdlib_EQ)) Opts.UseLibcxx = (strcmp(A->getValue(), "libc++") == 0); Opts.ResourceDir = Args.getLastArgValue(OPT_resource_dir); Opts.ModuleCachePath = Args.getLastArgValue(OPT_fmodules_cache_path); Opts.DisableModuleHash = Args.hasArg(OPT_fdisable_module_hash); // -fmodules implies -fmodule-maps Opts.ModuleMaps = Args.hasArg(OPT_fmodule_maps) || Args.hasArg(OPT_fmodules); Opts.ModuleCachePruneInterval = getLastArgIntValue(Args, OPT_fmodules_prune_interval, 7 * 24 * 60 * 60); Opts.ModuleCachePruneAfter = getLastArgIntValue(Args, OPT_fmodules_prune_after, 31 * 24 * 60 * 60); for (arg_iterator it = Args.filtered_begin(OPT_fmodules_ignore_macro), ie = Args.filtered_end(); it != ie; ++it) { StringRef MacroDef = (*it)->getValue(); Opts.ModulesIgnoreMacros.insert(MacroDef.split('=').first); } std::vector ModuleMapFiles = Args.getAllArgValues(OPT_fmodule_map_file); Opts.ModuleMapFiles.insert(ModuleMapFiles.begin(), ModuleMapFiles.end()); // Add -I..., -F..., and -index-header-map options in order. bool IsIndexHeaderMap = false; for (arg_iterator it = Args.filtered_begin(OPT_I, OPT_F, OPT_index_header_map), ie = Args.filtered_end(); it != ie; ++it) { if ((*it)->getOption().matches(OPT_index_header_map)) { // -index-header-map applies to the next -I or -F. IsIndexHeaderMap = true; continue; } frontend::IncludeDirGroup Group = IsIndexHeaderMap? frontend::IndexHeaderMap : frontend::Angled; Opts.AddPath((*it)->getValue(), Group, /*IsFramework=*/ (*it)->getOption().matches(OPT_F), true); IsIndexHeaderMap = false; } // Add -iprefix/-iwithprefix/-iwithprefixbefore options. StringRef Prefix = ""; // FIXME: This isn't the correct default prefix. for (arg_iterator it = Args.filtered_begin(OPT_iprefix, OPT_iwithprefix, OPT_iwithprefixbefore), ie = Args.filtered_end(); it != ie; ++it) { const Arg *A = *it; if (A->getOption().matches(OPT_iprefix)) Prefix = A->getValue(); else if (A->getOption().matches(OPT_iwithprefix)) Opts.AddPath(Prefix.str() + A->getValue(), frontend::After, false, true); else Opts.AddPath(Prefix.str() + A->getValue(), frontend::Angled, false, true); } for (arg_iterator it = Args.filtered_begin(OPT_idirafter), ie = Args.filtered_end(); it != ie; ++it) Opts.AddPath((*it)->getValue(), frontend::After, false, true); for (arg_iterator it = Args.filtered_begin(OPT_iquote), ie = Args.filtered_end(); it != ie; ++it) Opts.AddPath((*it)->getValue(), frontend::Quoted, false, true); for (arg_iterator it = Args.filtered_begin(OPT_isystem, OPT_iwithsysroot), ie = Args.filtered_end(); it != ie; ++it) Opts.AddPath((*it)->getValue(), frontend::System, false, !(*it)->getOption().matches(OPT_iwithsysroot)); for (arg_iterator it = Args.filtered_begin(OPT_iframework), ie = Args.filtered_end(); it != ie; ++it) Opts.AddPath((*it)->getValue(), frontend::System, true, true); // Add the paths for the various language specific isystem flags. for (arg_iterator it = Args.filtered_begin(OPT_c_isystem), ie = Args.filtered_end(); it != ie; ++it) Opts.AddPath((*it)->getValue(), frontend::CSystem, false, true); for (arg_iterator it = Args.filtered_begin(OPT_cxx_isystem), ie = Args.filtered_end(); it != ie; ++it) Opts.AddPath((*it)->getValue(), frontend::CXXSystem, false, true); for (arg_iterator it = Args.filtered_begin(OPT_objc_isystem), ie = Args.filtered_end(); it != ie; ++it) Opts.AddPath((*it)->getValue(), frontend::ObjCSystem, false,true); for (arg_iterator it = Args.filtered_begin(OPT_objcxx_isystem), ie = Args.filtered_end(); it != ie; ++it) Opts.AddPath((*it)->getValue(), frontend::ObjCXXSystem, false, true); // Add the internal paths from a driver that detects standard include paths. for (arg_iterator I = Args.filtered_begin(OPT_internal_isystem, OPT_internal_externc_isystem), E = Args.filtered_end(); I != E; ++I) { frontend::IncludeDirGroup Group = frontend::System; if ((*I)->getOption().matches(OPT_internal_externc_isystem)) Group = frontend::ExternCSystem; Opts.AddPath((*I)->getValue(), Group, false, true); } // Add the path prefixes which are implicitly treated as being system headers. for (arg_iterator I = Args.filtered_begin(OPT_isystem_prefix, OPT_ino_system_prefix), E = Args.filtered_end(); I != E; ++I) Opts.AddSystemHeaderPrefix((*I)->getValue(), (*I)->getOption().matches(OPT_isystem_prefix)); } void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK, LangStandard::Kind LangStd) { // Set some properties which depend solely on the input kind; it would be nice // to move these to the language standard, and have the driver resolve the // input kind + language standard. if (IK == IK_Asm) { Opts.AsmPreprocessor = 1; } else if (IK == IK_ObjC || IK == IK_ObjCXX || IK == IK_PreprocessedObjC || IK == IK_PreprocessedObjCXX) { Opts.ObjC1 = Opts.ObjC2 = 1; } if (LangStd == LangStandard::lang_unspecified) { // Based on the base language, pick one. switch (IK) { case IK_None: case IK_AST: case IK_LLVM_IR: llvm_unreachable("Invalid input kind!"); case IK_OpenCL: LangStd = LangStandard::lang_opencl; break; case IK_CUDA: LangStd = LangStandard::lang_cuda; break; case IK_Asm: case IK_C: case IK_PreprocessedC: case IK_ObjC: case IK_PreprocessedObjC: LangStd = LangStandard::lang_gnu99; break; case IK_CXX: case IK_PreprocessedCXX: case IK_ObjCXX: case IK_PreprocessedObjCXX: LangStd = LangStandard::lang_gnucxx98; break; } } const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd); Opts.LineComment = Std.hasLineComments(); Opts.C99 = Std.isC99(); Opts.C11 = Std.isC11(); Opts.CPlusPlus = Std.isCPlusPlus(); Opts.CPlusPlus11 = Std.isCPlusPlus11(); Opts.CPlusPlus1y = Std.isCPlusPlus1y(); Opts.Digraphs = Std.hasDigraphs(); Opts.GNUMode = Std.isGNUMode(); Opts.GNUInline = !Std.isC99(); Opts.HexFloats = Std.hasHexFloats(); Opts.ImplicitInt = Std.hasImplicitInt(); // Set OpenCL Version. if (LangStd == LangStandard::lang_opencl) { Opts.OpenCL = 1; Opts.OpenCLVersion = 100; } else if (LangStd == LangStandard::lang_opencl11) { Opts.OpenCL = 1; Opts.OpenCLVersion = 110; } else if (LangStd == LangStandard::lang_opencl12) { Opts.OpenCL = 1; Opts.OpenCLVersion = 120; } // OpenCL has some additional defaults. if (Opts.OpenCL) { Opts.AltiVec = 0; Opts.CXXOperatorNames = 1; Opts.LaxVectorConversions = 0; Opts.DefaultFPContract = 1; Opts.NativeHalfType = 1; } if (LangStd == LangStandard::lang_cuda) Opts.CUDA = 1; // OpenCL and C++ both have bool, true, false keywords. Opts.Bool = Opts.OpenCL || Opts.CPlusPlus; // C++ has wchar_t keyword. Opts.WChar = Opts.CPlusPlus; Opts.GNUKeywords = Opts.GNUMode; Opts.CXXOperatorNames = Opts.CPlusPlus; // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs // is specified, or -std is set to a conforming mode. Opts.Trigraphs = !Opts.GNUMode; Opts.DollarIdents = !Opts.AsmPreprocessor; // C++1y onwards has sized global deallocation functions. Opts.SizedDeallocation = Opts.CPlusPlus1y; } /// Attempt to parse a visibility value out of the given argument. static Visibility parseVisibility(Arg *arg, ArgList &args, DiagnosticsEngine &diags) { StringRef value = arg->getValue(); if (value == "default") { return DefaultVisibility; } else if (value == "hidden") { return HiddenVisibility; } else if (value == "protected") { // FIXME: diagnose if target does not support protected visibility return ProtectedVisibility; } diags.Report(diag::err_drv_invalid_value) << arg->getAsString(args) << value; return DefaultVisibility; } static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, DiagnosticsEngine &Diags) { // FIXME: Cleanup per-file based stuff. LangStandard::Kind LangStd = LangStandard::lang_unspecified; if (const Arg *A = Args.getLastArg(OPT_std_EQ)) { LangStd = llvm::StringSwitch(A->getValue()) #define LANGSTANDARD(id, name, desc, features) \ .Case(name, LangStandard::lang_##id) #include "clang/Frontend/LangStandards.def" .Default(LangStandard::lang_unspecified); if (LangStd == LangStandard::lang_unspecified) Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << A->getValue(); else { // Valid standard, check to make sure language and standard are compatable. const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd); switch (IK) { case IK_C: case IK_ObjC: case IK_PreprocessedC: case IK_PreprocessedObjC: if (!(Std.isC89() || Std.isC99())) Diags.Report(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args) << "C/ObjC"; break; case IK_CXX: case IK_ObjCXX: case IK_PreprocessedCXX: case IK_PreprocessedObjCXX: if (!Std.isCPlusPlus()) Diags.Report(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args) << "C++/ObjC++"; break; case IK_OpenCL: if (!Std.isC99()) Diags.Report(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args) << "OpenCL"; break; case IK_CUDA: if (!Std.isCPlusPlus()) Diags.Report(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args) << "CUDA"; break; default: break; } } } // -cl-std only applies for OpenCL language standards. // Override the -std option in this case. if (const Arg *A = Args.getLastArg(OPT_cl_std_EQ)) { LangStandard::Kind OpenCLLangStd = llvm::StringSwitch(A->getValue()) .Case("CL", LangStandard::lang_opencl) .Case("CL1.1", LangStandard::lang_opencl11) .Case("CL1.2", LangStandard::lang_opencl12) .Default(LangStandard::lang_unspecified); if (OpenCLLangStd == LangStandard::lang_unspecified) { Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << A->getValue(); } else LangStd = OpenCLLangStd; } CompilerInvocation::setLangDefaults(Opts, IK, LangStd); // We abuse '-f[no-]gnu-keywords' to force overriding all GNU-extension // keywords. This behavior is provided by GCC's poorly named '-fasm' flag, // while a subset (the non-C++ GNU keywords) is provided by GCC's // '-fgnu-keywords'. Clang conflates the two for simplicity under the single // name, as it doesn't seem a useful distinction. Opts.GNUKeywords = Args.hasFlag(OPT_fgnu_keywords, OPT_fno_gnu_keywords, Opts.GNUKeywords); if (Args.hasArg(OPT_fno_operator_names)) Opts.CXXOperatorNames = 0; if (Opts.ObjC1) { if (Arg *arg = Args.getLastArg(OPT_fobjc_runtime_EQ)) { StringRef value = arg->getValue(); if (Opts.ObjCRuntime.tryParse(value)) Diags.Report(diag::err_drv_unknown_objc_runtime) << value; } if (Args.hasArg(OPT_fobjc_gc_only)) Opts.setGC(LangOptions::GCOnly); else if (Args.hasArg(OPT_fobjc_gc)) Opts.setGC(LangOptions::HybridGC); else if (Args.hasArg(OPT_fobjc_arc)) { Opts.ObjCAutoRefCount = 1; if (!Opts.ObjCRuntime.allowsARC()) Diags.Report(diag::err_arc_unsupported_on_runtime); // Only set ObjCARCWeak if ARC is enabled. if (Args.hasArg(OPT_fobjc_runtime_has_weak)) Opts.ObjCARCWeak = 1; else Opts.ObjCARCWeak = Opts.ObjCRuntime.allowsWeak(); } if (Args.hasArg(OPT_fno_objc_infer_related_result_type)) Opts.ObjCInferRelatedResultType = 0; if (Args.hasArg(OPT_fobjc_subscripting_legacy_runtime)) Opts.ObjCSubscriptingLegacyRuntime = (Opts.ObjCRuntime.getKind() == ObjCRuntime::FragileMacOSX); } if (Args.hasArg(OPT_fgnu89_inline)) Opts.GNUInline = 1; if (Args.hasArg(OPT_fapple_kext)) { if (!Opts.CPlusPlus) Diags.Report(diag::warn_c_kext); else Opts.AppleKext = 1; } if (Args.hasArg(OPT_print_ivar_layout)) Opts.ObjCGCBitmapPrint = 1; if (Args.hasArg(OPT_fno_constant_cfstrings)) Opts.NoConstantCFStrings = 1; if (Args.hasArg(OPT_faltivec)) Opts.AltiVec = 1; if (Args.hasArg(OPT_pthread)) Opts.POSIXThreads = 1; // The value-visibility mode defaults to "default". if (Arg *visOpt = Args.getLastArg(OPT_fvisibility)) { Opts.setValueVisibilityMode(parseVisibility(visOpt, Args, Diags)); } else { Opts.setValueVisibilityMode(DefaultVisibility); } // The type-visibility mode defaults to the value-visibility mode. if (Arg *typeVisOpt = Args.getLastArg(OPT_ftype_visibility)) { Opts.setTypeVisibilityMode(parseVisibility(typeVisOpt, Args, Diags)); } else { Opts.setTypeVisibilityMode(Opts.getValueVisibilityMode()); } if (Args.hasArg(OPT_fvisibility_inlines_hidden)) Opts.InlineVisibilityHidden = 1; if (Args.hasArg(OPT_ftrapv)) { Opts.setSignedOverflowBehavior(LangOptions::SOB_Trapping); // Set the handler, if one is specified. Opts.OverflowHandler = Args.getLastArgValue(OPT_ftrapv_handler); } else if (Args.hasArg(OPT_fwrapv)) Opts.setSignedOverflowBehavior(LangOptions::SOB_Defined); if (Args.hasArg(OPT_trigraphs)) Opts.Trigraphs = 1; Opts.DollarIdents = Args.hasFlag(OPT_fdollars_in_identifiers, OPT_fno_dollars_in_identifiers, Opts.DollarIdents); Opts.PascalStrings = Args.hasArg(OPT_fpascal_strings); Opts.MicrosoftExt = Args.hasArg(OPT_fms_extensions) || Args.hasArg(OPT_fms_compatibility); Opts.MicrosoftMode = Args.hasArg(OPT_fms_compatibility); Opts.AsmBlocks = Args.hasArg(OPT_fasm_blocks) || Opts.MicrosoftExt; Opts.MSCVersion = getLastArgIntValue(Args, OPT_fmsc_version, 0, Diags); Opts.Borland = Args.hasArg(OPT_fborland_extensions); Opts.WritableStrings = Args.hasArg(OPT_fwritable_strings); Opts.ConstStrings = Args.hasFlag(OPT_fconst_strings, OPT_fno_const_strings, Opts.ConstStrings); if (Args.hasArg(OPT_fno_lax_vector_conversions)) Opts.LaxVectorConversions = 0; if (Args.hasArg(OPT_fno_threadsafe_statics)) Opts.ThreadsafeStatics = 0; Opts.Exceptions = Args.hasArg(OPT_fexceptions); Opts.ObjCExceptions = Args.hasArg(OPT_fobjc_exceptions); Opts.CXXExceptions = Args.hasArg(OPT_fcxx_exceptions); Opts.SjLjExceptions = Args.hasArg(OPT_fsjlj_exceptions); Opts.TraditionalCPP = Args.hasArg(OPT_traditional_cpp); Opts.RTTI = !Args.hasArg(OPT_fno_rtti); Opts.Blocks = Args.hasArg(OPT_fblocks); Opts.BlocksRuntimeOptional = Args.hasArg(OPT_fblocks_runtime_optional); Opts.Modules = Args.hasArg(OPT_fmodules); Opts.ModulesDeclUse = Args.hasArg(OPT_fmodules_decluse); Opts.CharIsSigned = Opts.OpenCL || !Args.hasArg(OPT_fno_signed_char); Opts.WChar = Opts.CPlusPlus && !Args.hasArg(OPT_fno_wchar); Opts.ShortWChar = Args.hasArg(OPT_fshort_wchar); Opts.ShortEnums = Args.hasArg(OPT_fshort_enums); Opts.Freestanding = Args.hasArg(OPT_ffreestanding); Opts.FormatExtensions = Args.hasArg(OPT_fformat_extensions); Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding; Opts.NoMathBuiltin = Args.hasArg(OPT_fno_math_builtin); Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new); Opts.SizedDeallocation |= Args.hasArg(OPT_fsized_deallocation); Opts.HeinousExtensions = Args.hasArg(OPT_fheinous_gnu_extensions); Opts.AccessControl = !Args.hasArg(OPT_fno_access_control); Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors); Opts.MathErrno = !Opts.OpenCL && Args.hasArg(OPT_fmath_errno); Opts.InstantiationDepth = getLastArgIntValue(Args, OPT_ftemplate_depth, 256, Diags); Opts.ArrowDepth = getLastArgIntValue(Args, OPT_foperator_arrow_depth, 256, Diags); Opts.ConstexprCallDepth = getLastArgIntValue(Args, OPT_fconstexpr_depth, 512, Diags); Opts.ConstexprStepLimit = getLastArgIntValue(Args, OPT_fconstexpr_steps, 1048576, Diags); Opts.BracketDepth = getLastArgIntValue(Args, OPT_fbracket_depth, 256, Diags); Opts.DelayedTemplateParsing = Args.hasArg(OPT_fdelayed_template_parsing); Opts.NumLargeByValueCopy = getLastArgIntValue(Args, OPT_Wlarge_by_value_copy_EQ, 0, Diags); Opts.MSBitfields = Args.hasArg(OPT_mms_bitfields); Opts.ObjCConstantStringClass = Args.getLastArgValue(OPT_fconstant_string_class); Opts.ObjCDefaultSynthProperties = !Args.hasArg(OPT_disable_objc_default_synthesize_properties); Opts.EncodeExtendedBlockSig = Args.hasArg(OPT_fencode_extended_block_signature); Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls); Opts.PackStruct = getLastArgIntValue(Args, OPT_fpack_struct_EQ, 0, Diags); Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags); Opts.PIELevel = getLastArgIntValue(Args, OPT_pie_level, 0, Diags); Opts.Static = Args.hasArg(OPT_static_define); Opts.DumpRecordLayoutsSimple = Args.hasArg(OPT_fdump_record_layouts_simple); Opts.DumpRecordLayouts = Opts.DumpRecordLayoutsSimple || Args.hasArg(OPT_fdump_record_layouts); Opts.DumpVTableLayouts = Args.hasArg(OPT_fdump_vtable_layouts); Opts.SpellChecking = !Args.hasArg(OPT_fno_spell_checking); Opts.NoBitFieldTypeAlign = Args.hasArg(OPT_fno_bitfield_type_align); Opts.SinglePrecisionConstants = Args.hasArg(OPT_cl_single_precision_constant); Opts.FastRelaxedMath = Args.hasArg(OPT_cl_fast_relaxed_math); Opts.MRTD = Args.hasArg(OPT_mrtd); Opts.HexagonQdsp6Compat = Args.hasArg(OPT_mqdsp6_compat); Opts.FakeAddressSpaceMap = Args.hasArg(OPT_ffake_address_space_map); Opts.ParseUnknownAnytype = Args.hasArg(OPT_funknown_anytype); Opts.DebuggerSupport = Args.hasArg(OPT_fdebugger_support); Opts.DebuggerCastResultToId = Args.hasArg(OPT_fdebugger_cast_result_to_id); Opts.DebuggerObjCLiteral = Args.hasArg(OPT_fdebugger_objc_literal); Opts.ApplePragmaPack = Args.hasArg(OPT_fapple_pragma_pack); Opts.CurrentModule = Args.getLastArgValue(OPT_fmodule_name); if (Arg *A = Args.getLastArg(OPT_faddress_space_map_mangling_EQ)) { switch (llvm::StringSwitch(A->getValue()) .Case("target", LangOptions::ASMM_Target) .Case("no", LangOptions::ASMM_Off) .Case("yes", LangOptions::ASMM_On) .Default(255)) { default: Diags.Report(diag::err_drv_invalid_value) << "-faddress-space-map-mangling=" << A->getValue(); break; case LangOptions::ASMM_Target: Opts.setAddressSpaceMapMangling(LangOptions::ASMM_Target); break; case LangOptions::ASMM_On: Opts.setAddressSpaceMapMangling(LangOptions::ASMM_On); break; case LangOptions::ASMM_Off: Opts.setAddressSpaceMapMangling(LangOptions::ASMM_Off); break; } } // Check if -fopenmp is specified. Opts.OpenMP = Args.hasArg(OPT_fopenmp); // Record whether the __DEPRECATED define was requested. Opts.Deprecated = Args.hasFlag(OPT_fdeprecated_macro, OPT_fno_deprecated_macro, Opts.Deprecated); // FIXME: Eliminate this dependency. unsigned Opt = getOptimizationLevel(Args, IK, Diags), OptSize = getOptimizationLevelSize(Args); Opts.Optimize = Opt != 0; Opts.OptimizeSize = OptSize != 0; // This is the __NO_INLINE__ define, which just depends on things like the // optimization level and -fno-inline, not actually whether the backend has // inlining enabled. Opts.NoInlineDefine = !Opt || Args.hasArg(OPT_fno_inline); Opts.FastMath = Args.hasArg(OPT_ffast_math); Opts.FiniteMathOnly = Args.hasArg(OPT_ffinite_math_only); Opts.RetainCommentsFromSystemHeaders = Args.hasArg(OPT_fretain_comments_from_system_headers); unsigned SSP = getLastArgIntValue(Args, OPT_stack_protector, 0, Diags); switch (SSP) { default: Diags.Report(diag::err_drv_invalid_value) << Args.getLastArg(OPT_stack_protector)->getAsString(Args) << SSP; break; case 0: Opts.setStackProtector(LangOptions::SSPOff); break; case 1: Opts.setStackProtector(LangOptions::SSPOn); break; case 2: Opts.setStackProtector(LangOptions::SSPReq); break; } // Parse -fsanitize= arguments. std::vector Sanitizers = Args.getAllArgValues(OPT_fsanitize_EQ); for (unsigned I = 0, N = Sanitizers.size(); I != N; ++I) { // Since the Opts.Sanitize* values are bitfields, it's a little tricky to // efficiently map string values to them. Perform the mapping indirectly: // convert strings to enumerated values, then switch over the enum to set // the right bitfield value. enum Sanitizer { #define SANITIZER(NAME, ID) \ ID, #include "clang/Basic/Sanitizers.def" Unknown }; switch (llvm::StringSwitch(Sanitizers[I]) #define SANITIZER(NAME, ID) \ .Case(NAME, ID) #include "clang/Basic/Sanitizers.def" .Default(Unknown)) { #define SANITIZER(NAME, ID) \ case ID: \ Opts.Sanitize.ID = true; \ break; #include "clang/Basic/Sanitizers.def" case Unknown: Diags.Report(diag::err_drv_invalid_value) << "-fsanitize=" << Sanitizers[I]; break; } } } static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, FileManager &FileMgr, DiagnosticsEngine &Diags) { using namespace options; Opts.ImplicitPCHInclude = Args.getLastArgValue(OPT_include_pch); Opts.ImplicitPTHInclude = Args.getLastArgValue(OPT_include_pth); if (const Arg *A = Args.getLastArg(OPT_token_cache)) Opts.TokenCache = A->getValue(); else Opts.TokenCache = Opts.ImplicitPTHInclude; Opts.UsePredefines = !Args.hasArg(OPT_undef); Opts.DetailedRecord = Args.hasArg(OPT_detailed_preprocessing_record); Opts.DisablePCHValidation = Args.hasArg(OPT_fno_validate_pch); Opts.DumpDeserializedPCHDecls = Args.hasArg(OPT_dump_deserialized_pch_decls); for (arg_iterator it = Args.filtered_begin(OPT_error_on_deserialized_pch_decl), ie = Args.filtered_end(); it != ie; ++it) { const Arg *A = *it; Opts.DeserializedPCHDeclsToErrorOn.insert(A->getValue()); } if (const Arg *A = Args.getLastArg(OPT_preamble_bytes_EQ)) { StringRef Value(A->getValue()); size_t Comma = Value.find(','); unsigned Bytes = 0; unsigned EndOfLine = 0; if (Comma == StringRef::npos || Value.substr(0, Comma).getAsInteger(10, Bytes) || Value.substr(Comma + 1).getAsInteger(10, EndOfLine)) Diags.Report(diag::err_drv_preamble_format); else { Opts.PrecompiledPreambleBytes.first = Bytes; Opts.PrecompiledPreambleBytes.second = (EndOfLine != 0); } } // Add macros from the command line. for (arg_iterator it = Args.filtered_begin(OPT_D, OPT_U), ie = Args.filtered_end(); it != ie; ++it) { if ((*it)->getOption().matches(OPT_D)) Opts.addMacroDef((*it)->getValue()); else Opts.addMacroUndef((*it)->getValue()); } Opts.MacroIncludes = Args.getAllArgValues(OPT_imacros); // Add the ordered list of -includes. for (arg_iterator it = Args.filtered_begin(OPT_include), ie = Args.filtered_end(); it != ie; ++it) { const Arg *A = *it; Opts.Includes.push_back(A->getValue()); } for (arg_iterator it = Args.filtered_begin(OPT_chain_include), ie = Args.filtered_end(); it != ie; ++it) { const Arg *A = *it; Opts.ChainedIncludes.push_back(A->getValue()); } // Include 'altivec.h' if -faltivec option present if (Args.hasArg(OPT_faltivec)) Opts.Includes.push_back("altivec.h"); for (arg_iterator it = Args.filtered_begin(OPT_remap_file), ie = Args.filtered_end(); it != ie; ++it) { const Arg *A = *it; std::pair Split = StringRef(A->getValue()).split(';'); if (Split.second.empty()) { Diags.Report(diag::err_drv_invalid_remap_file) << A->getAsString(Args); continue; } Opts.addRemappedFile(Split.first, Split.second); } if (Arg *A = Args.getLastArg(OPT_fobjc_arc_cxxlib_EQ)) { StringRef Name = A->getValue(); unsigned Library = llvm::StringSwitch(Name) .Case("libc++", ARCXX_libcxx) .Case("libstdc++", ARCXX_libstdcxx) .Case("none", ARCXX_nolib) .Default(~0U); if (Library == ~0U) Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name; else Opts.ObjCXXARCStandardLibrary = (ObjCXXARCStandardLibraryKind)Library; } } static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts, ArgList &Args, frontend::ActionKind Action) { using namespace options; switch (Action) { case frontend::ASTDeclList: case frontend::ASTDump: case frontend::ASTPrint: case frontend::ASTView: case frontend::EmitAssembly: case frontend::EmitBC: case frontend::EmitHTML: case frontend::EmitLLVM: case frontend::EmitLLVMOnly: case frontend::EmitCodeGenOnly: case frontend::EmitObj: case frontend::FixIt: case frontend::GenerateModule: case frontend::GeneratePCH: case frontend::GeneratePTH: case frontend::ParseSyntaxOnly: case frontend::ModuleFileInfo: case frontend::PluginAction: case frontend::PrintDeclContext: case frontend::RewriteObjC: case frontend::RewriteTest: case frontend::RunAnalysis: case frontend::MigrateSource: Opts.ShowCPP = 0; break; case frontend::DumpRawTokens: case frontend::DumpTokens: case frontend::InitOnly: case frontend::PrintPreamble: case frontend::PrintPreprocessedInput: case frontend::RewriteMacros: case frontend::RunPreprocessorOnly: Opts.ShowCPP = !Args.hasArg(OPT_dM); break; } Opts.ShowComments = Args.hasArg(OPT_C); Opts.ShowLineMarkers = !Args.hasArg(OPT_P); Opts.ShowMacroComments = Args.hasArg(OPT_CC); Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD); Opts.RewriteIncludes = Args.hasArg(OPT_frewrite_includes); } static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args) { using namespace options; Opts.ABI = Args.getLastArgValue(OPT_target_abi); Opts.CXXABI = Args.getLastArgValue(OPT_cxx_abi); Opts.CPU = Args.getLastArgValue(OPT_target_cpu); Opts.FPMath = Args.getLastArgValue(OPT_mfpmath); Opts.FeaturesAsWritten = Args.getAllArgValues(OPT_target_feature); Opts.LinkerVersion = Args.getLastArgValue(OPT_target_linker_version); Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple)); // Use the default target triple if unspecified. if (Opts.Triple.empty()) Opts.Triple = llvm::sys::getDefaultTargetTriple(); } // bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, const char *const *ArgBegin, const char *const *ArgEnd, DiagnosticsEngine &Diags) { bool Success = true; // Parse the arguments. OwningPtr Opts(createDriverOptTable()); const unsigned IncludedFlagsBitmask = options::CC1Option; unsigned MissingArgIndex, MissingArgCount; OwningPtr Args( Opts->ParseArgs(ArgBegin, ArgEnd, MissingArgIndex, MissingArgCount, IncludedFlagsBitmask)); // Check for missing argument error. if (MissingArgCount) { Diags.Report(diag::err_drv_missing_argument) << Args->getArgString(MissingArgIndex) << MissingArgCount; Success = false; } // Issue errors on unknown arguments. for (arg_iterator it = Args->filtered_begin(OPT_UNKNOWN), ie = Args->filtered_end(); it != ie; ++it) { Diags.Report(diag::err_drv_unknown_argument) << (*it)->getAsString(*Args); Success = false; } Success = ParseAnalyzerArgs(*Res.getAnalyzerOpts(), *Args, Diags) && Success; Success = ParseMigratorArgs(Res.getMigratorOpts(), *Args) && Success; ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), *Args); Success = ParseDiagnosticArgs(Res.getDiagnosticOpts(), *Args, &Diags) && Success; ParseCommentArgs(Res.getLangOpts()->CommentOpts, *Args); ParseFileSystemArgs(Res.getFileSystemOpts(), *Args); // FIXME: We shouldn't have to pass the DashX option around here InputKind DashX = ParseFrontendArgs(Res.getFrontendOpts(), *Args, Diags); - Success = ParseCodeGenArgs(Res.getCodeGenOpts(), *Args, DashX, Diags) - && Success; + ParseTargetArgs(Res.getTargetOpts(), *Args); + Success = ParseCodeGenArgs(Res.getCodeGenOpts(), *Args, DashX, Diags, + Res.getTargetOpts()) && Success; ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), *Args); if (DashX != IK_AST && DashX != IK_LLVM_IR) { ParseLangArgs(*Res.getLangOpts(), *Args, DashX, Diags); if (Res.getFrontendOpts().ProgramAction == frontend::RewriteObjC) Res.getLangOpts()->ObjCExceptions = 1; } // FIXME: ParsePreprocessorArgs uses the FileManager to read the contents of // PCH file and find the original header name. Remove the need to do that in // ParsePreprocessorArgs and remove the FileManager // parameters from the function and the "FileManager.h" #include. FileManager FileMgr(Res.getFileSystemOpts()); ParsePreprocessorArgs(Res.getPreprocessorOpts(), *Args, FileMgr, Diags); ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), *Args, Res.getFrontendOpts().ProgramAction); - ParseTargetArgs(Res.getTargetOpts(), *Args); - return Success; } namespace { class ModuleSignature { SmallVector Data; unsigned CurBit; uint64_t CurValue; public: ModuleSignature() : CurBit(0), CurValue(0) { } void add(uint64_t Value, unsigned Bits); void add(StringRef Value); void flush(); llvm::APInt getAsInteger() const; }; } void ModuleSignature::add(uint64_t Value, unsigned int NumBits) { CurValue |= Value << CurBit; if (CurBit + NumBits < 64) { CurBit += NumBits; return; } // Add the current word. Data.push_back(CurValue); if (CurBit) CurValue = Value >> (64-CurBit); else CurValue = 0; CurBit = (CurBit+NumBits) & 63; } void ModuleSignature::flush() { if (CurBit == 0) return; Data.push_back(CurValue); CurBit = 0; CurValue = 0; } void ModuleSignature::add(StringRef Value) { for (StringRef::iterator I = Value.begin(), IEnd = Value.end(); I != IEnd;++I) add(*I, 8); } llvm::APInt ModuleSignature::getAsInteger() const { return llvm::APInt(Data.size() * 64, Data); } std::string CompilerInvocation::getModuleHash() const { // Note: For QoI reasons, the things we use as a hash here should all be // dumped via the -module-info flag. using llvm::hash_code; using llvm::hash_value; using llvm::hash_combine; // Start the signature with the compiler version. // FIXME: We'd rather use something more cryptographically sound than // CityHash, but this will do for now. hash_code code = hash_value(getClangFullRepositoryVersion()); // Extend the signature with the language options #define LANGOPT(Name, Bits, Default, Description) \ code = hash_combine(code, LangOpts->Name); #define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ code = hash_combine(code, static_cast(LangOpts->get##Name())); #define BENIGN_LANGOPT(Name, Bits, Default, Description) #define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) #include "clang/Basic/LangOptions.def" // Extend the signature with the target options. code = hash_combine(code, TargetOpts->Triple, TargetOpts->CPU, TargetOpts->ABI, TargetOpts->CXXABI, TargetOpts->LinkerVersion); for (unsigned i = 0, n = TargetOpts->FeaturesAsWritten.size(); i != n; ++i) code = hash_combine(code, TargetOpts->FeaturesAsWritten[i]); // Extend the signature with preprocessor options. const PreprocessorOptions &ppOpts = getPreprocessorOpts(); const HeaderSearchOptions &hsOpts = getHeaderSearchOpts(); code = hash_combine(code, ppOpts.UsePredefines, ppOpts.DetailedRecord); std::vector MacroDefs; for (std::vector >::const_iterator I = getPreprocessorOpts().Macros.begin(), IEnd = getPreprocessorOpts().Macros.end(); I != IEnd; ++I) { // If we're supposed to ignore this macro for the purposes of modules, // don't put it into the hash. if (!hsOpts.ModulesIgnoreMacros.empty()) { // Check whether we're ignoring this macro. StringRef MacroDef = I->first; if (hsOpts.ModulesIgnoreMacros.count(MacroDef.split('=').first)) continue; } code = hash_combine(code, I->first, I->second); } // Extend the signature with the sysroot. code = hash_combine(code, hsOpts.Sysroot, hsOpts.UseBuiltinIncludes, hsOpts.UseStandardSystemIncludes, hsOpts.UseStandardCXXIncludes, hsOpts.UseLibcxx); // Darwin-specific hack: if we have a sysroot, use the contents and // modification time of // $sysroot/System/Library/CoreServices/SystemVersion.plist // as part of the module hash. if (!hsOpts.Sysroot.empty()) { llvm::OwningPtr buffer; SmallString<128> systemVersionFile; systemVersionFile += hsOpts.Sysroot; llvm::sys::path::append(systemVersionFile, "System"); llvm::sys::path::append(systemVersionFile, "Library"); llvm::sys::path::append(systemVersionFile, "CoreServices"); llvm::sys::path::append(systemVersionFile, "SystemVersion.plist"); if (!llvm::MemoryBuffer::getFile(systemVersionFile.str(), buffer)) { code = hash_combine(code, buffer.get()->getBuffer()); struct stat statBuf; if (stat(systemVersionFile.c_str(), &statBuf) == 0) code = hash_combine(code, statBuf.st_mtime); } } return llvm::APInt(64, code).toString(36, /*Signed=*/false); } namespace clang { // Declared in clang/Frontend/Utils.h. int getLastArgIntValue(const ArgList &Args, OptSpecifier Id, int Default, DiagnosticsEngine *Diags) { int Res = Default; if (Arg *A = Args.getLastArg(Id)) { if (StringRef(A->getValue()).getAsInteger(10, Res)) { if (Diags) Diags->Report(diag::err_drv_invalid_int_value) << A->getAsString(Args) << A->getValue(); } } return Res; } } Index: stable/9/contrib/llvm/tools/clang =================================================================== --- stable/9/contrib/llvm/tools/clang (revision 283018) +++ stable/9/contrib/llvm/tools/clang (revision 283019) Property changes on: stable/9/contrib/llvm/tools/clang ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/contrib/llvm/tools/clang:r264827,265477,269387 Index: stable/9/contrib/llvm =================================================================== --- stable/9/contrib/llvm (revision 283018) +++ stable/9/contrib/llvm (revision 283019) Property changes on: stable/9/contrib/llvm ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/contrib/llvm:r252503,264826-264827,265477,269387 Index: stable/9/contrib =================================================================== --- stable/9/contrib (revision 283018) +++ stable/9/contrib (revision 283019) Property changes on: stable/9/contrib ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/contrib:r252503,264826-264827,265477,269387 Index: stable/9 =================================================================== --- stable/9 (revision 283018) +++ stable/9 (revision 283019) Property changes on: stable/9 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r252503,264826-264827,265477,269387

; def _no_standard_includes : Flag<["--"], "no-standard-includes">, Alias; def _no_standard_libraries : Flag<["--"], "no-standard-libraries">, Alias; def _no_undefined : Flag<["--"], "no-undefined">, Flags<[LinkerInput]>; def _no_warnings : Flag<["--"], "no-warnings">, Alias; def _optimize_EQ : Joined<["--"], "optimize=">, Alias; def _optimize : Flag<["--"], "optimize">, Alias; def _output_class_directory_EQ : Joined<["--"], "output-class-directory=">, Alias; def _output_class_directory : Separate<["--"], "output-class-directory">, Alias; def _output_EQ : Joined<["--"], "output=">, Alias; def _output : Separate<["--"], "output">, Alias; def _param : Separate<["--"], "param">, Group; def _param_EQ : Joined<["--"], "param=">, Alias<_param>; def _prefix_EQ : Joined<["--"], "prefix=">, Alias; def _prefix : Separate<["--"], "prefix">, Alias; def _preprocess : Flag<["--"], "preprocess">, Alias; def _print_diagnostic_categories : Flag<["--"], "print-diagnostic-categories">; def _print_file_name : Separate<["--"], "print-file-name">, Alias; def _print_missing_file_dependencies : Flag<["--"], "print-missing-file-dependencies">, Alias; def _print_prog_name : Separate<["--"], "print-prog-name">, Alias; def _profile_blocks : Flag<["--"], "profile-blocks">, Alias; def _profile : Flag<["--"], "profile">, Alias