diff options
author | Roman Divacky <rdivacky@FreeBSD.org> | 2010-04-06 15:52:58 +0000 |
---|---|---|
committer | Roman Divacky <rdivacky@FreeBSD.org> | 2010-04-06 15:52:58 +0000 |
commit | 9f4a1da9a0a56a0b0a7f8249f34b3cdea6179c41 (patch) | |
tree | 0dd020f28a4846707f8d60717d9b2921ea187bd8 | |
parent | b5efedaf2ab20d844d5a21cdef76b55acbf4f01c (diff) |
Update LLVM to r100520.
Notes
Notes:
svn path=/vendor/llvm/dist/; revision=206274
178 files changed, 4173 insertions, 4069 deletions
diff --git a/docs/HowToReleaseLLVM.html b/docs/HowToReleaseLLVM.html index d6ef416e166c..ae0b13361b59 100644 --- a/docs/HowToReleaseLLVM.html +++ b/docs/HowToReleaseLLVM.html @@ -362,13 +362,12 @@ Qualification Details</a></div> <p><table> <tr><th>Architecture</th><th>OS</th><th>llvm-gcc baseline</th><th>clang baseline </th><th>tests</th></tr> - <tr><td>x86-32</td><td>Mac OS 10.5</td><td>last release</td><td>none</td><td>llvm dejagnu, clang tests, test-suite (including spec)</td></tr> - <tr><td>x86-32</td><td>Linux</td><td>last release</td><td>none</td><td>llvm dejagnu, clang tests, test-suite (including spec)</td></tr> - <tr><td>x86-32</td><td>FreeBSD</td><td>none</td><td>none</td><td>llvm dejagnu, clang tests, test-suite</td></tr> + <tr><td>x86-32</td><td>Linux</td><td>last release</td><td>last release</td><td>llvm dejagnu, clang tests, test-suite (including spec)</td></tr> + <tr><td>x86-32</td><td>FreeBSD</td><td>none</td><td>last release</td><td>llvm dejagnu, clang tests, test-suite</td></tr> <tr><td>x86-32</td><td>mingw</td><td>last release</td><td>none</td><td>QT</td></tr> - <tr><td>x86-64</td><td>Mac OS 10.5</td><td>last release</td><td>none</td><td>llvm dejagnu, clang tests, test-suite (including spec)</td></tr> - <tr><td>x86-64</td><td>Linux</td><td>last release</td><td>none</td><td>llvm dejagnu, clang tests, test-suite (including spec)</td></tr> - <tr><td>x86-64</td><td>FreeBSD</td><td>none</td><td>none</td><td>llvm dejagnu, clang tests, test-suite</td></tr> + <tr><td>x86-64</td><td>Mac OS 10.X</td><td>last release</td><td>last release</td><td>llvm dejagnu, clang tests, test-suite (including spec)</td></tr> + <tr><td>x86-64</td><td>Linux</td><td>last release</td><td>last release</td><td>llvm dejagnu, clang tests, test-suite (including spec)</td></tr> + <tr><td>x86-64</td><td>FreeBSD</td><td>none</td><td>last release</td><td>llvm dejagnu, clang tests, test-suite</td></tr> </table></p> </div> @@ -518,7 +517,7 @@ svn copy https://llvm.org/svn/llvm-project/test-suite/branches/release_XX \ src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"></a> <a href="http://llvm.cs.uiuc.edu">The LLVM Compiler Infrastructure</a> <br> - Last modified: $Date: 2009-10-12 16:46:08 +0200 (Mon, 12 Oct 2009) $ + Last modified: $Date: 2010-04-05 20:35:37 +0200 (Mon, 05 Apr 2010) $ </address> </body> </html> diff --git a/docs/Lexicon.html b/docs/Lexicon.html index 235dee3a4c3b..576b732c67c3 100644 --- a/docs/Lexicon.html +++ b/docs/Lexicon.html @@ -50,6 +50,11 @@ <td><a href="#LCSSA">LCSSA</a></td> <td><a href="#LICM">LICM</a></td> <td><a href="#Load-VN">Load-VN</a></td> + <td><a href="#LTO">LTO</a></td> + </tr> + <tr><th colspan="8"><b>- <a href="#M">M</a> -</b></th></tr> + <tr> + <td><a href="#MC">MC</a></td> </tr> <tr><th colspan="8"><b>- <a href="#O">O</a> -</b></th></tr> <tr> @@ -167,15 +172,24 @@ href="http://www.program-transformation.org/Transform/BURG">BURG</a> tool.</dd> <div class="doc_subsection"><a name="L">- L -</a></div> <div class="doc_text"> <dl> - <dt><a name="LCSSA"><b>LCSSA</b></a></dt> - <dd>Loop-Closed Static Single Assignment Form</dd> + <dt><a name="LCSSA"><b>LCSSA</b></a></dt> + <dd>Loop-Closed Static Single Assignment Form</dd> <dt><a name="LICM"><b>LICM</b></a></dt> <dd>Loop Invariant Code Motion</dd> <dt><a name="Load-VN"><b>Load-VN</b></a></dt> <dd>Load Value Numbering</dd> + <dt><a name="LTO"><b>LTO</b></a></dt> + <dd>Link-Time Optimization</dd> + </dl> +</div> +<!-- _______________________________________________________________________ --> +<div class="doc_subsection"><a name="M">- M -</a></div> +<div class="doc_text"> + <dl> + <dt><a name="MC"><b>MC</b></a></dt> + <dd>Machine Code</dd> </dl> </div> - <!-- _______________________________________________________________________ --> <div class="doc_subsection"><a name="O">- O -</a></div> <div class="doc_text"> @@ -255,7 +269,7 @@ href="http://www.program-transformation.org/Transform/BURG">BURG</a> tool.</dd> src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"></a><a href="http://llvm.org/">The LLVM Team</a><br> <a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br> -Last modified: $Date: 2008-12-14 09:01:51 +0100 (Sun, 14 Dec 2008) $ +Last modified: $Date: 2010-04-05 07:48:47 +0200 (Mon, 05 Apr 2010) $ </address> <!-- vim: sw=2 --> diff --git a/docs/SourceLevelDebugging.html b/docs/SourceLevelDebugging.html index 021d7ada158c..9a4a6f1b7e9d 100644 --- a/docs/SourceLevelDebugging.html +++ b/docs/SourceLevelDebugging.html @@ -144,7 +144,7 @@ height="369"> an LLVM user a relationship between generated code and the original program source code.</p> -<p>Currently, debug information is consumed by the DwarfWriter to produce dwarf +<p>Currently, debug information is consumed by DwarfDebug to produce dwarf information used by the gdb debugger. Other targets could use the same information to produce stabs or other debug forms.</p> @@ -1773,7 +1773,7 @@ enum Trees { <a href="mailto:sabre@nondot.org">Chris Lattner</a><br> <a href="http://llvm.org">LLVM Compiler Infrastructure</a><br> - Last modified: $Date: 2010-03-31 09:50:17 +0200 (Wed, 31 Mar 2010) $ + Last modified: $Date: 2010-04-05 06:11:11 +0200 (Mon, 05 Apr 2010) $ </address> </body> diff --git a/docs/WritingAnLLVMBackend.html b/docs/WritingAnLLVMBackend.html index 75353cf5321a..e513cea8b498 100644 --- a/docs/WritingAnLLVMBackend.html +++ b/docs/WritingAnLLVMBackend.html @@ -561,8 +561,7 @@ def AL : Register<"AL">, DwarfRegNum<[0, 0, 0]>; <p> This defines the register <tt>AL</tt> and assigns it values (with <tt>DwarfRegNum</tt>) that are used by <tt>gcc</tt>, <tt>gdb</tt>, or a debug -information writer (such as <tt>DwarfWriter</tt> -in <tt>llvm/lib/CodeGen/AsmPrinter</tt>) to identify a register. For register +information writer to identify a register. For register <tt>AL</tt>, <tt>DwarfRegNum</tt> takes an array of 3 values representing 3 different modes: the first element is for X86-64, the second for exception handling (EH) on X86-32, and the third is generic. -1 is a special Dwarf number @@ -2555,7 +2554,7 @@ with assembler. <a href="http://www.woo.com">Mason Woo</a> and <a href="http://misha.brukman.net">Misha Brukman</a><br> <a href="http://llvm.org">The LLVM Compiler Infrastructure</a> <br> - Last modified: $Date: 2010-02-02 19:44:12 +0100 (Tue, 02 Feb 2010) $ + Last modified: $Date: 2010-04-05 06:11:11 +0200 (Mon, 05 Apr 2010) $ </address> </body> diff --git a/include/llvm/ADT/OwningPtr.h b/include/llvm/ADT/OwningPtr.h index cc53c8c30c12..6d9c30597789 100644 --- a/include/llvm/ADT/OwningPtr.h +++ b/include/llvm/ADT/OwningPtr.h @@ -128,7 +128,6 @@ inline void swap(OwningArrayPtr<T> &a, OwningArrayPtr<T> &b) { a.swap(b); } - } // end namespace llvm #endif diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index a405932beadb..2eff50123a23 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -18,8 +18,6 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/Support/DebugLoc.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/ADT/DenseMap.h" namespace llvm { class BlockAddress; @@ -43,63 +41,33 @@ namespace llvm { class MachineConstantPoolValue; class MachineJumpTableInfo; class MachineModuleInfo; + class MachineMove; + class MCAsmInfo; class MCInst; class MCContext; class MCSection; class MCStreamer; class MCSymbol; - class DwarfWriter; + class DwarfDebug; + class DwarfException; class Mangler; - class MCAsmInfo; class TargetLoweringObjectFile; + class TargetData; class Twine; class Type; - class formatted_raw_ostream; /// AsmPrinter - This class is intended to be used as a driving class for all /// asm writers. class AsmPrinter : public MachineFunctionPass { - static char ID; - - // GCMetadataPrinters - The garbage collection metadata printer table. - typedef DenseMap<GCStrategy*,GCMetadataPrinter*> gcp_map_type; - typedef gcp_map_type::iterator gcp_iterator; - gcp_map_type GCMetadataPrinters; - - /// If VerboseAsm is set, a pointer to the loop info for this - /// function. - /// - MachineLoopInfo *LI; - - public: - /// MMI - If available, this is a pointer to the current MachineModuleInfo. - MachineModuleInfo *MMI; - - protected: - /// DW - If available, this is a pointer to the current dwarf writer. - DwarfWriter *DW; - public: - - /// Output stream on which we're printing assembly code. - /// - formatted_raw_ostream &O; - /// Target machine description. /// TargetMachine &TM; - /// getObjFileLowering - Return information about object file lowering. - TargetLoweringObjectFile &getObjFileLowering() const; - /// Target Asm Printer information. /// const MCAsmInfo *MAI; - /// Target Register Information. - /// - const TargetRegisterInfo *TRI; - /// OutContext - This is the context for the output file that we are /// streaming. This owns all of the global MC-related objects for the /// generated translation unit. @@ -114,6 +82,9 @@ namespace llvm { /// The current machine function. const MachineFunction *MF; + /// MMI - This is a pointer to the current MachineModuleInfo. + MachineModuleInfo *MMI; + /// Name-mangler for global names. /// Mangler *Mang; @@ -123,24 +94,28 @@ namespace llvm { /// MCSymbol *CurrentFnSym; - /// getCurrentSection() - Return the current section we are emitting to. - const MCSection *getCurrentSection() const; + private: + // GCMetadataPrinters - The garbage collection metadata printer table. + void *GCMetadataPrinters; // Really a DenseMap. - /// VerboseAsm - Emit comments in assembly output if this is true. /// bool VerboseAsm; + static char ID; + + /// If VerboseAsm is set, a pointer to the loop info for this + /// function. + MachineLoopInfo *LI; - /// Private state for PrintSpecial() - // Assign a unique ID to this machine instruction. - mutable const MachineInstr *LastMI; - mutable const Function *LastFn; - mutable unsigned Counter; - mutable unsigned SetCounter; + /// DD - If the target supports dwarf debug info, this pointer is non-null. + DwarfDebug *DD; + + /// DE - If the target supports dwarf exception info, this pointer is + /// non-null. + DwarfException *DE; protected: - explicit AsmPrinter(formatted_raw_ostream &o, TargetMachine &TM, - MCStreamer &Streamer); + explicit AsmPrinter(TargetMachine &TM, MCStreamer &Streamer); public: virtual ~AsmPrinter(); @@ -153,7 +128,20 @@ namespace llvm { /// unsigned getFunctionNumber() const; - protected: + /// getObjFileLowering - Return information about object file lowering. + TargetLoweringObjectFile &getObjFileLowering() const; + + /// getTargetData - Return information about data layout. + const TargetData &getTargetData() const; + + /// getCurrentSection() - Return the current section we are emitting to. + const MCSection *getCurrentSection() const; + + + //===------------------------------------------------------------------===// + // MachineFunctionPass Implementation. + //===------------------------------------------------------------------===// + /// getAnalysisUsage - Record analysis usage. /// void getAnalysisUsage(AnalysisUsage &AU) const; @@ -163,41 +151,10 @@ namespace llvm { /// call this implementation. bool doInitialization(Module &M); - /// EmitStartOfAsmFile - This virtual method can be overridden by targets - /// that want to emit something at the start of their file. - virtual void EmitStartOfAsmFile(Module &) {} - - /// EmitEndOfAsmFile - This virtual method can be overridden by targets that - /// want to emit something at the end of their file. - virtual void EmitEndOfAsmFile(Module &) {} - /// doFinalization - Shut down the asmprinter. If you override this in your /// pass, you must make sure to call it explicitly. bool doFinalization(Module &M); - /// PrintSpecial - Print information related to the specified machine instr - /// that is independent of the operand, and may be independent of the instr - /// itself. This can be useful for portably encoding the comment character - /// or other bits of target-specific knowledge into the asmstrings. The - /// syntax used is ${:comment}. Targets can override this to add support - /// for their own strange codes. - virtual void PrintSpecial(const MachineInstr *MI, const char *Code) const; - - /// PrintAsmOperand - Print the specified operand of MI, an INLINEASM - /// instruction, using the specified assembler variant. Targets should - /// override this to format as appropriate. This method can return true if - /// the operand is erroneous. - virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode); - - /// PrintAsmMemoryOperand - Print the specified operand of MI, an INLINEASM - /// instruction, using the specified assembler variant as an address. - /// Targets should override this to format as appropriate. This method can - /// return true if the operand is erroneous. - virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, - const char *ExtraCode); - /// runOnMachineFunction - Emit the specified function out to the /// OutStreamer. virtual bool runOnMachineFunction(MachineFunction &MF) { @@ -207,6 +164,10 @@ namespace llvm { return false; } + //===------------------------------------------------------------------===// + // Coarse grained IR lowering routines. + //===------------------------------------------------------------------===// + /// SetupMachineFunction - This should be called when a new MachineFunction /// is being processed from runOnMachineFunction. void SetupMachineFunction(MachineFunction &MF); @@ -219,19 +180,6 @@ namespace llvm { /// function. void EmitFunctionBody(); - /// EmitInstruction - Targets should implement this to emit instructions. - virtual void EmitInstruction(const MachineInstr *) { - assert(0 && "EmitInstruction not implemented"); - } - - /// EmitFunctionBodyStart - Targets can override this to emit stuff before - /// the first basic block in the function. - virtual void EmitFunctionBodyStart() {} - - /// EmitFunctionBodyEnd - Targets can override this to emit stuff after - /// the last basic block in the function. - virtual void EmitFunctionBodyEnd() {} - /// EmitConstantPool - Print to the current output stream assembly /// representations of the constants in the constant pool MCP. This is /// used to print out constants which have been "spilled to memory" by @@ -252,36 +200,6 @@ namespace llvm { /// do nothing and return false. bool EmitSpecialLLVMGlobal(const GlobalVariable *GV); - public: - //===------------------------------------------------------------------===// - // Emission and print routines - // - - /// EmitInt8 - Emit a byte directive and value. - /// - void EmitInt8(int Value) const; - - /// EmitInt16 - Emit a short directive and value. - /// - void EmitInt16(int Value) const; - - /// EmitInt32 - Emit a long directive and value. - /// - void EmitInt32(int Value) const; - - /// EmitInt64 - Emit a long long directive and value. - /// - void EmitInt64(uint64_t Value) const; - - - /// EmitLabelDifference - Emit something like ".long Hi-Lo" where the size - /// in bytes of the directive is specified by Size and Hi/Lo specify the - /// labels. This implicitly uses .set if it is available. - void EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, - unsigned Size) const; - - //===------------------------------------------------------------------===// - /// EmitAlignment - Emit an alignment directive to the specified power of /// two boundary. For example, if you pass in 3 here, you will get an 8 /// byte alignment. If a global value is specified, and if that global has @@ -301,11 +219,69 @@ namespace llvm { void EmitAlignment(unsigned NumBits, const GlobalValue *GV = 0, unsigned ForcedAlignBits = 0, bool UseFillExpr = true) const; + + /// EmitBasicBlockStart - This method prints the label for the specified + /// MachineBasicBlock, an alignment (if present) and a comment describing + /// it if appropriate. + void EmitBasicBlockStart(const MachineBasicBlock *MBB) const; + + + /// EmitGlobalConstant - Print a general LLVM constant to the .s file. + void EmitGlobalConstant(const Constant *CV, unsigned AddrSpace = 0); + + + //===------------------------------------------------------------------===// + // Overridable Hooks + //===------------------------------------------------------------------===// + + // Targets can, or in the case of EmitInstruction, must implement these to + // customize output. + + /// EmitStartOfAsmFile - This virtual method can be overridden by targets + /// that want to emit something at the start of their file. + virtual void EmitStartOfAsmFile(Module &) {} + + /// EmitEndOfAsmFile - This virtual method can be overridden by targets that + /// want to emit something at the end of their file. + virtual void EmitEndOfAsmFile(Module &) {} + + /// EmitFunctionBodyStart - Targets can override this to emit stuff before + /// the first basic block in the function. + virtual void EmitFunctionBodyStart() {} + + /// EmitFunctionBodyEnd - Targets can override this to emit stuff after + /// the last basic block in the function. + virtual void EmitFunctionBodyEnd() {} + + /// EmitInstruction - Targets should implement this to emit instructions. + virtual void EmitInstruction(const MachineInstr *) { + assert(0 && "EmitInstruction not implemented"); + } + + virtual void EmitFunctionEntryLabel(); + + virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV); + + /// isBlockOnlyReachableByFallthough - Return true if the basic block has + /// exactly one predecessor and the control transfer mechanism between + /// the predecessor and this block is a fall-through. + virtual bool + isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const; + + //===------------------------------------------------------------------===// + // Symbol Lowering Routines. + //===------------------------------------------------------------------===// + public: - /// printDeclare - This method prints a local variable declaration used by - /// debug tables. - void printDeclare(const MachineInstr *MI) const; - + /// GetTempSymbol - Return the MCSymbol corresponding to the assembler + /// temporary label with the specified stem and unique ID. + MCSymbol *GetTempSymbol(StringRef Name, unsigned ID) const; + + /// GetTempSymbol - Return an assembler temporary label with the specified + /// stem. + MCSymbol *GetTempSymbol(StringRef Name) const; + + /// GetSymbolWithGlobalValueBase - Return the MCSymbol for a symbol with /// global value name as its base, with the specified suffix, and where the /// symbol is forced to have private linkage if ForcePrivate is true. @@ -332,49 +308,131 @@ namespace llvm { MCSymbol *GetBlockAddressSymbol(const BlockAddress *BA) const; MCSymbol *GetBlockAddressSymbol(const BasicBlock *BB) const; - /// EmitBasicBlockStart - This method prints the label for the specified - /// MachineBasicBlock, an alignment (if present) and a comment describing - /// it if appropriate. - void EmitBasicBlockStart(const MachineBasicBlock *MBB) const; + //===------------------------------------------------------------------===// + // Emission Helper Routines. + //===------------------------------------------------------------------===// + public: + /// printOffset - This is just convenient handler for printing offsets. + void printOffset(int64_t Offset, raw_ostream &OS) const; + /// EmitInt8 - Emit a byte directive and value. + /// + void EmitInt8(int Value) const; - // Data emission. + /// EmitInt16 - Emit a short directive and value. + /// + void EmitInt16(int Value) const; - /// EmitGlobalConstant - Print a general LLVM constant to the .s file. - void EmitGlobalConstant(const Constant* CV, unsigned AddrSpace = 0); + /// EmitInt32 - Emit a long directive and value. + /// + void EmitInt32(int Value) const; - protected: - virtual void EmitFunctionEntryLabel(); + /// EmitLabelDifference - Emit something like ".long Hi-Lo" where the size + /// in bytes of the directive is specified by Size and Hi/Lo specify the + /// labels. This implicitly uses .set if it is available. + void EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, + unsigned Size) const; - virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV); - - /// printOffset - This is just convenient handler for printing offsets. - void printOffset(int64_t Offset) const; - - /// isBlockOnlyReachableByFallthough - Return true if the basic block has - /// exactly one predecessor and the control transfer mechanism between - /// the predecessor and this block is a fall-through. - virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const; + //===------------------------------------------------------------------===// + // Dwarf Emission Helper Routines + //===------------------------------------------------------------------===// + + /// EmitSLEB128 - emit the specified signed leb128 value. + void EmitSLEB128(int Value, const char *Desc = 0) const; + + /// EmitULEB128 - emit the specified unsigned leb128 value. + void EmitULEB128(unsigned Value, const char *Desc = 0, + unsigned PadTo = 0) const; + + /// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value. + void EmitCFAByte(unsigned Val) const; + /// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an + /// encoding. If verbose assembly output is enabled, we output comments + /// describing the encoding. Desc is a string saying what the encoding is + /// specifying (e.g. "LSDA"). + void EmitEncodingByte(unsigned Val, const char *Desc = 0) const; + + /// GetSizeOfEncodedValue - Return the size of the encoding in bytes. + unsigned GetSizeOfEncodedValue(unsigned Encoding) const; + + /// EmitReference - Emit a reference to a label with a specified encoding. + /// + void EmitReference(const MCSymbol *Sym, unsigned Encoding) const; + void EmitReference(const GlobalValue *GV, unsigned Encoding) const; + + /// EmitSectionOffset - Emit the 4-byte offset of Label from the start of + /// its section. This can be done with a special directive if the target + /// supports it (e.g. cygwin) or by emitting it as an offset from a label at + /// the start of the section. + /// + /// SectionLabel is a temporary label emitted at the start of the section + /// that Label lives in. + void EmitSectionOffset(const MCSymbol *Label, + const MCSymbol *SectionLabel) const; + + //===------------------------------------------------------------------===// + // Dwarf Lowering Routines + //===------------------------------------------------------------------===// + + /// EmitFrameMoves - Emit frame instructions to describe the layout of the + /// frame. + void EmitFrameMoves(const std::vector<MachineMove> &Moves, + MCSymbol *BaseLabel, bool isEH) const; + + + //===------------------------------------------------------------------===// + // Inline Asm Support + //===------------------------------------------------------------------===// + public: + // These are hooks that targets can override to implement inline asm + // support. These should probably be moved out of AsmPrinter someday. + + /// PrintSpecial - Print information related to the specified machine instr + /// that is independent of the operand, and may be independent of the instr + /// itself. This can be useful for portably encoding the comment character + /// or other bits of target-specific knowledge into the asmstrings. The + /// syntax used is ${:comment}. Targets can override this to add support + /// for their own strange codes. + virtual void PrintSpecial(const MachineInstr *MI, raw_ostream &OS, + const char *Code) const; + + /// PrintAsmOperand - Print the specified operand of MI, an INLINEASM + /// instruction, using the specified assembler variant. Targets should + /// override this to format as appropriate. This method can return true if + /// the operand is erroneous. + virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &OS); + + /// PrintAsmMemoryOperand - Print the specified operand of MI, an INLINEASM + /// instruction, using the specified assembler variant as an address. + /// Targets should override this to format as appropriate. This method can + /// return true if the operand is erroneous. + virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode, + raw_ostream &OS); + private: + /// Private state for PrintSpecial() + // Assign a unique ID to this machine instruction. + mutable const MachineInstr *LastMI; + mutable unsigned LastFn; + mutable unsigned Counter; + mutable unsigned SetCounter; - /// processDebugLoc - Processes the debug information of each machine - /// instruction's DebugLoc. - void processDebugLoc(const MachineInstr *MI, bool BeforePrintingInsn); + /// EmitInlineAsm - Emit a blob of inline asm to the output streamer. + void EmitInlineAsm(StringRef Str, unsigned LocCookie) const; - void printLabelInst(const MachineInstr *MI) const; - - /// printInlineAsm - This method formats and prints the specified machine + /// EmitInlineAsm - This method formats and emits the specified machine /// instruction that is an inline asm. - void printInlineAsm(const MachineInstr *MI) const; - - /// printImplicitDef - This method prints the specified machine instruction - /// that is an implicit def. - void printImplicitDef(const MachineInstr *MI) const; - - /// printKill - This method prints the specified kill machine instruction. - void printKill(const MachineInstr *MI) const; + void EmitInlineAsm(const MachineInstr *MI) const; + //===------------------------------------------------------------------===// + // Internal Implementation Details + //===------------------------------------------------------------------===// + /// EmitVisibility - This emits visibility information about symbol, if /// this is suported by the target. void EmitVisibility(MCSymbol *Sym, unsigned Visibility) const; diff --git a/include/llvm/CodeGen/DwarfWriter.h b/include/llvm/CodeGen/DwarfWriter.h deleted file mode 100644 index 494400ee2c98..000000000000 --- a/include/llvm/CodeGen/DwarfWriter.h +++ /dev/null @@ -1,96 +0,0 @@ -//===-- llvm/CodeGen/DwarfWriter.h - Dwarf Framework ------------*- 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 debug and exception info into -// asm files. For Details on the Dwarf 3 specfication see DWARF Debugging -// Information Format V.3 reference manual http://dwarf.freestandards.org , -// -// The role of the Dwarf Writer class is to extract information from the -// MachineModuleInfo object, organize it in Dwarf form and then emit it into asm -// the current asm file using data and high level Dwarf directives. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_DWARFWRITER_H -#define LLVM_CODEGEN_DWARFWRITER_H - -#include "llvm/Pass.h" -#include "llvm/Target/TargetMachine.h" - -namespace llvm { - -class AsmPrinter; -class DwarfDebug; -class DwarfException; -class MachineModuleInfo; -class MachineFunction; -class MachineInstr; -class Value; -class Module; -class MDNode; -class MCAsmInfo; -class MCSymbol; -class raw_ostream; -class Instruction; -class DICompileUnit; -class DISubprogram; -class DIVariable; - -//===----------------------------------------------------------------------===// -// DwarfWriter - Emits Dwarf debug and exception handling directives. -// - -class DwarfWriter : public ImmutablePass { -private: - /// DD - Provides the DwarfWriter debug implementation. - /// - DwarfDebug *DD; - - /// DE - Provides the DwarfWriter exception implementation. - /// - DwarfException *DE; - -public: - static char ID; // Pass identification, replacement for typeid - - DwarfWriter(); - virtual ~DwarfWriter(); - - //===--------------------------------------------------------------------===// - // Main entry points. - // - - /// BeginModule - Emit all Dwarf sections that should come prior to the - /// content. - void BeginModule(Module *M, MachineModuleInfo *MMI, raw_ostream &OS, - AsmPrinter *A, const MCAsmInfo *T); - - /// EndModule - Emit all Dwarf sections that should come after the content. - /// - void EndModule(); - - /// BeginFunction - Gather pre-function debug information. Assumes being - /// emitted immediately after the function entry point. - void BeginFunction(const MachineFunction *MF); - - /// EndFunction - Gather and emit post-function debug information. - /// - void EndFunction(const MachineFunction *MF); - - /// ShouldEmitDwarfDebug - Returns true if Dwarf debugging declarations should - /// be emitted. - bool ShouldEmitDwarfDebug() const; - - void BeginScope(const MachineInstr *MI); - void EndScope(const MachineInstr *MI); -}; - -} // end llvm namespace - -#endif diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index 9d0f0d9e57b9..8d336654411c 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -27,8 +27,6 @@ class MachineBasicBlock; class MachineConstantPool; class MachineFunction; class MachineFrameInfo; -class MachineModuleInfo; -class DwarfWriter; class MachineRegisterInfo; class TargetData; class TargetInstrInfo; @@ -50,8 +48,6 @@ protected: SmallSet<Instruction*, 8> &CatchInfoLost; #endif MachineFunction &MF; - MachineModuleInfo *MMI; - DwarfWriter *DW; MachineRegisterInfo &MRI; MachineFrameInfo &MFI; MachineConstantPool &MCP; @@ -116,8 +112,6 @@ public: protected: FastISel(MachineFunction &mf, - MachineModuleInfo *mmi, - DwarfWriter *dw, DenseMap<const Value *, unsigned> &vm, DenseMap<const BasicBlock *, MachineBasicBlock *> &bm, DenseMap<const AllocaInst *, int> &am diff --git a/include/llvm/CodeGen/GCMetadataPrinter.h b/include/llvm/CodeGen/GCMetadataPrinter.h index 62875c398b89..3703545bb6f6 100644 --- a/include/llvm/CodeGen/GCMetadataPrinter.h +++ b/include/llvm/CodeGen/GCMetadataPrinter.h @@ -27,8 +27,6 @@ namespace llvm { class GCMetadataPrinter; - class raw_ostream; - class MCAsmInfo; /// GCMetadataPrinterRegistry - The GC assembly printer registry uses all the /// defaults from Registry. @@ -63,11 +61,9 @@ namespace llvm { iterator end() { return S->end(); } /// beginAssembly/finishAssembly - Emit module metadata as assembly code. - virtual void beginAssembly(raw_ostream &OS, AsmPrinter &AP, - const MCAsmInfo &MAI); + virtual void beginAssembly(AsmPrinter &AP); - virtual void finishAssembly(raw_ostream &OS, AsmPrinter &AP, - const MCAsmInfo &MAI); + virtual void finishAssembly(AsmPrinter &AP); virtual ~GCMetadataPrinter(); }; diff --git a/include/llvm/CodeGen/MachineDominators.h b/include/llvm/CodeGen/MachineDominators.h index 086528aaf57c..48695d500b19 100644 --- a/include/llvm/CodeGen/MachineDominators.h +++ b/include/llvm/CodeGen/MachineDominators.h @@ -156,8 +156,13 @@ public: inline void splitBlock(MachineBasicBlock* NewBB) { DT->splitBlock(NewBB); } - - + + /// isReachableFromEntry - Return true if A is dominated by the entry + /// block of the function containing it. + bool isReachableFromEntry(MachineBasicBlock *A) { + return DT->isReachableFromEntry(A); + } + virtual void releaseMemory(); virtual void print(raw_ostream &OS, const Module*) const; diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h index 043e97f9a7cd..c7c53006f687 100644 --- a/include/llvm/CodeGen/MachineFrameInfo.h +++ b/include/llvm/CodeGen/MachineFrameInfo.h @@ -14,12 +14,9 @@ #ifndef LLVM_CODEGEN_MACHINEFRAMEINFO_H #define LLVM_CODEGEN_MACHINEFRAMEINFO_H -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/System/DataTypes.h" #include <cassert> -#include <limits> #include <vector> namespace llvm { @@ -27,26 +24,21 @@ class raw_ostream; class TargetData; class TargetRegisterClass; class Type; -class MachineModuleInfo; class MachineFunction; class MachineBasicBlock; class TargetFrameInfo; +class BitVector; /// The CalleeSavedInfo class tracks the information need to locate where a /// callee saved register in the current frame. class CalleeSavedInfo { - -private: unsigned Reg; const TargetRegisterClass *RegClass; int FrameIdx; public: CalleeSavedInfo(unsigned R, const TargetRegisterClass *RC, int FI = 0) - : Reg(R) - , RegClass(RC) - , FrameIdx(FI) - {} + : Reg(R), RegClass(RC), FrameIdx(FI) {} // Accessors. unsigned getReg() const { return Reg; } @@ -188,13 +180,6 @@ class MachineFrameInfo { /// spill slots. SmallVector<bool, 8> SpillObjects; - /// MMI - This field is set (via setMachineModuleInfo) by a module info - /// consumer (ex. DwarfWriter) to indicate that frame layout information - /// should be acquired. Typically, it's the responsibility of the target's - /// TargetRegisterInfo prologue/epilogue emitting code to inform - /// MachineModuleInfo of frame layouts. - MachineModuleInfo *MMI; - /// TargetFrameInfo - Target information about frame layout. /// const TargetFrameInfo &TFI; @@ -208,7 +193,6 @@ public: StackProtectorIdx = -1; MaxCallFrameSize = 0; CSIValid = false; - MMI = 0; } /// hasStackObjects - Return true if there are any stack objects in this @@ -451,14 +435,6 @@ public: /// method always returns an empty set. BitVector getPristineRegs(const MachineBasicBlock *MBB) const; - /// getMachineModuleInfo - Used by a prologue/epilogue - /// emitter (TargetRegisterInfo) to provide frame layout information. - MachineModuleInfo *getMachineModuleInfo() const { return MMI; } - - /// setMachineModuleInfo - Used by a meta info consumer (DwarfWriter) to - /// indicate that frame layout information should be gathered. - void setMachineModuleInfo(MachineModuleInfo *mmi) { MMI = mmi; } - /// print - Used by the MachineFunction printer to print information about /// stack objects. Implemented in MachineFunction.cpp /// diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index 59b171850d0d..b3609c2ea73e 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -32,6 +32,7 @@ class MachineRegisterInfo; class MachineFrameInfo; class MachineConstantPool; class MachineJumpTableInfo; +class MachineModuleInfo; class MCContext; class Pass; class TargetMachine; @@ -72,7 +73,8 @@ class MachineFunction { Function *Fn; const TargetMachine &Target; MCContext &Ctx; - + MachineModuleInfo &MMI; + // RegInfo - Information about each register in use in the function. MachineRegisterInfo *RegInfo; @@ -107,8 +109,8 @@ class MachineFunction { typedef ilist<MachineBasicBlock> BasicBlockListType; BasicBlockListType BasicBlocks; - // Default debug location. Used to print out the debug label at the beginning - // of a function. + /// Default debug location. Used to print out the debug label at the beginning + /// of a function. DebugLoc DefaultDebugLoc; /// FunctionNumber - This provides a unique ID for each function emitted in @@ -116,17 +118,17 @@ class MachineFunction { /// unsigned FunctionNumber; - // The alignment of the function. + /// The alignment of the function. unsigned Alignment; MachineFunction(const MachineFunction &); // DO NOT IMPLEMENT void operator=(const MachineFunction&); // DO NOT IMPLEMENT - public: MachineFunction(Function *Fn, const TargetMachine &TM, unsigned FunctionNum, - MCContext &Ctx); + MachineModuleInfo &MMI); ~MachineFunction(); + MachineModuleInfo &getMMI() const { return MMI; } MCContext &getContext() const { return Ctx; } /// getFunction - Return the LLVM function that this machine code represents diff --git a/include/llvm/CodeGen/MachineFunctionAnalysis.h b/include/llvm/CodeGen/MachineFunctionAnalysis.h index ee2c6ddc81f3..75dbaab973d8 100644 --- a/include/llvm/CodeGen/MachineFunctionAnalysis.h +++ b/include/llvm/CodeGen/MachineFunctionAnalysis.h @@ -39,7 +39,7 @@ public: CodeGenOpt::Level getOptLevel() const { return OptLevel; } private: - virtual bool doInitialization(Module &) { NextFnNum = 1; return false; } + virtual bool doInitialization(Module &M); virtual bool runOnFunction(Function &F); virtual void releaseMemory(); virtual void getAnalysisUsage(AnalysisUsage &AU) const; diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h index d610390b6357..17da43b7d621 100644 --- a/include/llvm/CodeGen/MachineModuleInfo.h +++ b/include/llvm/CodeGen/MachineModuleInfo.h @@ -100,6 +100,9 @@ class MachineModuleInfo : public ImmutablePass { /// Context - This is the MCContext used for the entire code generator. MCContext Context; + /// TheModule - This is the LLVM Module being worked on. + Module *TheModule; + /// ObjFileMMI - This is the object-file-format-specific implementation of /// MachineModuleInfoImpl, which lets targets accumulate whatever info they /// want. @@ -176,6 +179,9 @@ public: const MCContext &getContext() const { return Context; } MCContext &getContext() { return Context; } + void setModule(Module *M) { TheModule = M; } + Module *getModule() const { return TheModule; } + /// getInfo - Keep track of various per-function pieces of information for /// backends that would like to do so. /// diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index 81e9ab31529e..9563d0811cf5 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -27,7 +27,6 @@ namespace llvm { class SUnit; class MachineConstantPool; class MachineFunction; - class MachineModuleInfo; class MachineRegisterInfo; class MachineInstr; class TargetRegisterInfo; diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index ef5d7e2a8959..5dd0aa8705f3 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -29,11 +29,9 @@ namespace llvm { class AliasAnalysis; -class DwarfWriter; class FunctionLoweringInfo; class MachineConstantPoolValue; class MachineFunction; -class MachineModuleInfo; class MDNode; class SDNodeOrdering; class SDDbgValue; @@ -122,9 +120,7 @@ class SelectionDAG { TargetLowering &TLI; MachineFunction *MF; FunctionLoweringInfo &FLI; - MachineModuleInfo *MMI; - DwarfWriter *DW; - LLVMContext* Context; + LLVMContext *Context; /// EntryNode - The starting token. SDNode EntryNode; @@ -182,7 +178,7 @@ public: /// init - Prepare this SelectionDAG to process code in the given /// MachineFunction. /// - void init(MachineFunction &mf, MachineModuleInfo *mmi, DwarfWriter *dw); + void init(MachineFunction &mf); /// clear - Clear state and free memory necessary to make this /// SelectionDAG ready to process a new block. @@ -193,8 +189,6 @@ public: const TargetMachine &getTarget() const; TargetLowering &getTargetLoweringInfo() const { return TLI; } FunctionLoweringInfo &getFunctionLoweringInfo() const { return FLI; } - MachineModuleInfo *getMachineModuleInfo() const { return MMI; } - DwarfWriter *getDwarfWriter() const { return DW; } LLVMContext *getContext() const {return Context; } /// viewGraph - Pop up a GraphViz/gv window with the DAG rendered using 'dot'. @@ -532,17 +526,17 @@ public: SDValue getStackArgumentTokenFactor(SDValue Chain); SDValue getMemcpy(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Src, - SDValue Size, unsigned Align, bool AlwaysInline, + SDValue Size, unsigned Align, bool isVol, bool AlwaysInline, const Value *DstSV, uint64_t DstSVOff, const Value *SrcSV, uint64_t SrcSVOff); SDValue getMemmove(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Src, - SDValue Size, unsigned Align, + SDValue Size, unsigned Align, bool isVol, const Value *DstSV, uint64_t DstOSVff, const Value *SrcSV, uint64_t SrcSVOff); SDValue getMemset(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Src, - SDValue Size, unsigned Align, + SDValue Size, unsigned Align, bool isVol, const Value *DstSV, uint64_t DstSVOff); /// getSetCC - Helper function to make it easier to build SetCC's if you just diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h index def09c76fcbe..3c000f032c97 100644 --- a/include/llvm/CodeGen/SelectionDAGISel.h +++ b/include/llvm/CodeGen/SelectionDAGISel.h @@ -29,8 +29,6 @@ namespace llvm { class MachineBasicBlock; class MachineFunction; class MachineInstr; - class MachineModuleInfo; - class DwarfWriter; class TargetLowering; class TargetInstrInfo; class FunctionLoweringInfo; @@ -284,8 +282,6 @@ private: const SDValue *Ops, unsigned NumOps, unsigned EmitNodeInfo); void SelectAllBasicBlocks(Function &Fn, MachineFunction &MF, - MachineModuleInfo *MMI, - DwarfWriter *DW, const TargetInstrInfo &TII); void FinishBasicBlock(); diff --git a/include/llvm/IntrinsicInst.h b/include/llvm/IntrinsicInst.h index d86b33ef50a8..bd8a8c4e9d39 100644 --- a/include/llvm/IntrinsicInst.h +++ b/include/llvm/IntrinsicInst.h @@ -133,6 +133,13 @@ namespace llvm { return getAlignmentCst()->getZExtValue(); } + ConstantInt *getVolatileCst() const { + return cast<ConstantInt>(const_cast<Value*>(getOperand(5))); + } + bool isVolatile() const { + return getVolatileCst()->getZExtValue() != 0; + } + /// getDest - This is just like getRawDest, but it strips off any cast /// instructions that feed it, giving the original input. The returned /// value is guaranteed to be a pointer. @@ -155,7 +162,11 @@ namespace llvm { void setAlignment(Constant* A) { setOperand(4, A); } - + + void setVolatile(Constant* V) { + setOperand(5, V); + } + const Type *getAlignmentType() const { return getOperand(4)->getType(); } diff --git a/include/llvm/Intrinsics.td b/include/llvm/Intrinsics.td index d66e80fb22fb..8bbfd774bdb5 100644 --- a/include/llvm/Intrinsics.td +++ b/include/llvm/Intrinsics.td @@ -224,16 +224,16 @@ def int_stackprotector : Intrinsic<[], // def int_memcpy : Intrinsic<[], - [llvm_ptr_ty, llvm_ptr_ty, llvm_anyint_ty, - llvm_i32_ty], + [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, + llvm_i32_ty, llvm_i1_ty], [IntrWriteArgMem, NoCapture<0>, NoCapture<1>]>; def int_memmove : Intrinsic<[], - [llvm_ptr_ty, llvm_ptr_ty, llvm_anyint_ty, - llvm_i32_ty], + [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, + llvm_i32_ty, llvm_i1_ty], [IntrWriteArgMem, NoCapture<0>, NoCapture<1>]>; def int_memset : Intrinsic<[], - [llvm_ptr_ty, llvm_i8_ty, llvm_anyint_ty, - llvm_i32_ty], + [llvm_anyptr_ty, llvm_i8_ty, llvm_anyint_ty, + llvm_i32_ty, llvm_i1_ty], [IntrWriteArgMem, NoCapture<0>]>; // These functions do not actually read memory, but they are sensitive to the diff --git a/include/llvm/LLVMContext.h b/include/llvm/LLVMContext.h index ea7f4a2d8e9d..43548407f681 100644 --- a/include/llvm/LLVMContext.h +++ b/include/llvm/LLVMContext.h @@ -50,6 +50,24 @@ public: /// custom metadata IDs registered in this LLVMContext. ID #0 is not used, /// so it is filled in as an empty string. void getMDKindNames(SmallVectorImpl<StringRef> &Result) const; + + /// setInlineAsmDiagnosticHandler - This method sets a handler that is invoked + /// when problems with inline asm are detected by the backend. The first + /// argument is a function pointer (of type SourceMgr::DiagHandlerTy) and the + /// second is a context pointer that gets passed into the DiagHandler. + /// + /// LLVMContext doesn't take ownership or interpreter either of these + /// pointers. + void setInlineAsmDiagnosticHandler(void *DiagHandler, void *DiagContext = 0); + + /// getInlineAsmDiagnosticHandler - Return the diagnostic handler set by + /// setInlineAsmDiagnosticHandler. + void *getInlineAsmDiagnosticHandler() const; + + /// getInlineAsmDiagnosticContext - Return the diagnostic context set by + /// setInlineAsmDiagnosticHandler. + void *getInlineAsmDiagnosticContext() const; + }; /// getGlobalContext - Returns a global context. This is for LLVM clients that diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index 4dfe9f0e52eb..33def8618990 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -223,14 +223,6 @@ namespace llvm { //===--- Dwarf Emission Directives -----------------------------------===// - /// AbsoluteDebugSectionOffsets - True if we should emit abolute section - /// offsets for debug information. - bool AbsoluteDebugSectionOffsets; // Defaults to false. - - /// AbsoluteEHSectionOffsets - True if we should emit abolute section - /// offsets for EH information. Defaults to false. - bool AbsoluteEHSectionOffsets; - /// HasLEB128 - True if target asm supports leb128 directives. bool HasLEB128; // Defaults to false. @@ -389,12 +381,6 @@ namespace llvm { MCSymbolAttr getProtectedVisibilityAttr() const { return ProtectedVisibilityAttr; } - bool isAbsoluteDebugSectionOffsets() const { - return AbsoluteDebugSectionOffsets; - } - bool isAbsoluteEHSectionOffsets() const { - return AbsoluteEHSectionOffsets; - } bool hasLEB128() const { return HasLEB128; } diff --git a/include/llvm/MC/MCInstPrinter.h b/include/llvm/MC/MCInstPrinter.h index d2ddc5bb42b2..4839a83dba5c 100644 --- a/include/llvm/MC/MCInstPrinter.h +++ b/include/llvm/MC/MCInstPrinter.h @@ -20,26 +20,23 @@ class StringRef; /// that converts an MCInst to valid target assembly syntax. class MCInstPrinter { protected: - /// O - The main stream to emit instruction text to. - raw_ostream &O; - /// CommentStream - a stream that comments can be emitted to if desired. /// Each comment must end with a newline. This will be null if verbose /// assembly emission is disable. raw_ostream *CommentStream; const MCAsmInfo &MAI; public: - MCInstPrinter(raw_ostream &o, const MCAsmInfo &mai) - : O(o), CommentStream(0), MAI(mai) {} + MCInstPrinter(const MCAsmInfo &mai) + : CommentStream(0), MAI(mai) {} virtual ~MCInstPrinter(); /// setCommentStream - Specify a stream to emit comments to. void setCommentStream(raw_ostream &OS) { CommentStream = &OS; } - /// printInst - Print the specified MCInst to the current raw_ostream. + /// printInst - Print the specified MCInst to the specified raw_ostream. /// - virtual void printInst(const MCInst *MI) = 0; + virtual void printInst(const MCInst *MI, raw_ostream &OS) = 0; /// getOpcodeName - Return the name of the specified opcode enum (e.g. /// "MOV32ri") or empty if we can't resolve it. diff --git a/include/llvm/MC/MCParser/AsmParser.h b/include/llvm/MC/MCParser/AsmParser.h index 06e0920950d4..23f4a1fb72a2 100644 --- a/include/llvm/MC/MCParser/AsmParser.h +++ b/include/llvm/MC/MCParser/AsmParser.h @@ -64,7 +64,7 @@ public: const MCAsmInfo &MAI); ~AsmParser(); - bool Run(bool NoInitialTextSection); + bool Run(bool NoInitialTextSection, bool NoFinalize = false); void AddDirectiveHandler(StringRef Directive, diff --git a/include/llvm/MC/MCSection.h b/include/llvm/MC/MCSection.h index 4a1c46ccb926..e9c19fce20aa 100644 --- a/include/llvm/MC/MCSection.h +++ b/include/llvm/MC/MCSection.h @@ -39,6 +39,14 @@ namespace llvm { virtual void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS) const = 0; + + /// isBaseAddressKnownZero - Return true if we know that this section will + /// get a base address of zero. In cases where we know that this is true we + /// can emit section offsets as direct references to avoid a subtraction + /// from the base of the section, saving a relocation. + virtual bool isBaseAddressKnownZero() const { + return false; + } }; class MCSectionCOFF : public MCSection { diff --git a/include/llvm/MC/MCSectionELF.h b/include/llvm/MC/MCSectionELF.h index cdd2f73b3484..e550cd2c1111 100644 --- a/include/llvm/MC/MCSectionELF.h +++ b/include/llvm/MC/MCSectionELF.h @@ -172,6 +172,11 @@ public: virtual void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS) const; + /// isBaseAddressKnownZero - We know that non-allocatable sections (like + /// debug info) have a base of zero. + virtual bool isBaseAddressKnownZero() const { + return (getFlags() & SHF_ALLOC) == 0; + } /// PrintTargetSpecificSectionFlags - Targets that define their own /// MCSectionELF subclasses with target specific section flags should diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index bdcfdb2debee..4667c41d6235 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -62,9 +62,13 @@ class TargetAsmBackend; /// @name Assembly File Formatting. /// @{ - /// isVerboseAsm - Return true if this streamer supports verbose assembly at - /// all. + /// isVerboseAsm - Return true if this streamer supports verbose assembly + /// and if it is enabled. virtual bool isVerboseAsm() const { return false; } + + /// hasRawTextSupport - Return true if this asm streamer supports emitting + /// unformatted text to the .s file with EmitRawText. + virtual bool hasRawTextSupport() const { return false; } /// AddComment - Add a comment that can be emitted to the generated .s /// file if applicable as a QoI issue to make the output of the compiler @@ -278,6 +282,12 @@ class TargetAsmBackend; /// section. virtual void EmitInstruction(const MCInst &Inst) = 0; + /// EmitRawText - If this file is backed by a assembly streamer, this dumps + /// the specified string in the output .s file. This capability is + /// indicated by the hasRawTextSupport() predicate. By default this aborts. + virtual void EmitRawText(StringRef String); + void EmitRawText(const Twine &String); + /// Finish - Finish emission of machine code and flush any output. virtual void Finish() = 0; }; diff --git a/include/llvm/Support/Allocator.h b/include/llvm/Support/Allocator.h index eb6c2d1e25a7..148d47e785c7 100644 --- a/include/llvm/Support/Allocator.h +++ b/include/llvm/Support/Allocator.h @@ -202,7 +202,7 @@ public: (char *)Slab + Slab->Size; for (char *Ptr = (char*)(Slab+1); Ptr < End; Ptr += sizeof(T)) { Ptr = Allocator.AlignPtr(Ptr, alignof<T>()); - if (Ptr + sizeof(T) <= End) + if (Ptr + sizeof(T) <= End) reinterpret_cast<T*>(Ptr)->~T(); } Slab = Slab->NextPtr; diff --git a/include/llvm/Support/IRBuilder.h b/include/llvm/Support/IRBuilder.h index faa8fa3aee2b..660c9f8001b2 100644 --- a/include/llvm/Support/IRBuilder.h +++ b/include/llvm/Support/IRBuilder.h @@ -917,6 +917,11 @@ public: Value *Args[] = { Arg1, Arg2, Arg3, Arg4 }; return Insert(CallInst::Create(Callee, Args, Args+4), Name); } + CallInst *CreateCall5(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3, + Value *Arg4, Value *Arg5, const Twine &Name = "") { + Value *Args[] = { Arg1, Arg2, Arg3, Arg4, Arg5 }; + return Insert(CallInst::Create(Callee, Args, Args+5), Name); + } template<typename InputIterator> CallInst *CreateCall(Value *Callee, InputIterator ArgBegin, diff --git a/include/llvm/Support/IRReader.h b/include/llvm/Support/IRReader.h index 66314e057ef6..2a43c5fa906a 100644 --- a/include/llvm/Support/IRReader.h +++ b/include/llvm/Support/IRReader.h @@ -38,7 +38,8 @@ namespace llvm { std::string ErrMsg; Module *M = getLazyBitcodeModule(Buffer, Context, &ErrMsg); if (M == 0) { - Err = SMDiagnostic(Buffer->getBufferIdentifier(), -1, -1, ErrMsg, ""); + Err = SMDiagnostic(SMLoc(), Buffer->getBufferIdentifier(), -1, -1, + ErrMsg, ""); // ParseBitcodeFile does not take ownership of the Buffer in the // case of an error. delete Buffer; @@ -59,7 +60,7 @@ namespace llvm { std::string ErrMsg; MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrMsg); if (F == 0) { - Err = SMDiagnostic(Filename, -1, -1, + Err = SMDiagnostic(SMLoc(), Filename, -1, -1, "Could not open input file '" + Filename + "'", ""); return 0; } @@ -81,7 +82,8 @@ namespace llvm { // ParseBitcodeFile does not take ownership of the Buffer. delete Buffer; if (M == 0) - Err = SMDiagnostic(Buffer->getBufferIdentifier(), -1, -1, ErrMsg, ""); + Err = SMDiagnostic(SMLoc(), Buffer->getBufferIdentifier(), + -1, -1, ErrMsg, ""); return M; } @@ -97,7 +99,7 @@ namespace llvm { std::string ErrMsg; MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrMsg); if (F == 0) { - Err = SMDiagnostic(Filename, -1, -1, + Err = SMDiagnostic(SMLoc(), Filename, -1, -1, "Could not open input file '" + Filename + "'", ""); return 0; } diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h index f56241c5790b..80d11ae062f7 100644 --- a/include/llvm/Support/MathExtras.h +++ b/include/llvm/Support/MathExtras.h @@ -459,14 +459,14 @@ inline int64_t abs64(int64_t x) { /// SignExtend32 - Sign extend B-bit number x to 32-bit int. /// Usage int32_t r = SignExtend32<5>(x); -template <unsigned B> inline int32_t SignExtend32(int32_t x) { - return (x << (32 - B)) >> (32 - B); +template <unsigned B> inline int32_t SignExtend32(uint32_t x) { + return int32_t(x << (32 - B)) >> (32 - B); } /// SignExtend64 - Sign extend B-bit number x to 64-bit int. /// Usage int64_t r = SignExtend64<5>(x); -template <unsigned B> inline int64_t SignExtend64(int32_t x) { - return (x << (64 - B)) >> (64 - B); +template <unsigned B> inline int64_t SignExtend64(uint64_t x) { + return int64_t(x << (64 - B)) >> (64 - B); } } // End llvm namespace diff --git a/include/llvm/Support/MemoryBuffer.h b/include/llvm/Support/MemoryBuffer.h index fcea5d20de4b..ef7af6968405 100644 --- a/include/llvm/Support/MemoryBuffer.h +++ b/include/llvm/Support/MemoryBuffer.h @@ -65,13 +65,13 @@ public: /// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note /// that EndPtr[0] must be a null byte and be accessible! - static MemoryBuffer *getMemBuffer(const char *StartPtr, const char *EndPtr, + static MemoryBuffer *getMemBuffer(StringRef InputData, const char *BufferName = ""); /// getMemBufferCopy - Open the specified memory range as a MemoryBuffer, /// copying the contents and taking ownership of it. This has no requirements /// on EndPtr[0]. - static MemoryBuffer *getMemBufferCopy(const char *StartPtr,const char *EndPtr, + static MemoryBuffer *getMemBufferCopy(StringRef InputData, const char *BufferName = ""); /// getNewMemBuffer - Allocate a new MemoryBuffer of the specified size that diff --git a/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h index fd56b16639cb..3e66762ae349 100644 --- a/include/llvm/Support/SourceMgr.h +++ b/include/llvm/Support/SourceMgr.h @@ -31,6 +31,13 @@ namespace llvm { /// SourceMgr - This owns the files read by a parser, handles include stacks, /// and handles diagnostic wrangling. class SourceMgr { +public: + /// DiagHandlerTy - Clients that want to handle their own diagnostics in a + /// custom way can register a function pointer+context as a diagnostic + /// handler. It gets called each time PrintMessage is invoked. + typedef void (*DiagHandlerTy)(const SMDiagnostic&, void *Context, + unsigned LocCookie); +private: struct SrcBuffer { /// Buffer - The memory buffer for the file. MemoryBuffer *Buffer; @@ -51,16 +58,29 @@ class SourceMgr { /// is really private to SourceMgr.cpp. mutable void *LineNoCache; + DiagHandlerTy DiagHandler; + void *DiagContext; + unsigned DiagLocCookie; + SourceMgr(const SourceMgr&); // DO NOT IMPLEMENT void operator=(const SourceMgr&); // DO NOT IMPLEMENT public: - SourceMgr() : LineNoCache(0) {} + SourceMgr() : LineNoCache(0), DiagHandler(0), DiagContext(0) {} ~SourceMgr(); void setIncludeDirs(const std::vector<std::string> &Dirs) { IncludeDirectories = Dirs; } + /// setDiagHandler - Specify a diagnostic handler to be invoked every time + /// PrintMessage is called. Ctx and Cookie are passed into the handler when + /// it is invoked. + void setDiagHandler(DiagHandlerTy DH, void *Ctx = 0, unsigned Cookie = 0) { + DiagHandler = DH; + DiagContext = Ctx; + DiagLocCookie = Cookie; + } + const SrcBuffer &getBufferInfo(unsigned i) const { assert(i < Buffers.size() && "Invalid Buffer ID!"); return Buffers[i]; @@ -76,6 +96,8 @@ public: return Buffers[i].IncludeLoc; } + /// AddNewSourceBuffer - Add a new source buffer to this source manager. This + /// takes ownership of the memory buffer. unsigned AddNewSourceBuffer(MemoryBuffer *F, SMLoc IncludeLoc) { SrcBuffer NB; NB.Buffer = F; @@ -126,6 +148,7 @@ private: /// SMDiagnostic - Instances of this class encapsulate one diagnostic report, /// allowing printing to a raw_ostream as a caret diagnostic. class SMDiagnostic { + SMLoc Loc; std::string Filename; int LineNo, ColumnNo; std::string Message, LineContents; @@ -133,12 +156,20 @@ class SMDiagnostic { public: SMDiagnostic() : LineNo(0), ColumnNo(0), ShowLine(0) {} - SMDiagnostic(const std::string &FN, int Line, int Col, + SMDiagnostic(SMLoc L, const std::string &FN, int Line, int Col, const std::string &Msg, const std::string &LineStr, bool showline = true) - : Filename(FN), LineNo(Line), ColumnNo(Col), Message(Msg), + : Loc(L), Filename(FN), LineNo(Line), ColumnNo(Col), Message(Msg), LineContents(LineStr), ShowLine(showline) {} + SMLoc getLoc() const { return Loc; } + const std::string getFilename() { return Filename; } + int getLineNo() const { return LineNo; } + int getColumnNo() const { return ColumnNo; } + const std::string &getMessage() const { return Message; } + const std::string &getLineContents() const { return LineContents; } + bool getShowLine() const { return ShowLine; } + void Print(const char *ProgName, raw_ostream &S) const; }; diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index 0a7f54937705..462c38f03d27 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -132,8 +132,8 @@ class RegisterClass<string namespace, list<ValueType> regTypes, int alignment, //===----------------------------------------------------------------------===// // DwarfRegNum - This class provides a mapping of the llvm register enumeration // to the register numbering used by gcc and gdb. These values are used by a -// debug information writer (ex. DwarfWriter) to describe where values may be -// located during execution. +// debug information writer to describe where values may be located during +// execution. class DwarfRegNum<list<int> Numbers> { // DwarfNumbers - Numbers used internally by gcc/gdb to identify the register. // These values can be determined by locating the <target>.h file in the @@ -224,10 +224,13 @@ class Instruction { InstrItinClass Itinerary = NoItinerary;// Execution steps used for scheduling. string Constraints = ""; // OperandConstraint, e.g. $src = $dst. - + /// DisableEncoding - List of operand names (e.g. "$op1,$op2") that should not /// be encoded into the output machineinstr. string DisableEncoding = ""; + + /// Target-specific flags. This becomes the TSFlags field in TargetInstrDesc. + bits<32> TSFlags = 0; } /// Predicates - These are extra conditionals which are turned into instruction @@ -372,13 +375,6 @@ class OptionalDefOperand<ValueType ty, dag OpTypes, dag defaultops> // which are global to the target machine. // class InstrInfo { - // If the target wants to associate some target-specific information with each - // instruction, it should provide these two lists to indicate how to assemble - // the target specific information into the 32 bits available. - // - list<string> TSFlagsFields = []; - list<int> TSFlagsShifts = []; - // Target can specify its instructions in either big or little-endian formats. // For instance, while both Sparc and PowerPC are big-endian platforms, the // Sparc manual specifies its instructions in the format [31..0] (big), while diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index f040c9db38ca..1a94b4448ae4 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -47,10 +47,8 @@ namespace llvm { class MachineFrameInfo; class MachineInstr; class MachineJumpTableInfo; - class MachineModuleInfo; class MCContext; class MCExpr; - class DwarfWriter; class SDNode; class SDValue; class SelectionDAG; @@ -1191,7 +1189,7 @@ public: EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, SDValue Chain, SDValue Op1, SDValue Op2, - SDValue Op3, unsigned Align, + SDValue Op3, unsigned Align, bool isVolatile, bool AlwaysInline, const Value *DstSV, uint64_t DstOff, const Value *SrcSV, uint64_t SrcOff) { @@ -1208,7 +1206,7 @@ public: EmitTargetCodeForMemmove(SelectionDAG &DAG, DebugLoc dl, SDValue Chain, SDValue Op1, SDValue Op2, - SDValue Op3, unsigned Align, + SDValue Op3, unsigned Align, bool isVolatile, const Value *DstSV, uint64_t DstOff, const Value *SrcSV, uint64_t SrcOff) { return SDValue(); @@ -1224,7 +1222,7 @@ public: EmitTargetCodeForMemset(SelectionDAG &DAG, DebugLoc dl, SDValue Chain, SDValue Op1, SDValue Op2, - SDValue Op3, unsigned Align, + SDValue Op3, unsigned Align, bool isVolatile, const Value *DstSV, uint64_t DstOff) { return SDValue(); } @@ -1274,7 +1272,6 @@ public: /// or null if the target does not support "fast" ISel. virtual FastISel * createFastISel(MachineFunction &, - MachineModuleInfo *, DwarfWriter *, DenseMap<const Value *, unsigned> &, DenseMap<const BasicBlock *, MachineBasicBlock *> &, DenseMap<const AllocaInst *, int> & diff --git a/include/llvm/Target/TargetRegistry.h b/include/llvm/Target/TargetRegistry.h index 6b6dad8185b0..36bbe000025c 100644 --- a/include/llvm/Target/TargetRegistry.h +++ b/include/llvm/Target/TargetRegistry.h @@ -38,7 +38,6 @@ namespace llvm { class TargetAsmLexer; class TargetAsmParser; class TargetMachine; - class formatted_raw_ostream; class raw_ostream; /// Target - Wrapper for Target specific information. @@ -60,8 +59,7 @@ namespace llvm { typedef TargetMachine *(*TargetMachineCtorTy)(const Target &T, const std::string &TT, const std::string &Features); - typedef AsmPrinter *(*AsmPrinterCtorTy)(formatted_raw_ostream &OS, - TargetMachine &TM, + typedef AsmPrinter *(*AsmPrinterCtorTy)(TargetMachine &TM, MCStreamer &Streamer); typedef TargetAsmBackend *(*AsmBackendCtorTy)(const Target &T, const std::string &TT); @@ -71,8 +69,7 @@ namespace llvm { typedef MCDisassembler *(*MCDisassemblerCtorTy)(const Target &T); typedef MCInstPrinter *(*MCInstPrinterCtorTy)(const Target &T, unsigned SyntaxVariant, - const MCAsmInfo &MAI, - raw_ostream &O); + const MCAsmInfo &MAI); typedef MCCodeEmitter *(*CodeEmitterCtorTy)(const Target &T, TargetMachine &TM, MCContext &Ctx); @@ -234,11 +231,10 @@ namespace llvm { /// createAsmPrinter - Create a target specific assembly printer pass. This /// takes ownership of the MCStreamer object. - AsmPrinter *createAsmPrinter(formatted_raw_ostream &OS, TargetMachine &TM, - MCStreamer &Streamer) const { + AsmPrinter *createAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) const{ if (!AsmPrinterCtorFn) return 0; - return AsmPrinterCtorFn(OS, TM, Streamer); + return AsmPrinterCtorFn(TM, Streamer); } MCDisassembler *createMCDisassembler() const { @@ -248,11 +244,10 @@ namespace llvm { } MCInstPrinter *createMCInstPrinter(unsigned SyntaxVariant, - const MCAsmInfo &MAI, - raw_ostream &O) const { + const MCAsmInfo &MAI) const { if (!MCInstPrinterCtorFn) return 0; - return MCInstPrinterCtorFn(*this, SyntaxVariant, MAI, O); + return MCInstPrinterCtorFn(*this, SyntaxVariant, MAI); } @@ -646,9 +641,8 @@ namespace llvm { } private: - static AsmPrinter *Allocator(formatted_raw_ostream &OS, TargetMachine &TM, - MCStreamer &Streamer) { - return new AsmPrinterImpl(OS, TM, Streamer); + static AsmPrinter *Allocator(TargetMachine &TM, MCStreamer &Streamer) { + return new AsmPrinterImpl(TM, Streamer); } }; diff --git a/include/llvm/Transforms/Utils/BuildLibCalls.h b/include/llvm/Transforms/Utils/BuildLibCalls.h index d278672a1f02..8e76f50bb21e 100644 --- a/include/llvm/Transforms/Utils/BuildLibCalls.h +++ b/include/llvm/Transforms/Utils/BuildLibCalls.h @@ -46,8 +46,8 @@ namespace llvm { /// EmitMemCpy - Emit a call to the memcpy function to the builder. This /// always expects that the size has type 'intptr_t' and Dst/Src are pointers. - Value *EmitMemCpy(Value *Dst, Value *Src, Value *Len, - unsigned Align, IRBuilder<> &B, const TargetData *TD); + Value *EmitMemCpy(Value *Dst, Value *Src, Value *Len, unsigned Align, + bool isVolatile, IRBuilder<> &B, const TargetData *TD); /// EmitMemCpyChk - Emit a call to the __memcpy_chk function to the builder. /// This expects that the Len and ObjSize have type 'intptr_t' and Dst/Src @@ -57,8 +57,8 @@ namespace llvm { /// EmitMemMove - Emit a call to the memmove function to the builder. This /// always expects that the size has type 'intptr_t' and Dst/Src are pointers. - Value *EmitMemMove(Value *Dst, Value *Src, Value *Len, - unsigned Align, IRBuilder<> &B, const TargetData *TD); + Value *EmitMemMove(Value *Dst, Value *Src, Value *Len, unsigned Align, + bool isVolatile, IRBuilder<> &B, const TargetData *TD); /// EmitMemChr - Emit a call to the memchr function. This assumes that Ptr is /// a pointer, Val is an i32 value, and Len is an 'intptr_t' value. @@ -70,8 +70,8 @@ namespace llvm { const TargetData *TD); /// EmitMemSet - Emit a call to the memset function - Value *EmitMemSet(Value *Dst, Value *Val, Value *Len, IRBuilder<> &B, - const TargetData *TD); + Value *EmitMemSet(Value *Dst, Value *Val, Value *Len, bool isVolatile, + IRBuilder<> &B, const TargetData *TD); /// EmitUnaryFloatFnCall - Emit a call to the unary function named 'Name' /// (e.g. 'floor'). This function is known to take a single of type matching diff --git a/lib/Analysis/IVUsers.cpp b/lib/Analysis/IVUsers.cpp index 98a436f79bd8..47b5d4a0f08d 100644 --- a/lib/Analysis/IVUsers.cpp +++ b/lib/Analysis/IVUsers.cpp @@ -142,7 +142,7 @@ static bool getSCEVStartAndStride(const SCEV *&SH, Loop *L, Loop *UseLoop, /// the loop, resulting in reg-reg copies (if we use the pre-inc value when we /// should use the post-inc value). static bool IVUseShouldUsePostIncValue(Instruction *User, Instruction *IV, - Loop *L, DominatorTree *DT) { + const Loop *L, DominatorTree *DT) { // If the user is in the loop, use the preinc value. if (L->contains(User)) return false; diff --git a/lib/AsmParser/Parser.cpp b/lib/AsmParser/Parser.cpp index aac4027fc578..7280cf479f22 100644 --- a/lib/AsmParser/Parser.cpp +++ b/lib/AsmParser/Parser.cpp @@ -44,7 +44,7 @@ Module *llvm::ParseAssemblyFile(const std::string &Filename, SMDiagnostic &Err, std::string ErrorStr; MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrorStr); if (F == 0) { - Err = SMDiagnostic("", -1, -1, + Err = SMDiagnostic(SMLoc(), "", -1, -1, "Could not open input file '" + Filename + "': " + ErrorStr, ""); return 0; @@ -56,7 +56,7 @@ Module *llvm::ParseAssemblyFile(const std::string &Filename, SMDiagnostic &Err, Module *llvm::ParseAssemblyString(const char *AsmString, Module *M, SMDiagnostic &Err, LLVMContext &Context) { MemoryBuffer *F = - MemoryBuffer::getMemBuffer(AsmString, AsmString+strlen(AsmString), + MemoryBuffer::getMemBuffer(StringRef(AsmString, strlen(AsmString)), "<string>"); return ParseAssembly(F, M, Err, Context); diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 625a2b95f205..c86e2411d303 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -13,11 +13,9 @@ #define DEBUG_TYPE "asm-printer" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/Assembly/Writer.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Constants.h" +#include "DwarfDebug.h" +#include "DwarfException.h" #include "llvm/Module.h" -#include "llvm/CodeGen/DwarfWriter.h" #include "llvm/CodeGen/GCMetadataPrinter.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -27,50 +25,59 @@ #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/DebugInfo.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCAsmInfo.h" #include "llvm/Target/Mangler.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetLoweringObjectFile.h" -#include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Statistic.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" -#include "llvm/Support/FormattedStream.h" -#include <cerrno> using namespace llvm; STATISTIC(EmittedInsts, "Number of machine instrs printed"); char AsmPrinter::ID = 0; -AsmPrinter::AsmPrinter(formatted_raw_ostream &o, TargetMachine &tm, - MCStreamer &Streamer) - : MachineFunctionPass(&ID), O(o), - TM(tm), MAI(tm.getMCAsmInfo()), TRI(tm.getRegisterInfo()), +typedef DenseMap<GCStrategy*,GCMetadataPrinter*> gcp_map_type; +static gcp_map_type &getGCMap(void *&P) { + if (P == 0) + P = new gcp_map_type(); + return *(gcp_map_type*)P; +} + + +AsmPrinter::AsmPrinter(TargetMachine &tm, MCStreamer &Streamer) + : MachineFunctionPass(&ID), + TM(tm), MAI(tm.getMCAsmInfo()), OutContext(Streamer.getContext()), OutStreamer(Streamer), LastMI(0), LastFn(0), Counter(~0U), SetCounter(0) { - DW = 0; MMI = 0; + DD = 0; DE = 0; MMI = 0; LI = 0; + GCMetadataPrinters = 0; VerboseAsm = Streamer.isVerboseAsm(); } AsmPrinter::~AsmPrinter() { - for (gcp_iterator I = GCMetadataPrinters.begin(), - E = GCMetadataPrinters.end(); I != E; ++I) - delete I->second; + assert(DD == 0 && DE == 0 && "Debug/EH info didn't get finalized"); + + if (GCMetadataPrinters != 0) { + gcp_map_type &GCMap = getGCMap(GCMetadataPrinters); + + for (gcp_map_type::iterator I = GCMap.begin(), E = GCMap.end(); I != E; ++I) + delete I->second; + delete &GCMap; + GCMetadataPrinters = 0; + } delete &OutStreamer; } @@ -85,18 +92,25 @@ TargetLoweringObjectFile &AsmPrinter::getObjFileLowering() const { return TM.getTargetLowering()->getObjFileLowering(); } + +/// getTargetData - Return information about data layout. +const TargetData &AsmPrinter::getTargetData() const { + return *TM.getTargetData(); +} + /// getCurrentSection() - Return the current section we are emitting to. const MCSection *AsmPrinter::getCurrentSection() const { return OutStreamer.getCurrentSection(); } + void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); MachineFunctionPass::getAnalysisUsage(AU); AU.addRequired<MachineModuleInfo>(); AU.addRequired<GCModuleInfo>(); - if (VerboseAsm) + if (isVerbose()) AU.addRequired<MachineLoopInfo>(); } @@ -124,17 +138,22 @@ bool AsmPrinter::doInitialization(Module &M) { assert(MI && "AsmPrinter didn't require GCModuleInfo?"); for (GCModuleInfo::iterator I = MI->begin(), E = MI->end(); I != E; ++I) if (GCMetadataPrinter *MP = GetOrCreateGCPrinter(*I)) - MP->beginAssembly(O, *this, *MAI); - - if (!M.getModuleInlineAsm().empty()) - O << MAI->getCommentString() << " Start of file scope inline assembly\n" - << M.getModuleInlineAsm() - << '\n' << MAI->getCommentString() - << " End of file scope inline assembly\n"; + MP->beginAssembly(*this); - DW = getAnalysisIfAvailable<DwarfWriter>(); - if (DW) - DW->BeginModule(&M, MMI, O, this, MAI); + // Emit module-level inline asm if it exists. + if (!M.getModuleInlineAsm().empty()) { + OutStreamer.AddComment("Start of file scope inline assembly"); + OutStreamer.AddBlankLine(); + EmitInlineAsm(M.getModuleInlineAsm(), 0/*no loc cookie*/); + OutStreamer.AddComment("End of file scope inline assembly"); + OutStreamer.AddBlankLine(); + } + + if (MAI->doesSupportDebugInformation()) + DD = new DwarfDebug(this, &M); + + if (MAI->doesSupportExceptionHandling()) + DE = new DwarfException(this); return false; } @@ -161,7 +180,7 @@ void AsmPrinter::EmitLinkage(unsigned Linkage, MCSymbol *GVSym) const { // .linkonce discard // FIXME: It would be nice to use .linkonce samesize for non-common // globals. - O << LinkOnce; + OutStreamer.EmitRawText(StringRef(LinkOnce)); } else { // .weak _foo OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak); @@ -210,7 +229,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { if (GVKind.isCommon() || GVKind.isBSSLocal()) { if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. - if (VerboseAsm) { + if (isVerbose()) { WriteAsOperand(OutStreamer.GetCommentOS(), GV, /*PrintType=*/false, GV->getParent()); OutStreamer.GetCommentOS() << '\n'; @@ -263,7 +282,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { EmitLinkage(GV->getLinkage(), GVSym); EmitAlignment(AlignLog, GV); - if (VerboseAsm) { + if (isVerbose()) { WriteAsOperand(OutStreamer.GetCommentOS(), GV, /*PrintType=*/false, GV->getParent()); OutStreamer.GetCommentOS() << '\n'; @@ -297,7 +316,7 @@ void AsmPrinter::EmitFunctionHeader() { if (MAI->hasDotTypeDotSizeDirective()) OutStreamer.EmitSymbolAttribute(CurrentFnSym, MCSA_ELF_TypeFunction); - if (VerboseAsm) { + if (isVerbose()) { WriteAsOperand(OutStreamer.GetCommentOS(), F, /*PrintType=*/false, F->getParent()); OutStreamer.GetCommentOS() << '\n'; @@ -319,13 +338,17 @@ void AsmPrinter::EmitFunctionHeader() { // Add some workaround for linkonce linkage on Cygwin\MinGW. if (MAI->getLinkOnceDirective() != 0 && - (F->hasLinkOnceLinkage() || F->hasWeakLinkage())) + (F->hasLinkOnceLinkage() || F->hasWeakLinkage())) { // FIXME: What is this? - O << "Lllvm$workaround$fake$stub$" << *CurrentFnSym << ":\n"; + MCSymbol *FakeStub = + OutContext.GetOrCreateSymbol(Twine("Lllvm$workaround$fake$stub$")+ + CurrentFnSym->getName()); + OutStreamer.EmitLabel(FakeStub); + } // Emit pre-function debug and/or EH information. - if (MAI->doesSupportDebugInformation() || MAI->doesSupportExceptionHandling()) - DW->BeginFunction(MF); + if (DE) DE->BeginFunction(MF); + if (DD) DD->beginFunction(MF); } /// EmitFunctionEntryLabel - Emit the label that is the entrypoint for the @@ -389,6 +412,28 @@ static void EmitComments(const MachineInstr &MI, raw_ostream &CommentOS) { } } +/// EmitImplicitDef - This method emits the specified machine instruction +/// that is an implicit def. +static void EmitImplicitDef(const MachineInstr *MI, AsmPrinter &AP) { + unsigned RegNo = MI->getOperand(0).getReg(); + AP.OutStreamer.AddComment(Twine("implicit-def: ") + + AP.TM.getRegisterInfo()->getName(RegNo)); + AP.OutStreamer.AddBlankLine(); +} + +static void EmitKill(const MachineInstr *MI, AsmPrinter &AP) { + std::string Str = "kill:"; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &Op = MI->getOperand(i); + assert(Op.isReg() && "KILL instruction must have only register operands"); + Str += ' '; + Str += AP.TM.getRegisterInfo()->getName(Op.getReg()); + Str += (Op.isDef() ? "<def>" : "<kill>"); + } + AP.OutStreamer.AddComment(Str); + AP.OutStreamer.AddBlankLine(); +} + /// EmitFunctionBody - This method emits the body and trailer for a @@ -397,6 +442,8 @@ void AsmPrinter::EmitFunctionBody() { // Emit target-specific gunk before the function body. EmitFunctionBodyStart(); + bool ShouldPrintDebugScopes = DD && MMI->hasDebugInfo(); + // Print out code for the function. bool HasAnyRealCode = false; for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); @@ -411,34 +458,34 @@ void AsmPrinter::EmitFunctionBody() { ++EmittedInsts; - // FIXME: Clean up processDebugLoc. - processDebugLoc(II, true); + if (ShouldPrintDebugScopes) + DD->beginScope(II); - if (VerboseAsm) + if (isVerbose()) EmitComments(*II, OutStreamer.GetCommentOS()); switch (II->getOpcode()) { case TargetOpcode::DBG_LABEL: case TargetOpcode::EH_LABEL: case TargetOpcode::GC_LABEL: - printLabelInst(II); + OutStreamer.EmitLabel(II->getOperand(0).getMCSymbol()); break; case TargetOpcode::INLINEASM: - printInlineAsm(II); + EmitInlineAsm(II); break; case TargetOpcode::IMPLICIT_DEF: - printImplicitDef(II); + if (isVerbose()) EmitImplicitDef(II, *this); break; case TargetOpcode::KILL: - printKill(II); + if (isVerbose()) EmitKill(II, *this); break; default: EmitInstruction(II); break; } - // FIXME: Clean up processDebugLoc. - processDebugLoc(II, false); + if (ShouldPrintDebugScopes) + DD->endScope(II); } } @@ -451,12 +498,25 @@ void AsmPrinter::EmitFunctionBody() { // Emit target-specific gunk after the function body. EmitFunctionBodyEnd(); - if (MAI->hasDotTypeDotSizeDirective()) - O << "\t.size\t" << *CurrentFnSym << ", .-" << *CurrentFnSym << '\n'; + // If the target wants a .size directive for the size of the function, emit + // it. + if (MAI->hasDotTypeDotSizeDirective()) { + // Create a symbol for the end of function, so we can get the size as + // difference between the function label and the temp label. + MCSymbol *FnEndLabel = OutContext.CreateTempSymbol(); + OutStreamer.EmitLabel(FnEndLabel); + + const MCExpr *SizeExp = + MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(FnEndLabel, OutContext), + MCSymbolRefExpr::Create(CurrentFnSym, OutContext), + OutContext); + OutStreamer.EmitELFSize(CurrentFnSym, SizeExp); + } // Emit post-function debug information. - if (MAI->doesSupportDebugInformation() || MAI->doesSupportExceptionHandling()) - DW->EndFunction(MF); + if (DD) DD->endFunction(MF); + if (DE) DE->EndFunction(); + MMI->EndFunction(); // Print out jump tables referenced by the function. EmitJumpTableInfo(); @@ -471,9 +531,15 @@ bool AsmPrinter::doFinalization(Module &M) { I != E; ++I) EmitGlobalVariable(I); - // Emit final debug information. - if (MAI->doesSupportDebugInformation() || MAI->doesSupportExceptionHandling()) - DW->EndModule(); + // Finalize debug and EH information. + if (DE) { + DE->EndModule(); + delete DE; DE = 0; + } + if (DD) { + DD->endModule(); + delete DD; DD = 0; + } // If the target wants to know about weak references, print them all. if (MAI->getWeakRefDirective()) { @@ -523,7 +589,7 @@ bool AsmPrinter::doFinalization(Module &M) { assert(MI && "AsmPrinter didn't require GCModuleInfo?"); for (GCModuleInfo::iterator I = MI->end(), E = MI->begin(); I != E; ) if (GCMetadataPrinter *MP = GetOrCreateGCPrinter(*--I)) - MP->finishAssembly(O, *this, *MAI); + MP->finishAssembly(*this); // If we don't have any trampolines, then we don't require stack memory // to be executable. Some targets have a directive to declare this. @@ -537,7 +603,7 @@ bool AsmPrinter::doFinalization(Module &M) { EmitEndOfAsmFile(M); delete Mang; Mang = 0; - DW = 0; MMI = 0; + MMI = 0; OutStreamer.Finish(); return false; @@ -548,7 +614,7 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { // Get the function symbol. CurrentFnSym = Mang->getSymbol(MF.getFunction()); - if (VerboseAsm) + if (isVerbose()) LI = &getAnalysis<MachineLoopInfo>(); } @@ -636,7 +702,7 @@ void AsmPrinter::EmitConstantPool() { Offset = NewOffset + TM.getTargetData()->getTypeAllocSize(Ty); // Emit the label with a comment on it. - if (VerboseAsm) { + if (isVerbose()) { OutStreamer.GetCommentOS() << "constant pool "; WriteTypeSymbolic(OutStreamer.GetCommentOS(), CPE.getType(), MF->getFunction()->getParent()); @@ -896,12 +962,6 @@ void AsmPrinter::EmitInt32(int Value) const { OutStreamer.EmitIntValue(Value, 4, 0/*addrspace*/); } -/// EmitInt64 - Emit a long long directive and value. -/// -void AsmPrinter::EmitInt64(uint64_t Value) const { - OutStreamer.EmitIntValue(Value, 8, 0/*addrspace*/); -} - /// EmitLabelDifference - Emit something like ".long Hi-Lo" where the size /// in bytes of the directive is specified by Size and Hi/Lo specify the /// labels. This implicitly uses .set if it is available. @@ -919,9 +979,7 @@ void AsmPrinter::EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, } // Otherwise, emit with .set (aka assignment). - MCSymbol *SetLabel = - OutContext.GetOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix()) + - "set" + Twine(SetCounter++)); + MCSymbol *SetLabel = GetTempSymbol("set", SetCounter++); OutStreamer.EmitAssignment(SetLabel, Diff); OutStreamer.EmitSymbolValue(SetLabel, Size, 0/*AddrSpace*/); } @@ -1156,7 +1214,7 @@ static void EmitGlobalConstantFP(const ConstantFP *CFP, unsigned AddrSpace, // FP Constants are printed as integer constants to avoid losing // precision. if (CFP->getType()->isDoubleTy()) { - if (AP.VerboseAsm) { + if (AP.isVerbose()) { double Val = CFP->getValueAPF().convertToDouble(); AP.OutStreamer.GetCommentOS() << "double " << Val << '\n'; } @@ -1167,7 +1225,7 @@ static void EmitGlobalConstantFP(const ConstantFP *CFP, unsigned AddrSpace, } if (CFP->getType()->isFloatTy()) { - if (AP.VerboseAsm) { + if (AP.isVerbose()) { float Val = CFP->getValueAPF().convertToFloat(); AP.OutStreamer.GetCommentOS() << "float " << Val << '\n'; } @@ -1181,7 +1239,7 @@ static void EmitGlobalConstantFP(const ConstantFP *CFP, unsigned AddrSpace, // api needed to prevent premature destruction APInt API = CFP->getValueAPF().bitcastToAPInt(); const uint64_t *p = API.getRawData(); - if (AP.VerboseAsm) { + if (AP.isVerbose()) { // Convert to double so we can print the approximate val as a comment. APFloat DoubleVal = CFP->getValueAPF(); bool ignored; @@ -1252,7 +1310,7 @@ void AsmPrinter::EmitGlobalConstant(const Constant *CV, unsigned AddrSpace) { case 2: case 4: case 8: - if (VerboseAsm) + if (isVerbose()) OutStreamer.GetCommentOS() << format("0x%llx\n", CI->getZExtValue()); OutStreamer.EmitIntValue(CI->getZExtValue(), Size, AddrSpace); return; @@ -1295,297 +1353,31 @@ void AsmPrinter::EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { llvm_unreachable("Target does not support EmitMachineConstantPoolValue"); } -/// PrintSpecial - Print information related to the specified machine instr -/// that is independent of the operand, and may be independent of the instr -/// itself. This can be useful for portably encoding the comment character -/// or other bits of target-specific knowledge into the asmstrings. The -/// syntax used is ${:comment}. Targets can override this to add support -/// for their own strange codes. -void AsmPrinter::PrintSpecial(const MachineInstr *MI, const char *Code) const { - if (!strcmp(Code, "private")) { - O << MAI->getPrivateGlobalPrefix(); - } else if (!strcmp(Code, "comment")) { - if (VerboseAsm) - O << MAI->getCommentString(); - } else if (!strcmp(Code, "uid")) { - // Comparing the address of MI isn't sufficient, because machineinstrs may - // be allocated to the same address across functions. - const Function *ThisF = MI->getParent()->getParent()->getFunction(); - - // If this is a new LastFn instruction, bump the counter. - if (LastMI != MI || LastFn != ThisF) { - ++Counter; - LastMI = MI; - LastFn = ThisF; - } - O << Counter; - } else { - std::string msg; - raw_string_ostream Msg(msg); - Msg << "Unknown special formatter '" << Code - << "' for machine instr: " << *MI; - llvm_report_error(Msg.str()); - } -} - -/// processDebugLoc - Processes the debug information of each machine -/// instruction's DebugLoc. -void AsmPrinter::processDebugLoc(const MachineInstr *MI, - bool BeforePrintingInsn) { - if (!MAI || !DW || !MAI->doesSupportDebugInformation() - || !DW->ShouldEmitDwarfDebug()) - return; - - if (!BeforePrintingInsn) - // After printing instruction - DW->EndScope(MI); - else - DW->BeginScope(MI); -} - - -/// printInlineAsm - This method formats and prints the specified machine -/// instruction that is an inline asm. -void AsmPrinter::printInlineAsm(const MachineInstr *MI) const { - unsigned NumOperands = MI->getNumOperands(); - - // Count the number of register definitions. - unsigned NumDefs = 0; - for (; MI->getOperand(NumDefs).isReg() && MI->getOperand(NumDefs).isDef(); - ++NumDefs) - assert(NumDefs != NumOperands-1 && "No asm string?"); - - assert(MI->getOperand(NumDefs).isSymbol() && "No asm string?"); - - // Disassemble the AsmStr, printing out the literal pieces, the operands, etc. - const char *AsmStr = MI->getOperand(NumDefs).getSymbolName(); - - O << '\t'; - - // If this asmstr is empty, just print the #APP/#NOAPP markers. - // These are useful to see where empty asm's wound up. - if (AsmStr[0] == 0) { - O << MAI->getCommentString() << MAI->getInlineAsmStart() << "\n\t"; - O << MAI->getCommentString() << MAI->getInlineAsmEnd() << '\n'; - return; - } - - O << MAI->getCommentString() << MAI->getInlineAsmStart() << "\n\t"; - - // The variant of the current asmprinter. - int AsmPrinterVariant = MAI->getAssemblerDialect(); - - int CurVariant = -1; // The number of the {.|.|.} region we are in. - const char *LastEmitted = AsmStr; // One past the last character emitted. - - while (*LastEmitted) { - switch (*LastEmitted) { - default: { - // Not a special case, emit the string section literally. - const char *LiteralEnd = LastEmitted+1; - while (*LiteralEnd && *LiteralEnd != '{' && *LiteralEnd != '|' && - *LiteralEnd != '}' && *LiteralEnd != '$' && *LiteralEnd != '\n') - ++LiteralEnd; - if (CurVariant == -1 || CurVariant == AsmPrinterVariant) - O.write(LastEmitted, LiteralEnd-LastEmitted); - LastEmitted = LiteralEnd; - break; - } - case '\n': - ++LastEmitted; // Consume newline character. - O << '\n'; // Indent code with newline. - break; - case '$': { - ++LastEmitted; // Consume '$' character. - bool Done = true; - - // Handle escapes. - switch (*LastEmitted) { - default: Done = false; break; - case '$': // $$ -> $ - if (CurVariant == -1 || CurVariant == AsmPrinterVariant) - O << '$'; - ++LastEmitted; // Consume second '$' character. - break; - case '(': // $( -> same as GCC's { character. - ++LastEmitted; // Consume '(' character. - if (CurVariant != -1) { - llvm_report_error("Nested variants found in inline asm string: '" - + std::string(AsmStr) + "'"); - } - CurVariant = 0; // We're in the first variant now. - break; - case '|': - ++LastEmitted; // consume '|' character. - if (CurVariant == -1) - O << '|'; // this is gcc's behavior for | outside a variant - else - ++CurVariant; // We're in the next variant. - break; - case ')': // $) -> same as GCC's } char. - ++LastEmitted; // consume ')' character. - if (CurVariant == -1) - O << '}'; // this is gcc's behavior for } outside a variant - else - CurVariant = -1; - break; - } - if (Done) break; - - bool HasCurlyBraces = false; - if (*LastEmitted == '{') { // ${variable} - ++LastEmitted; // Consume '{' character. - HasCurlyBraces = true; - } - - // If we have ${:foo}, then this is not a real operand reference, it is a - // "magic" string reference, just like in .td files. Arrange to call - // PrintSpecial. - if (HasCurlyBraces && *LastEmitted == ':') { - ++LastEmitted; - const char *StrStart = LastEmitted; - const char *StrEnd = strchr(StrStart, '}'); - if (StrEnd == 0) { - llvm_report_error("Unterminated ${:foo} operand in inline asm string: '" - + std::string(AsmStr) + "'"); - } - - std::string Val(StrStart, StrEnd); - PrintSpecial(MI, Val.c_str()); - LastEmitted = StrEnd+1; - break; - } - - const char *IDStart = LastEmitted; - char *IDEnd; - errno = 0; - long Val = strtol(IDStart, &IDEnd, 10); // We only accept numbers for IDs. - if (!isdigit(*IDStart) || (Val == 0 && errno == EINVAL)) { - llvm_report_error("Bad $ operand number in inline asm string: '" - + std::string(AsmStr) + "'"); - } - LastEmitted = IDEnd; - - char Modifier[2] = { 0, 0 }; - - if (HasCurlyBraces) { - // If we have curly braces, check for a modifier character. This - // supports syntax like ${0:u}, which correspond to "%u0" in GCC asm. - if (*LastEmitted == ':') { - ++LastEmitted; // Consume ':' character. - if (*LastEmitted == 0) { - llvm_report_error("Bad ${:} expression in inline asm string: '" - + std::string(AsmStr) + "'"); - } - - Modifier[0] = *LastEmitted; - ++LastEmitted; // Consume modifier character. - } - - if (*LastEmitted != '}') { - llvm_report_error("Bad ${} expression in inline asm string: '" - + std::string(AsmStr) + "'"); - } - ++LastEmitted; // Consume '}' character. - } - - if ((unsigned)Val >= NumOperands-1) { - llvm_report_error("Invalid $ operand number in inline asm string: '" - + std::string(AsmStr) + "'"); - } - - // Okay, we finally have a value number. Ask the target to print this - // operand! - if (CurVariant == -1 || CurVariant == AsmPrinterVariant) { - unsigned OpNo = 1; - - bool Error = false; - - // Scan to find the machine operand number for the operand. - for (; Val; --Val) { - if (OpNo >= MI->getNumOperands()) break; - unsigned OpFlags = MI->getOperand(OpNo).getImm(); - OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1; - } - - if (OpNo >= MI->getNumOperands()) { - Error = true; - } else { - unsigned OpFlags = MI->getOperand(OpNo).getImm(); - ++OpNo; // Skip over the ID number. - - if (Modifier[0] == 'l') // labels are target independent - O << *MI->getOperand(OpNo).getMBB()->getSymbol(); - else { - AsmPrinter *AP = const_cast<AsmPrinter*>(this); - if ((OpFlags & 7) == 4) { - Error = AP->PrintAsmMemoryOperand(MI, OpNo, AsmPrinterVariant, - Modifier[0] ? Modifier : 0); - } else { - Error = AP->PrintAsmOperand(MI, OpNo, AsmPrinterVariant, - Modifier[0] ? Modifier : 0); - } - } - } - if (Error) { - std::string msg; - raw_string_ostream Msg(msg); - Msg << "Invalid operand found in inline asm: '" << AsmStr << "'\n"; - MI->print(Msg); - llvm_report_error(Msg.str()); - } - } - break; - } - } - } - O << "\n\t" << MAI->getCommentString() << MAI->getInlineAsmEnd(); - OutStreamer.AddBlankLine(); -} - -/// printImplicitDef - This method prints the specified machine instruction -/// that is an implicit def. -void AsmPrinter::printImplicitDef(const MachineInstr *MI) const { - if (!VerboseAsm) return; - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << " implicit-def: " - << TRI->getName(MI->getOperand(0).getReg()); - OutStreamer.AddBlankLine(); +void AsmPrinter::printOffset(int64_t Offset, raw_ostream &OS) const { + if (Offset > 0) + OS << '+' << Offset; + else if (Offset < 0) + OS << Offset; } -void AsmPrinter::printKill(const MachineInstr *MI) const { - if (!VerboseAsm) return; - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << " kill:"; - for (unsigned n = 0, e = MI->getNumOperands(); n != e; ++n) { - const MachineOperand &op = MI->getOperand(n); - assert(op.isReg() && "KILL instruction must have only register operands"); - O << ' ' << TRI->getName(op.getReg()) << (op.isDef() ? "<def>" : "<kill>"); - } - OutStreamer.AddBlankLine(); -} +//===----------------------------------------------------------------------===// +// Symbol Lowering Routines. +//===----------------------------------------------------------------------===// -/// printLabel - This method prints a local label used by debug and -/// exception handling tables. -void AsmPrinter::printLabelInst(const MachineInstr *MI) const { - OutStreamer.EmitLabel(MI->getOperand(0).getMCSymbol()); +/// GetTempSymbol - Return the MCSymbol corresponding to the assembler +/// temporary label with the specified stem and unique ID. +MCSymbol *AsmPrinter::GetTempSymbol(StringRef Name, unsigned ID) const { + return OutContext.GetOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix()) + + Name + Twine(ID)); } -/// PrintAsmOperand - Print the specified operand of MI, an INLINEASM -/// instruction, using the specified assembler variant. Targets should -/// override this to format as appropriate. -bool AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode) { - // Target doesn't support this yet! - return true; +/// GetTempSymbol - Return an assembler temporary label with the specified +/// stem. +MCSymbol *AsmPrinter::GetTempSymbol(StringRef Name) const { + return OutContext.GetOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix())+ + Name); } -bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, - const char *ExtraCode) { - // Target doesn't support this yet! - return true; -} MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BlockAddress *BA) const { return MMI->getAddrLabelSymbol(BA->getBasicBlock()); @@ -1663,10 +1455,10 @@ static void PrintChildLoopComment(raw_ostream &OS, const MachineLoop *Loop, } } -/// PrintBasicBlockLoopComments - Pretty-print comments for basic blocks. -static void PrintBasicBlockLoopComments(const MachineBasicBlock &MBB, - const MachineLoopInfo *LI, - const AsmPrinter &AP) { +/// EmitBasicBlockLoopComments - Pretty-print comments for basic blocks. +static void EmitBasicBlockLoopComments(const MachineBasicBlock &MBB, + const MachineLoopInfo *LI, + const AsmPrinter &AP) { // Add loop depth information const MachineLoop *Loop = LI->getLoopFor(&MBB); if (Loop == 0) return; @@ -1716,7 +1508,7 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock *MBB) const { // the references were generated. if (MBB->hasAddressTaken()) { const BasicBlock *BB = MBB->getBasicBlock(); - if (VerboseAsm) + if (isVerbose()) OutStreamer.AddComment("Block address taken"); std::vector<MCSymbol*> Syms = MMI->getAddrLabelSymbolToEmit(BB); @@ -1727,22 +1519,23 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock *MBB) const { // Print the main label for the block. if (MBB->pred_empty() || isBlockOnlyReachableByFallthrough(MBB)) { - if (VerboseAsm) { - // NOTE: Want this comment at start of line. - O << MAI->getCommentString() << " BB#" << MBB->getNumber() << ':'; + if (isVerbose() && OutStreamer.hasRawTextSupport()) { if (const BasicBlock *BB = MBB->getBasicBlock()) if (BB->hasName()) OutStreamer.AddComment("%" + BB->getName()); - PrintBasicBlockLoopComments(*MBB, LI, *this); - OutStreamer.AddBlankLine(); + EmitBasicBlockLoopComments(*MBB, LI, *this); + + // NOTE: Want this comment at start of line, don't emit with AddComment. + OutStreamer.EmitRawText(Twine(MAI->getCommentString()) + " BB#" + + Twine(MBB->getNumber()) + ":"); } } else { - if (VerboseAsm) { + if (isVerbose()) { if (const BasicBlock *BB = MBB->getBasicBlock()) if (BB->hasName()) OutStreamer.AddComment("%" + BB->getName()); - PrintBasicBlockLoopComments(*MBB, LI, *this); + EmitBasicBlockLoopComments(*MBB, LI, *this); } OutStreamer.EmitLabel(MBB->getSymbol()); @@ -1766,18 +1559,11 @@ void AsmPrinter::EmitVisibility(MCSymbol *Sym, unsigned Visibility) const { OutStreamer.EmitSymbolAttribute(Sym, Attr); } -void AsmPrinter::printOffset(int64_t Offset) const { - if (Offset > 0) - O << '+' << Offset; - else if (Offset < 0) - O << Offset; -} - /// isBlockOnlyReachableByFallthough - Return true if the basic block has /// exactly one predecessor and the control transfer mechanism between /// the predecessor and this block is a fall-through. -bool AsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) - const { +bool AsmPrinter:: +isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { // If this is a landing pad, it isn't a fall through. If it has no preds, // then nothing falls through to it. if (MBB->isLandingPad() || MBB->pred_empty()) @@ -1809,9 +1595,10 @@ bool AsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy *S) { if (!S->usesMetadata()) return 0; - - gcp_iterator GCPI = GCMetadataPrinters.find(S); - if (GCPI != GCMetadataPrinters.end()) + + gcp_map_type &GCMap = getGCMap(GCMetadataPrinters); + gcp_map_type::iterator GCPI = GCMap.find(S); + if (GCPI != GCMap.end()) return GCPI->second; const char *Name = S->getName().c_str(); @@ -1822,7 +1609,7 @@ GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy *S) { if (strcmp(Name, I->getName()) == 0) { GCMetadataPrinter *GMP = I->instantiate(); GMP->S = S; - GCMetadataPrinters.insert(std::make_pair(S, GMP)); + GCMap.insert(std::make_pair(S, GMP)); return GMP; } diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp new file mode 100644 index 000000000000..b310578584bc --- /dev/null +++ b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp @@ -0,0 +1,279 @@ +//===-- AsmPrinterDwarf.cpp - AsmPrinter Dwarf Support --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Dwarf emissions parts of AsmPrinter. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/Dwarf.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Dwarf Emission Helper Routines +//===----------------------------------------------------------------------===// + +/// EmitSLEB128 - emit the specified signed leb128 value. +void AsmPrinter::EmitSLEB128(int Value, const char *Desc) const { + if (isVerbose() && Desc) + OutStreamer.AddComment(Desc); + + if (MAI->hasLEB128()) { + // FIXME: MCize. + OutStreamer.EmitRawText("\t.sleb128\t" + Twine(Value)); + return; + } + + // If we don't have .sleb128, emit as .bytes. + int Sign = Value >> (8 * sizeof(Value) - 1); + bool IsMore; + + do { + unsigned char Byte = static_cast<unsigned char>(Value & 0x7f); + Value >>= 7; + IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; + if (IsMore) Byte |= 0x80; + OutStreamer.EmitIntValue(Byte, 1, /*addrspace*/0); + } while (IsMore); +} + +/// EmitULEB128 - emit the specified signed leb128 value. +void AsmPrinter::EmitULEB128(unsigned Value, const char *Desc, + unsigned PadTo) const { + if (isVerbose() && Desc) + OutStreamer.AddComment(Desc); + + if (MAI->hasLEB128() && PadTo == 0) { + // FIXME: MCize. + OutStreamer.EmitRawText("\t.uleb128\t" + Twine(Value)); + return; + } + + // If we don't have .uleb128 or we want to emit padding, emit as .bytes. + do { + unsigned char Byte = static_cast<unsigned char>(Value & 0x7f); + Value >>= 7; + if (Value || PadTo != 0) Byte |= 0x80; + OutStreamer.EmitIntValue(Byte, 1, /*addrspace*/0); + } while (Value); + + if (PadTo) { + if (PadTo > 1) + OutStreamer.EmitFill(PadTo - 1, 0x80/*fillval*/, 0/*addrspace*/); + OutStreamer.EmitFill(1, 0/*fillval*/, 0/*addrspace*/); + } +} + +/// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value. +void AsmPrinter::EmitCFAByte(unsigned Val) const { + if (isVerbose()) { + if (Val >= dwarf::DW_CFA_offset && Val < dwarf::DW_CFA_offset+64) + OutStreamer.AddComment("DW_CFA_offset + Reg (" + + Twine(Val-dwarf::DW_CFA_offset) + ")"); + else + OutStreamer.AddComment(dwarf::CallFrameString(Val)); + } + OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/); +} + +static const char *DecodeDWARFEncoding(unsigned Encoding) { + switch (Encoding) { + case dwarf::DW_EH_PE_absptr: return "absptr"; + case dwarf::DW_EH_PE_omit: return "omit"; + case dwarf::DW_EH_PE_pcrel: return "pcrel"; + case dwarf::DW_EH_PE_udata4: return "udata4"; + case dwarf::DW_EH_PE_udata8: return "udata8"; + case dwarf::DW_EH_PE_sdata4: return "sdata4"; + case dwarf::DW_EH_PE_sdata8: return "sdata8"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4: return "pcrel udata4"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4: return "pcrel sdata4"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8: return "pcrel udata8"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8: return "pcrel sdata8"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata4: + return "indirect pcrel udata4"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata4: + return "indirect pcrel sdata4"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata8: + return "indirect pcrel udata8"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata8: + return "indirect pcrel sdata8"; + } + + return "<unknown encoding>"; +} + + +/// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an +/// encoding. If verbose assembly output is enabled, we output comments +/// describing the encoding. Desc is an optional string saying what the +/// encoding is specifying (e.g. "LSDA"). +void AsmPrinter::EmitEncodingByte(unsigned Val, const char *Desc) const { + if (isVerbose()) { + if (Desc != 0) + OutStreamer.AddComment(Twine(Desc)+" Encoding = " + + Twine(DecodeDWARFEncoding(Val))); + else + OutStreamer.AddComment(Twine("Encoding = ") + + DecodeDWARFEncoding(Val)); + } + + OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/); +} + +/// GetSizeOfEncodedValue - Return the size of the encoding in bytes. +unsigned AsmPrinter::GetSizeOfEncodedValue(unsigned Encoding) const { + if (Encoding == dwarf::DW_EH_PE_omit) + return 0; + + switch (Encoding & 0x07) { + default: assert(0 && "Invalid encoded value."); + case dwarf::DW_EH_PE_absptr: return TM.getTargetData()->getPointerSize(); + case dwarf::DW_EH_PE_udata2: return 2; + case dwarf::DW_EH_PE_udata4: return 4; + case dwarf::DW_EH_PE_udata8: return 8; + } +} + +void AsmPrinter::EmitReference(const MCSymbol *Sym, unsigned Encoding) const { + const TargetLoweringObjectFile &TLOF = getObjFileLowering(); + + const MCExpr *Exp = + TLOF.getExprForDwarfReference(Sym, Mang, MMI, Encoding, OutStreamer); + OutStreamer.EmitValue(Exp, GetSizeOfEncodedValue(Encoding), /*addrspace*/0); +} + +void AsmPrinter::EmitReference(const GlobalValue *GV, unsigned Encoding)const{ + const TargetLoweringObjectFile &TLOF = getObjFileLowering(); + + const MCExpr *Exp = + TLOF.getExprForDwarfGlobalReference(GV, Mang, MMI, Encoding, OutStreamer); + OutStreamer.EmitValue(Exp, GetSizeOfEncodedValue(Encoding), /*addrspace*/0); +} + +/// EmitSectionOffset - Emit the 4-byte offset of Label from the start of its +/// section. This can be done with a special directive if the target supports +/// it (e.g. cygwin) or by emitting it as an offset from a label at the start +/// of the section. +/// +/// SectionLabel is a temporary label emitted at the start of the section that +/// Label lives in. +void AsmPrinter::EmitSectionOffset(const MCSymbol *Label, + const MCSymbol *SectionLabel) const { + // On COFF targets, we have to emit the special .secrel32 directive. + if (const char *SecOffDir = MAI->getDwarfSectionOffsetDirective()) { + // FIXME: MCize. + OutStreamer.EmitRawText(SecOffDir + Twine(Label->getName())); + return; + } + + // Get the section that we're referring to, based on SectionLabel. + const MCSection &Section = SectionLabel->getSection(); + + // If Label has already been emitted, verify that it is in the same section as + // section label for sanity. + assert((!Label->isInSection() || &Label->getSection() == &Section) && + "Section offset using wrong section base for label"); + + // If the section in question will end up with an address of 0 anyway, we can + // just emit an absolute reference to save a relocation. + if (Section.isBaseAddressKnownZero()) { + OutStreamer.EmitSymbolValue(Label, 4, 0/*AddrSpace*/); + return; + } + + // Otherwise, emit it as a label difference from the start of the section. + EmitLabelDifference(Label, SectionLabel, 4); +} + +//===----------------------------------------------------------------------===// +// Dwarf Lowering Routines +//===----------------------------------------------------------------------===// + + +/// EmitFrameMoves - Emit frame instructions to describe the layout of the +/// frame. +void AsmPrinter::EmitFrameMoves(const std::vector<MachineMove> &Moves, + MCSymbol *BaseLabel, bool isEH) const { + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + + int stackGrowth = TM.getTargetData()->getPointerSize(); + if (TM.getFrameInfo()->getStackGrowthDirection() != + TargetFrameInfo::StackGrowsUp) + stackGrowth *= -1; + + for (unsigned i = 0, N = Moves.size(); i < N; ++i) { + const MachineMove &Move = Moves[i]; + MCSymbol *Label = Move.getLabel(); + // Throw out move if the label is invalid. + if (Label && !Label->isDefined()) continue; // Not emitted, in dead code. + + const MachineLocation &Dst = Move.getDestination(); + const MachineLocation &Src = Move.getSource(); + + // Advance row if new location. + if (BaseLabel && Label) { + MCSymbol *ThisSym = Label; + if (ThisSym != BaseLabel) { + EmitCFAByte(dwarf::DW_CFA_advance_loc4); + EmitLabelDifference(ThisSym, BaseLabel, 4); + BaseLabel = ThisSym; + } + } + + // If advancing cfa. + if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) { + assert(!Src.isReg() && "Machine move not supported yet."); + + if (Src.getReg() == MachineLocation::VirtualFP) { + EmitCFAByte(dwarf::DW_CFA_def_cfa_offset); + } else { + EmitCFAByte(dwarf::DW_CFA_def_cfa); + EmitULEB128(RI->getDwarfRegNum(Src.getReg(), isEH), "Register"); + } + + EmitULEB128(-Src.getOffset(), "Offset"); + continue; + } + + if (Src.isReg() && Src.getReg() == MachineLocation::VirtualFP) { + assert(Dst.isReg() && "Machine move not supported yet."); + EmitCFAByte(dwarf::DW_CFA_def_cfa_register); + EmitULEB128(RI->getDwarfRegNum(Dst.getReg(), isEH), "Register"); + continue; + } + + unsigned Reg = RI->getDwarfRegNum(Src.getReg(), isEH); + int Offset = Dst.getOffset() / stackGrowth; + + if (Offset < 0) { + EmitCFAByte(dwarf::DW_CFA_offset_extended_sf); + EmitULEB128(Reg, "Reg"); + EmitSLEB128(Offset, "Offset"); + } else if (Reg < 64) { + EmitCFAByte(dwarf::DW_CFA_offset + Reg); + EmitULEB128(Offset, "Offset"); + } else { + EmitCFAByte(dwarf::DW_CFA_offset_extended); + EmitULEB128(Reg, "Reg"); + EmitULEB128(Offset, "Offset"); + } + } +} diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp new file mode 100644 index 000000000000..255bcd413f22 --- /dev/null +++ b/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -0,0 +1,357 @@ +//===-- AsmPrinterInlineAsm.cpp - AsmPrinter Inline Asm Handling ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the inline assembler pieces of the AsmPrinter class. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/InlineAsm.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCParser/AsmParser.h" +#include "llvm/Target/TargetAsmParser.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +/// EmitInlineAsm - Emit a blob of inline asm to the output streamer. +void AsmPrinter::EmitInlineAsm(StringRef Str, unsigned LocCookie) const { + assert(!Str.empty() && "Can't emit empty inline asm block"); + + // Remember if the buffer is nul terminated or not so we can avoid a copy. + bool isNullTerminated = Str.back() == 0; + if (isNullTerminated) + Str = Str.substr(0, Str.size()-1); + + // If the output streamer is actually a .s file, just emit the blob textually. + // This is useful in case the asm parser doesn't handle something but the + // system assembler does. + if (OutStreamer.hasRawTextSupport()) { + OutStreamer.EmitRawText(Str); + return; + } + + SourceMgr SrcMgr; + + // If the current LLVMContext has an inline asm handler, set it in SourceMgr. + LLVMContext &LLVMCtx = MMI->getModule()->getContext(); + bool HasDiagHandler = false; + if (void *DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler()) { + SrcMgr.setDiagHandler((SourceMgr::DiagHandlerTy)(intptr_t)DiagHandler, + LLVMCtx.getInlineAsmDiagnosticContext(), LocCookie); + HasDiagHandler = true; + } + + MemoryBuffer *Buffer; + if (isNullTerminated) + Buffer = MemoryBuffer::getMemBuffer(Str, "<inline asm>"); + else + Buffer = MemoryBuffer::getMemBufferCopy(Str, "<inline asm>"); + + // Tell SrcMgr about this buffer, it takes ownership of the buffer. + SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); + + AsmParser Parser(SrcMgr, OutContext, OutStreamer, *MAI); + OwningPtr<TargetAsmParser> TAP(TM.getTarget().createAsmParser(Parser)); + if (!TAP) + llvm_report_error("Inline asm not supported by this streamer because" + " we don't have an asm parser for this target\n"); + Parser.setTargetParser(*TAP.get()); + + // Don't implicitly switch to the text section before the asm. + int Res = Parser.Run(/*NoInitialTextSection*/ true, + /*NoFinalize*/ true); + if (Res && !HasDiagHandler) + llvm_report_error("Error parsing inline asm\n"); +} + + +/// EmitInlineAsm - This method formats and emits the specified machine +/// instruction that is an inline asm. +void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const { + assert(MI->isInlineAsm() && "printInlineAsm only works on inline asms"); + + unsigned NumOperands = MI->getNumOperands(); + + // Count the number of register definitions to find the asm string. + unsigned NumDefs = 0; + for (; MI->getOperand(NumDefs).isReg() && MI->getOperand(NumDefs).isDef(); + ++NumDefs) + assert(NumDefs != NumOperands-1 && "No asm string?"); + + assert(MI->getOperand(NumDefs).isSymbol() && "No asm string?"); + + // Disassemble the AsmStr, printing out the literal pieces, the operands, etc. + const char *AsmStr = MI->getOperand(NumDefs).getSymbolName(); + + // If this asmstr is empty, just print the #APP/#NOAPP markers. + // These are useful to see where empty asm's wound up. + if (AsmStr[0] == 0) { + // Don't emit the comments if writing to a .o file. + if (!OutStreamer.hasRawTextSupport()) return; + + OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+ + MAI->getInlineAsmStart()); + OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+ + MAI->getInlineAsmEnd()); + return; + } + + // Emit the #APP start marker. This has to happen even if verbose-asm isn't + // enabled, so we use EmitRawText. + if (OutStreamer.hasRawTextSupport()) + OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+ + MAI->getInlineAsmStart()); + + // Emit the inline asm to a temporary string so we can emit it through + // EmitInlineAsm. + SmallString<256> StringData; + raw_svector_ostream OS(StringData); + + OS << '\t'; + + // The variant of the current asmprinter. + int AsmPrinterVariant = MAI->getAssemblerDialect(); + + int CurVariant = -1; // The number of the {.|.|.} region we are in. + const char *LastEmitted = AsmStr; // One past the last character emitted. + + while (*LastEmitted) { + switch (*LastEmitted) { + default: { + // Not a special case, emit the string section literally. + const char *LiteralEnd = LastEmitted+1; + while (*LiteralEnd && *LiteralEnd != '{' && *LiteralEnd != '|' && + *LiteralEnd != '}' && *LiteralEnd != '$' && *LiteralEnd != '\n') + ++LiteralEnd; + if (CurVariant == -1 || CurVariant == AsmPrinterVariant) + OS.write(LastEmitted, LiteralEnd-LastEmitted); + LastEmitted = LiteralEnd; + break; + } + case '\n': + ++LastEmitted; // Consume newline character. + OS << '\n'; // Indent code with newline. + break; + case '$': { + ++LastEmitted; // Consume '$' character. + bool Done = true; + + // Handle escapes. + switch (*LastEmitted) { + default: Done = false; break; + case '$': // $$ -> $ + if (CurVariant == -1 || CurVariant == AsmPrinterVariant) + OS << '$'; + ++LastEmitted; // Consume second '$' character. + break; + case '(': // $( -> same as GCC's { character. + ++LastEmitted; // Consume '(' character. + if (CurVariant != -1) { + llvm_report_error("Nested variants found in inline asm string: '" + + std::string(AsmStr) + "'"); + } + CurVariant = 0; // We're in the first variant now. + break; + case '|': + ++LastEmitted; // consume '|' character. + if (CurVariant == -1) + OS << '|'; // this is gcc's behavior for | outside a variant + else + ++CurVariant; // We're in the next variant. + break; + case ')': // $) -> same as GCC's } char. + ++LastEmitted; // consume ')' character. + if (CurVariant == -1) + OS << '}'; // this is gcc's behavior for } outside a variant + else + CurVariant = -1; + break; + } + if (Done) break; + + bool HasCurlyBraces = false; + if (*LastEmitted == '{') { // ${variable} + ++LastEmitted; // Consume '{' character. + HasCurlyBraces = true; + } + + // If we have ${:foo}, then this is not a real operand reference, it is a + // "magic" string reference, just like in .td files. Arrange to call + // PrintSpecial. + if (HasCurlyBraces && *LastEmitted == ':') { + ++LastEmitted; + const char *StrStart = LastEmitted; + const char *StrEnd = strchr(StrStart, '}'); + if (StrEnd == 0) + llvm_report_error(Twine("Unterminated ${:foo} operand in inline asm" + " string: '") + Twine(AsmStr) + "'"); + + std::string Val(StrStart, StrEnd); + PrintSpecial(MI, OS, Val.c_str()); + LastEmitted = StrEnd+1; + break; + } + + const char *IDStart = LastEmitted; + const char *IDEnd = IDStart; + while (*IDEnd >= '0' && *IDEnd <= '9') ++IDEnd; + + unsigned Val; + if (StringRef(IDStart, IDEnd-IDStart).getAsInteger(10, Val)) + llvm_report_error("Bad $ operand number in inline asm string: '" + + std::string(AsmStr) + "'"); + LastEmitted = IDEnd; + + char Modifier[2] = { 0, 0 }; + + if (HasCurlyBraces) { + // If we have curly braces, check for a modifier character. This + // supports syntax like ${0:u}, which correspond to "%u0" in GCC asm. + if (*LastEmitted == ':') { + ++LastEmitted; // Consume ':' character. + if (*LastEmitted == 0) + llvm_report_error("Bad ${:} expression in inline asm string: '" + + std::string(AsmStr) + "'"); + + Modifier[0] = *LastEmitted; + ++LastEmitted; // Consume modifier character. + } + + if (*LastEmitted != '}') + llvm_report_error("Bad ${} expression in inline asm string: '" + + std::string(AsmStr) + "'"); + ++LastEmitted; // Consume '}' character. + } + + if (Val >= NumOperands-1) + llvm_report_error("Invalid $ operand number in inline asm string: '" + + std::string(AsmStr) + "'"); + + // Okay, we finally have a value number. Ask the target to print this + // operand! + if (CurVariant == -1 || CurVariant == AsmPrinterVariant) { + unsigned OpNo = 1; + + bool Error = false; + + // Scan to find the machine operand number for the operand. + for (; Val; --Val) { + if (OpNo >= MI->getNumOperands()) break; + unsigned OpFlags = MI->getOperand(OpNo).getImm(); + OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1; + } + + if (OpNo >= MI->getNumOperands()) { + Error = true; + } else { + unsigned OpFlags = MI->getOperand(OpNo).getImm(); + ++OpNo; // Skip over the ID number. + + if (Modifier[0] == 'l') // labels are target independent + // FIXME: What if the operand isn't an MBB, report error? + OS << *MI->getOperand(OpNo).getMBB()->getSymbol(); + else { + AsmPrinter *AP = const_cast<AsmPrinter*>(this); + if ((OpFlags & 7) == 4) { + Error = AP->PrintAsmMemoryOperand(MI, OpNo, AsmPrinterVariant, + Modifier[0] ? Modifier : 0, + OS); + } else { + Error = AP->PrintAsmOperand(MI, OpNo, AsmPrinterVariant, + Modifier[0] ? Modifier : 0, OS); + } + } + } + if (Error) { + std::string msg; + raw_string_ostream Msg(msg); + Msg << "Invalid operand found in inline asm: '" << AsmStr << "'\n"; + MI->print(Msg); + llvm_report_error(Msg.str()); + } + } + break; + } + } + } + OS << '\n' << (char)0; // null terminate string. + EmitInlineAsm(OS.str(), 0/*no loc cookie*/); + + // Emit the #NOAPP end marker. This has to happen even if verbose-asm isn't + // enabled, so we use EmitRawText. + if (OutStreamer.hasRawTextSupport()) + OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+ + MAI->getInlineAsmEnd()); +} + + +/// PrintSpecial - Print information related to the specified machine instr +/// that is independent of the operand, and may be independent of the instr +/// itself. This can be useful for portably encoding the comment character +/// or other bits of target-specific knowledge into the asmstrings. The +/// syntax used is ${:comment}. Targets can override this to add support +/// for their own strange codes. +void AsmPrinter::PrintSpecial(const MachineInstr *MI, raw_ostream &OS, + const char *Code) const { + if (!strcmp(Code, "private")) { + OS << MAI->getPrivateGlobalPrefix(); + } else if (!strcmp(Code, "comment")) { + OS << MAI->getCommentString(); + } else if (!strcmp(Code, "uid")) { + // Comparing the address of MI isn't sufficient, because machineinstrs may + // be allocated to the same address across functions. + + // If this is a new LastFn instruction, bump the counter. + if (LastMI != MI || LastFn != getFunctionNumber()) { + ++Counter; + LastMI = MI; + LastFn = getFunctionNumber(); + } + OS << Counter; + } else { + std::string msg; + raw_string_ostream Msg(msg); + Msg << "Unknown special formatter '" << Code + << "' for machine instr: " << *MI; + llvm_report_error(Msg.str()); + } +} + +/// PrintAsmOperand - Print the specified operand of MI, an INLINEASM +/// instruction, using the specified assembler variant. Targets should +/// override this to format as appropriate. +bool AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O) { + // Target doesn't support this yet! + return true; +} + +bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode, raw_ostream &O) { + // Target doesn't support this yet! + return true; +} + diff --git a/lib/CodeGen/AsmPrinter/CMakeLists.txt b/lib/CodeGen/AsmPrinter/CMakeLists.txt index 7dc1fb596568..afc482dd15bf 100644 --- a/lib/CodeGen/AsmPrinter/CMakeLists.txt +++ b/lib/CodeGen/AsmPrinter/CMakeLists.txt @@ -1,9 +1,9 @@ add_llvm_library(LLVMAsmPrinter AsmPrinter.cpp + AsmPrinterDwarf.cpp + AsmPrinterInlineAsm.cpp DIE.cpp DwarfDebug.cpp DwarfException.cpp - DwarfPrinter.cpp - DwarfWriter.cpp OcamlGCPrinter.cpp ) diff --git a/lib/CodeGen/AsmPrinter/DIE.cpp b/lib/CodeGen/AsmPrinter/DIE.cpp index e0e3ff794672..b2c70d51f5a5 100644 --- a/lib/CodeGen/AsmPrinter/DIE.cpp +++ b/lib/CodeGen/AsmPrinter/DIE.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "DIE.h" -#include "DwarfPrinter.h" #include "llvm/ADT/Twine.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/MC/MCAsmInfo.h" @@ -54,14 +53,14 @@ void DIEAbbrev::Profile(FoldingSetNodeID &ID) const { /// Emit - Print the abbreviation using the specified asm printer. /// -void DIEAbbrev::Emit(const DwarfPrinter *DP) const { +void DIEAbbrev::Emit(AsmPrinter *AP) const { // Emit its Dwarf tag type. // FIXME: Doing work even in non-asm-verbose runs. - DP->EmitULEB128(Tag, dwarf::TagString(Tag)); + AP->EmitULEB128(Tag, dwarf::TagString(Tag)); // Emit whether it has children DIEs. // FIXME: Doing work even in non-asm-verbose runs. - DP->EmitULEB128(ChildrenFlag, dwarf::ChildrenString(ChildrenFlag)); + AP->EmitULEB128(ChildrenFlag, dwarf::ChildrenString(ChildrenFlag)); // For each attribute description. for (unsigned i = 0, N = Data.size(); i < N; ++i) { @@ -69,18 +68,18 @@ void DIEAbbrev::Emit(const DwarfPrinter *DP) const { // Emit attribute type. // FIXME: Doing work even in non-asm-verbose runs. - DP->EmitULEB128(AttrData.getAttribute(), - dwarf::AttributeString(AttrData.getAttribute())); + AP->EmitULEB128(AttrData.getAttribute(), + dwarf::AttributeString(AttrData.getAttribute())); // Emit form type. // FIXME: Doing work even in non-asm-verbose runs. - DP->EmitULEB128(AttrData.getForm(), + AP->EmitULEB128(AttrData.getForm(), dwarf::FormEncodingString(AttrData.getForm())); } // Mark end of abbreviation. - DP->EmitULEB128(0, "EOM(1)"); - DP->EmitULEB128(0, "EOM(2)"); + AP->EmitULEB128(0, "EOM(1)"); + AP->EmitULEB128(0, "EOM(2)"); } #ifndef NDEBUG @@ -188,8 +187,7 @@ void DIEValue::dump() { /// EmitValue - Emit integer of appropriate size. /// -void DIEInteger::EmitValue(DwarfPrinter *D, unsigned Form) const { - const AsmPrinter *Asm = D->getAsm(); +void DIEInteger::EmitValue(AsmPrinter *Asm, unsigned Form) const { unsigned Size = ~0U; switch (Form) { case dwarf::DW_FORM_flag: // Fall thru @@ -201,8 +199,8 @@ void DIEInteger::EmitValue(DwarfPrinter *D, unsigned Form) const { case dwarf::DW_FORM_data4: Size = 4; break; case dwarf::DW_FORM_ref8: // Fall thru case dwarf::DW_FORM_data8: Size = 8; break; - case dwarf::DW_FORM_udata: D->EmitULEB128(Integer); return; - case dwarf::DW_FORM_sdata: D->EmitSLEB128(Integer, ""); return; + case dwarf::DW_FORM_udata: Asm->EmitULEB128(Integer); return; + case dwarf::DW_FORM_sdata: Asm->EmitSLEB128(Integer); return; default: llvm_unreachable("DIE Value form not supported yet"); } Asm->OutStreamer.EmitIntValue(Integer, Size, 0/*addrspace*/); @@ -210,7 +208,7 @@ void DIEInteger::EmitValue(DwarfPrinter *D, unsigned Form) const { /// SizeOf - Determine size of integer value in bytes. /// -unsigned DIEInteger::SizeOf(const TargetData *TD, unsigned Form) const { +unsigned DIEInteger::SizeOf(AsmPrinter *AP, unsigned Form) const { switch (Form) { case dwarf::DW_FORM_flag: // Fall thru case dwarf::DW_FORM_ref1: // Fall thru @@ -241,10 +239,10 @@ void DIEInteger::print(raw_ostream &O) { /// EmitValue - Emit string value. /// -void DIEString::EmitValue(DwarfPrinter *D, unsigned Form) const { - D->getAsm()->OutStreamer.EmitBytes(Str, /*addrspace*/0); +void DIEString::EmitValue(AsmPrinter *AP, unsigned Form) const { + AP->OutStreamer.EmitBytes(Str, /*addrspace*/0); // Emit nul terminator. - D->getAsm()->OutStreamer.EmitIntValue(0, 1, /*addrspace*/0); + AP->OutStreamer.EmitIntValue(0, 1, /*addrspace*/0); } #ifndef NDEBUG @@ -259,17 +257,15 @@ void DIEString::print(raw_ostream &O) { /// EmitValue - Emit label value. /// -void DIELabel::EmitValue(DwarfPrinter *D, unsigned Form) const { - bool IsSmall = Form == dwarf::DW_FORM_data4; - unsigned Size = IsSmall ? 4 : D->getTargetData()->getPointerSize(); - D->getAsm()->OutStreamer.EmitSymbolValue(Label, Size, 0/*AddrSpace*/); +void DIELabel::EmitValue(AsmPrinter *AP, unsigned Form) const { + AP->OutStreamer.EmitSymbolValue(Label, SizeOf(AP, Form), 0/*AddrSpace*/); } /// SizeOf - Determine size of label value in bytes. /// -unsigned DIELabel::SizeOf(const TargetData *TD, unsigned Form) const { +unsigned DIELabel::SizeOf(AsmPrinter *AP, unsigned Form) const { if (Form == dwarf::DW_FORM_data4) return 4; - return TD->getPointerSize(); + return AP->getTargetData().getPointerSize(); } #ifndef NDEBUG @@ -284,16 +280,15 @@ void DIELabel::print(raw_ostream &O) { /// EmitValue - Emit delta value. /// -void DIEDelta::EmitValue(DwarfPrinter *D, unsigned Form) const { - bool IsSmall = Form == dwarf::DW_FORM_data4; - D->EmitDifference(LabelHi, LabelLo, IsSmall); +void DIEDelta::EmitValue(AsmPrinter *AP, unsigned Form) const { + AP->EmitLabelDifference(LabelHi, LabelLo, SizeOf(AP, Form)); } /// SizeOf - Determine size of delta value in bytes. /// -unsigned DIEDelta::SizeOf(const TargetData *TD, unsigned Form) const { +unsigned DIEDelta::SizeOf(AsmPrinter *AP, unsigned Form) const { if (Form == dwarf::DW_FORM_data4) return 4; - return TD->getPointerSize(); + return AP->getTargetData().getPointerSize(); } #ifndef NDEBUG @@ -308,8 +303,8 @@ void DIEDelta::print(raw_ostream &O) { /// EmitValue - Emit debug information entry offset. /// -void DIEEntry::EmitValue(DwarfPrinter *D, unsigned Form) const { - D->getAsm()->EmitInt32(Entry->getOffset()); +void DIEEntry::EmitValue(AsmPrinter *AP, unsigned Form) const { + AP->EmitInt32(Entry->getOffset()); } #ifndef NDEBUG @@ -324,11 +319,11 @@ void DIEEntry::print(raw_ostream &O) { /// ComputeSize - calculate the size of the block. /// -unsigned DIEBlock::ComputeSize(const TargetData *TD) { +unsigned DIEBlock::ComputeSize(AsmPrinter *AP) { if (!Size) { const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev.getData(); for (unsigned i = 0, N = Values.size(); i < N; ++i) - Size += Values[i]->SizeOf(TD, AbbrevData[i].getForm()); + Size += Values[i]->SizeOf(AP, AbbrevData[i].getForm()); } return Size; @@ -336,29 +331,28 @@ unsigned DIEBlock::ComputeSize(const TargetData *TD) { /// EmitValue - Emit block data. /// -void DIEBlock::EmitValue(DwarfPrinter *D, unsigned Form) const { - const AsmPrinter *Asm = D->getAsm(); +void DIEBlock::EmitValue(AsmPrinter *Asm, unsigned Form) const { switch (Form) { - case dwarf::DW_FORM_block1: Asm->EmitInt8(Size); break; - case dwarf::DW_FORM_block2: Asm->EmitInt16(Size); break; - case dwarf::DW_FORM_block4: Asm->EmitInt32(Size); break; - case dwarf::DW_FORM_block: D->EmitULEB128(Size); break; - default: llvm_unreachable("Improper form for block"); break; + default: assert(0 && "Improper form for block"); break; + case dwarf::DW_FORM_block1: Asm->EmitInt8(Size); break; + case dwarf::DW_FORM_block2: Asm->EmitInt16(Size); break; + case dwarf::DW_FORM_block4: Asm->EmitInt32(Size); break; + case dwarf::DW_FORM_block: Asm->EmitULEB128(Size); break; } const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev.getData(); for (unsigned i = 0, N = Values.size(); i < N; ++i) - Values[i]->EmitValue(D, AbbrevData[i].getForm()); + Values[i]->EmitValue(Asm, AbbrevData[i].getForm()); } /// SizeOf - Determine size of block data in bytes. /// -unsigned DIEBlock::SizeOf(const TargetData *TD, unsigned Form) const { +unsigned DIEBlock::SizeOf(AsmPrinter *AP, unsigned Form) const { switch (Form) { case dwarf::DW_FORM_block1: return Size + sizeof(int8_t); case dwarf::DW_FORM_block2: return Size + sizeof(int16_t); case dwarf::DW_FORM_block4: return Size + sizeof(int32_t); - case dwarf::DW_FORM_block: return Size + MCAsmInfo::getULEB128Size(Size); + case dwarf::DW_FORM_block: return Size + MCAsmInfo::getULEB128Size(Size); default: llvm_unreachable("Improper form for block"); break; } return 0; diff --git a/lib/CodeGen/AsmPrinter/DIE.h b/lib/CodeGen/AsmPrinter/DIE.h index 8b27ed20cb63..454326db0ea1 100644 --- a/lib/CodeGen/AsmPrinter/DIE.h +++ b/lib/CodeGen/AsmPrinter/DIE.h @@ -22,8 +22,6 @@ namespace llvm { class AsmPrinter; - class DwarfPrinter; - class TargetData; class MCSymbol; class raw_ostream; @@ -101,7 +99,7 @@ namespace llvm { /// Emit - Print the abbreviation using the specified asm printer. /// - void Emit(const DwarfPrinter *DP) const; + void Emit(AsmPrinter *AP) const; #ifndef NDEBUG void print(raw_ostream &O); @@ -221,11 +219,11 @@ namespace llvm { /// EmitValue - Emit value via the Dwarf writer. /// - virtual void EmitValue(DwarfPrinter *D, unsigned Form) const = 0; + virtual void EmitValue(AsmPrinter *AP, unsigned Form) const = 0; /// SizeOf - Return the size of a value in bytes. /// - virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const = 0; + virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const = 0; // Implement isa/cast/dyncast. static bool classof(const DIEValue *) { return true; } @@ -261,11 +259,11 @@ namespace llvm { /// EmitValue - Emit integer of appropriate size. /// - virtual void EmitValue(DwarfPrinter *D, unsigned Form) const; + virtual void EmitValue(AsmPrinter *AP, unsigned Form) const; /// SizeOf - Determine size of integer value in bytes. /// - virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const; + virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const; // Implement isa/cast/dyncast. @@ -287,11 +285,11 @@ namespace llvm { /// EmitValue - Emit string value. /// - virtual void EmitValue(DwarfPrinter *D, unsigned Form) const; + virtual void EmitValue(AsmPrinter *AP, unsigned Form) const; /// SizeOf - Determine size of string value in bytes. /// - virtual unsigned SizeOf(const TargetData *, unsigned /*Form*/) const { + virtual unsigned SizeOf(AsmPrinter *AP, unsigned /*Form*/) const { return Str.size() + sizeof(char); // sizeof('\0'); } @@ -314,11 +312,11 @@ namespace llvm { /// EmitValue - Emit label value. /// - virtual void EmitValue(DwarfPrinter *D, unsigned Form) const; + virtual void EmitValue(AsmPrinter *AP, unsigned Form) const; /// SizeOf - Determine size of label value in bytes. /// - virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const; + virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const; // Implement isa/cast/dyncast. static bool classof(const DIELabel *) { return true; } @@ -341,11 +339,11 @@ namespace llvm { /// EmitValue - Emit delta value. /// - virtual void EmitValue(DwarfPrinter *D, unsigned Form) const; + virtual void EmitValue(AsmPrinter *AP, unsigned Form) const; /// SizeOf - Determine size of delta value in bytes. /// - virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const; + virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const; // Implement isa/cast/dyncast. static bool classof(const DIEDelta *) { return true; } @@ -369,11 +367,11 @@ namespace llvm { /// EmitValue - Emit debug information entry offset. /// - virtual void EmitValue(DwarfPrinter *D, unsigned Form) const; + virtual void EmitValue(AsmPrinter *AP, unsigned Form) const; /// SizeOf - Determine size of debug information entry in bytes. /// - virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const { + virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const { return sizeof(int32_t); } @@ -398,7 +396,7 @@ namespace llvm { /// ComputeSize - calculate the size of the block. /// - unsigned ComputeSize(const TargetData *TD); + unsigned ComputeSize(AsmPrinter *AP); /// BestForm - Choose the best form for data. /// @@ -411,11 +409,11 @@ namespace llvm { /// EmitValue - Emit block data. /// - virtual void EmitValue(DwarfPrinter *D, unsigned Form) const; + virtual void EmitValue(AsmPrinter *AP, unsigned Form) const; /// SizeOf - Determine size of block data in bytes. /// - virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const; + virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const; // Implement isa/cast/dyncast. static bool classof(const DIEBlock *) { return true; } diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 9084456c8f4d..b472d1e5335c 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -13,6 +13,8 @@ #define DEBUG_TYPE "dwarfdebug" #include "DwarfDebug.h" +#include "DIE.h" +#include "llvm/Constants.h" #include "llvm/Module.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineModuleInfo.h" @@ -24,7 +26,9 @@ #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameInfo.h" #include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Analysis/DebugInfo.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Debug.h" @@ -269,6 +273,8 @@ public: void dump() const; #endif }; + +} // end llvm namespace #ifndef NDEBUG void DbgScope::dump() const { @@ -296,16 +302,19 @@ DbgScope::~DbgScope() { delete Variables[j]; } -} // end llvm namespace - -DwarfDebug::DwarfDebug(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T) - : DwarfPrinter(OS, A, T), ModuleCU(0), - AbbreviationsSet(InitAbbreviationsSetSize), Abbreviations(), - DIEBlocks(), SectionSourceLines(), didInitial(false), shouldEmit(false), +DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) + : Asm(A), MMI(Asm->MMI), ModuleCU(0), + AbbreviationsSet(InitAbbreviationsSetSize), CurrentFnDbgScope(0), DebugTimer(0) { NextStringPoolNumber = 0; + + DwarfFrameSectionSym = DwarfInfoSectionSym = DwarfAbbrevSectionSym = 0; + DwarfStrSectionSym = TextSectionSym = 0; + if (TimePassesIsEnabled) DebugTimer = new Timer("Dwarf Debug Writer"); + + beginModule(M); } DwarfDebug::~DwarfDebug() { for (unsigned j = 0, M = DIEBlocks.size(); j < M; ++j) @@ -319,7 +328,7 @@ MCSymbol *DwarfDebug::getStringPoolEntry(StringRef Str) { if (Entry.first) return Entry.first; Entry.second = NextStringPoolNumber++; - return Entry.first = getDWLabel("string", Entry.second); + return Entry.first = Asm->GetTempSymbol("string", Entry.second); } @@ -395,11 +404,19 @@ void DwarfDebug::addDelta(DIE *Die, unsigned Attribute, unsigned Form, Die->addValue(Attribute, Form, Value); } +/// addDIEEntry - Add a DIE attribute data and value. +/// +void DwarfDebug::addDIEEntry(DIE *Die, unsigned Attribute, unsigned Form, + DIE *Entry) { + Die->addValue(Attribute, Form, createDIEEntry(Entry)); +} + + /// addBlock - Add block data. /// void DwarfDebug::addBlock(DIE *Die, unsigned Attribute, unsigned Form, DIEBlock *Block) { - Block->ComputeSize(TD); + Block->ComputeSize(Asm); DIEBlocks.push_back(Block); // Memoize so we can call the destructor later on. Die->addValue(Attribute, Block->BestForm(), Block); } @@ -553,6 +570,7 @@ void DwarfDebug::addComplexAddress(DbgVariable *&DV, DIE *Die, // Decode the original location, and use that as the start of the byref // variable's location. + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false); DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); @@ -693,6 +711,7 @@ void DwarfDebug::addBlockByrefAddress(DbgVariable *&DV, DIE *Die, // Decode the original location, and use that as the start of the byref // variable's location. + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false); DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); @@ -748,6 +767,7 @@ void DwarfDebug::addBlockByrefAddress(DbgVariable *&DV, DIE *Die, /// provided. void DwarfDebug::addAddress(DIE *Die, unsigned Attribute, const MachineLocation &Location) { + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false); DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); @@ -1114,7 +1134,8 @@ DIE *DwarfDebug::createMemberDIE(const DIDerivedType &DT) { Offset -= FieldOffset; // Maybe we need to work from the other end. - if (TD->isLittleEndian()) Offset = FieldSize - (Offset + Size); + if (Asm->getTargetData().isLittleEndian()) + Offset = FieldSize - (Offset + Size); addUInt(MemberDie, dwarf::DW_AT_bit_offset, 0, Offset); // Here WD_AT_data_member_location points to the anonymous @@ -1272,7 +1293,7 @@ DbgScope *DwarfDebug::getUpdatedDbgScope(MDNode *N, const MachineInstr *MI, if (!Parent && !InlinedAt) { StringRef SPName = DISubprogram(N).getLinkageName(); - if (SPName == MF->getFunction()->getName()) + if (SPName == Asm->MF->getFunction()->getName()) CurrentFnDbgScope = NScope; } @@ -1316,50 +1337,51 @@ DbgScope *DwarfDebug::getOrCreateAbstractScope(MDNode *N) { /// If there are global variables in this scope then create and insert /// DIEs for these variables. DIE *DwarfDebug::updateSubprogramScopeDIE(MDNode *SPNode) { - DIE *SPDie = ModuleCU->getDIE(SPNode); - assert(SPDie && "Unable to find subprogram DIE!"); - DISubprogram SP(SPNode); + DIE *SPDie = ModuleCU->getDIE(SPNode); + assert(SPDie && "Unable to find subprogram DIE!"); + DISubprogram SP(SPNode); + + // 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. + if (SP.isDefinition() && !SP.getContext().isCompileUnit() && + !SP.getContext().isFile() && !SP.getContext().isSubprogram()) { + addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); + + // Add arguments. + DICompositeType SPTy = SP.getType(); + DIArray Args = SPTy.getTypeArray(); + unsigned SPTag = SPTy.getTag(); + if (SPTag == dwarf::DW_TAG_subroutine_type) + for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { + DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); + DIType ATy = DIType(DIType(Args.getElement(i).getNode())); + addType(Arg, ATy); + if (ATy.isArtificial()) + addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); + SPDie->addChild(Arg); + } + DIE *SPDeclDie = SPDie; + SPDie = new DIE(dwarf::DW_TAG_subprogram); + addDIEEntry(SPDie, dwarf::DW_AT_specification, dwarf::DW_FORM_ref4, + SPDeclDie); + ModuleCU->addDie(SPDie); + } + + addLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, + Asm->GetTempSymbol("func_begin", Asm->getFunctionNumber())); + addLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, + Asm->GetTempSymbol("func_end", Asm->getFunctionNumber())); + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); + MachineLocation Location(RI->getFrameRegister(*Asm->MF)); + addAddress(SPDie, dwarf::DW_AT_frame_base, Location); + + if (!DISubprogram(SPNode).isLocalToUnit()) + addUInt(SPDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); - // 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. - if (SP.isDefinition() && !SP.getContext().isCompileUnit() && - !SP.getContext().isFile() && !SP.getContext().isSubprogram()) { - addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); - - // Add arguments. - DICompositeType SPTy = SP.getType(); - DIArray Args = SPTy.getTypeArray(); - unsigned SPTag = SPTy.getTag(); - if (SPTag == dwarf::DW_TAG_subroutine_type) - for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { - DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); - DIType ATy = DIType(DIType(Args.getElement(i).getNode())); - addType(Arg, ATy); - if (ATy.isArtificial()) - addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); - SPDie->addChild(Arg); - } - DIE *SPDeclDie = SPDie; - SPDie = new DIE(dwarf::DW_TAG_subprogram); - addDIEEntry(SPDie, dwarf::DW_AT_specification, dwarf::DW_FORM_ref4, - SPDeclDie); - ModuleCU->addDie(SPDie); - } - - addLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, - getDWLabel("func_begin", SubprogramCount)); - addLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, - getDWLabel("func_end", SubprogramCount)); - MachineLocation Location(RI->getFrameRegister(*MF)); - addAddress(SPDie, dwarf::DW_AT_frame_base, Location); - - if (!DISubprogram(SPNode).isLocalToUnit()) - addUInt(SPDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); - - return SPDie; + return SPDie; } /// constructLexicalScope - Construct new DW_TAG_lexical_block @@ -1377,9 +1399,10 @@ DIE *DwarfDebug::constructLexicalScopeDIE(DbgScope *Scope) { return ScopeDIE; addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, - Start ? Start : getDWLabel("func_begin", SubprogramCount)); + Start ? Start : Asm->GetTempSymbol("func_begin", + Asm->getFunctionNumber())); addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, - End ? End : getDWLabel("func_end", SubprogramCount)); + End ? End : Asm->GetTempSymbol("func_end",Asm->getFunctionNumber())); return ScopeDIE; } @@ -1510,6 +1533,31 @@ DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV, DbgScope *Scope) { if (MCSymbol *VS = DV->getDbgValueLabel()) addLabel(VariableDie, dwarf::DW_AT_start_scope, dwarf::DW_FORM_addr, VS); + } else if (DbgValueInsn->getOperand(0).getType() == + MachineOperand::MO_FPImmediate) { + DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + APFloat FPImm = DbgValueInsn->getOperand(0).getFPImm()->getValueAPF(); + + // Get the raw data form of the floating point. + const APInt FltVal = FPImm.bitcastToAPInt(); + const char *FltPtr = (const char*)FltVal.getRawData(); + + unsigned NumBytes = FltVal.getBitWidth() / 8; // 8 bits per byte. + bool LittleEndian = Asm->getTargetData().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, 0, dwarf::DW_FORM_data1, + (unsigned char)0xFF & FltPtr[Start]); + + addBlock(VariableDie, dwarf::DW_AT_const_value, 0, Block); + + if (MCSymbol *VS = DV->getDbgValueLabel()) + addLabel(VariableDie, dwarf::DW_AT_start_scope, dwarf::DW_FORM_addr, + VS); } else { //FIXME : Handle other operand types. delete VariableDie; @@ -1519,7 +1567,8 @@ DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV, DbgScope *Scope) { } else { MachineLocation Location; unsigned FrameReg; - int Offset = RI->getFrameIndexReference(*MF, DV->getFrameIndex(), + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); + int Offset = RI->getFrameIndexReference(*Asm->MF, DV->getFrameIndex(), FrameReg); Location.set(FrameReg, Offset); @@ -1667,10 +1716,9 @@ void DwarfDebug::constructCompileUnit(MDNode *N) { addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data1, DIUnit.getLanguage()); addString(Die, dwarf::DW_AT_name, dwarf::DW_FORM_string, FN); - addLabel(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, - getTempLabel("text_begin")); + addLabel(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, TextSectionSym); addLabel(Die, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, - getTempLabel("text_end")); + Asm->GetTempSymbol("text_end")); // DW_AT_stmt_list is a offset of line number information for this // compile unit in debug_line section. It is always zero when only one // compile unit is emitted in one object file. @@ -1780,25 +1828,37 @@ void DwarfDebug::constructSubprogramDIE(MDNode *N) { /// beginModule - Emit all Dwarf sections that should come prior to the /// content. Create global DIEs and emit initial debug info sections. /// This is inovked by the target AsmPrinter. -void DwarfDebug::beginModule(Module *M, MachineModuleInfo *mmi) { - this->M = M; - - if (!MAI->doesSupportDebugInformation()) - return; - +void DwarfDebug::beginModule(Module *M) { TimeRegion Timer(DebugTimer); - + DebugInfoFinder DbgFinder; DbgFinder.processModule(*M); + bool HasDebugInfo = false; + + // Scan all the compile-units to see if there are any marked as the main unit. + // if not, we do not generate debug info. + for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(), + E = DbgFinder.compile_unit_end(); I != E; ++I) { + if (DICompileUnit(*I).isMain()) { + HasDebugInfo = true; + break; + } + } + + if (!HasDebugInfo) return; + + // Tell MMI that we have debug info. + MMI->setDebugInfoAvailability(true); + + // Emit initial sections. + EmitSectionLabels(); + // Create all the compile unit DIEs. for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(), E = DbgFinder.compile_unit_end(); I != E; ++I) constructCompileUnit(*I); - if (!ModuleCU) - return; - // Create DIEs for each subprogram. for (DebugInfoFinder::iterator I = DbgFinder.subprogram_begin(), E = DbgFinder.subprogram_end(); I != E; ++I) @@ -1809,16 +1869,12 @@ void DwarfDebug::beginModule(Module *M, MachineModuleInfo *mmi) { E = DbgFinder.global_variable_end(); I != E; ++I) constructGlobalVariableDIE(*I); - MMI = mmi; - shouldEmit = true; - MMI->setDebugInfoAvailability(true); - // Prime section data. SectionMap.insert(Asm->getObjFileLowering().getTextSection()); // Print out .file directives to specify files for .loc directives. These are // printed out early so that they precede any .loc directives. - if (MAI->hasDotLocAndDotFile()) { + if (Asm->MAI->hasDotLocAndDotFile()) { for (unsigned i = 1, e = getNumSourceIds()+1; i != e; ++i) { // Remember source id starts at 1. std::pair<unsigned, unsigned> Id = getSourceDirectoryAndFileIds(i); @@ -1832,9 +1888,6 @@ void DwarfDebug::beginModule(Module *M, MachineModuleInfo *mmi) { Asm->OutStreamer.EmitDwarfFileDirective(i, FullPath.str()); } } - - // Emit initial sections - emitInitial(); } /// endModule - Emit all Dwarf sections that should come after the content. @@ -1871,14 +1924,14 @@ void DwarfDebug::endModule() { // Standard sections final addresses. Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getTextSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("text_end")); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("text_end")); Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getDataSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("data_end")); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("data_end")); // End text sections. for (unsigned i = 1, N = SectionMap.size(); i <= N; ++i) { Asm->OutStreamer.SwitchSection(SectionMap[i]); - Asm->OutStreamer.EmitLabel(getDWLabel("section_end", i)); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("section_end", i)); } // Emit common frame information. @@ -1975,9 +2028,7 @@ DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &Var, /// collectVariableInfo - Populate DbgScope entries with variables' info. void DwarfDebug::collectVariableInfo() { - if (!MMI) return; - - const LLVMContext &Ctx = MF->getFunction()->getContext(); + const LLVMContext &Ctx = Asm->MF->getFunction()->getContext(); MachineModuleInfo::VariableDbgInfoMapTy &VMap = MMI->getVariableDbgInfo(); for (MachineModuleInfo::VariableDbgInfoMapTy::iterator VI = VMap.begin(), @@ -2003,7 +2054,7 @@ void DwarfDebug::collectVariableInfo() { } // Collect variable information from DBG_VALUE machine instructions; - for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); + for (MachineFunction::const_iterator I = Asm->MF->begin(), E = Asm->MF->end(); I != E; ++I) { for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); II != IE; ++II) { @@ -2055,7 +2106,7 @@ void DwarfDebug::beginScope(const MachineInstr *MI) { if (DL == PrevInstLoc) return; - MDNode *Scope = DL.getScope(MF->getFunction()->getContext()); + MDNode *Scope = DL.getScope(Asm->MF->getFunction()->getContext()); // FIXME: Should only verify each scope once! if (!DIScope(Scope).Verify()) @@ -2148,10 +2199,10 @@ bool DwarfDebug::extractScopeInformation() { DenseMap<const MachineInstr *, unsigned> MIIndexMap; unsigned MIIndex = 0; - LLVMContext &Ctx = MF->getFunction()->getContext(); + LLVMContext &Ctx = Asm->MF->getFunction()->getContext(); // Scan each instruction and create scopes. First build working set of scopes. - for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); + for (MachineFunction::const_iterator I = Asm->MF->begin(), E = Asm->MF->end(); I != E; ++I) { for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); II != IE; ++II) { @@ -2175,7 +2226,7 @@ bool DwarfDebug::extractScopeInformation() { // Build scope hierarchy using working set of scopes. - for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); + for (MachineFunction::const_iterator I = Asm->MF->begin(), E = Asm->MF->end(); I != E; ++I) { for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); II != IE; ++II) { @@ -2243,18 +2294,17 @@ bool DwarfDebug::extractScopeInformation() { /// beginFunction - Gather pre-function debug information. Assumes being /// emitted immediately after the function entry point. void DwarfDebug::beginFunction(const MachineFunction *MF) { - this->MF = MF; - - if (!ShouldEmitDwarfDebug()) return; + if (!MMI->hasDebugInfo()) return; + + TimeRegion Timer(DebugTimer); if (!extractScopeInformation()) return; - TimeRegion Timer(DebugTimer); - collectVariableInfo(); // Assumes in correct section after the entry point. - Asm->OutStreamer.EmitLabel(getDWLabel("func_begin", ++SubprogramCount)); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("func_begin", + Asm->getFunctionNumber())); // Emit label for the implicitly defined dbg.stoppoint at the start of the // function. @@ -2279,14 +2329,15 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { /// endFunction - Gather and emit post-function debug information. /// void DwarfDebug::endFunction(const MachineFunction *MF) { - if (!ShouldEmitDwarfDebug()) return; - if (DbgScopeMap.empty()) return; + if (!MMI->hasDebugInfo() || + DbgScopeMap.empty()) return; TimeRegion Timer(DebugTimer); if (CurrentFnDbgScope) { // Define end label for subprogram. - Asm->OutStreamer.EmitLabel(getDWLabel("func_end", SubprogramCount)); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("func_end", + Asm->getFunctionNumber())); // Get function line info. if (!Lines.empty()) { @@ -2306,7 +2357,7 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { constructScopeDIE(CurrentFnDbgScope); - DebugFrames.push_back(FunctionDebugFrameInfo(SubprogramCount, + DebugFrames.push_back(FunctionDebugFrameInfo(Asm->getFunctionNumber(), MMI->getFrameMoves())); } @@ -2327,9 +2378,6 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { /// unique label that was emitted and which provides correspondence to /// the source line list. MCSymbol *DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, MDNode *S) { - if (!MMI) - return 0; - TimeRegion Timer(DebugTimer); StringRef Dir; @@ -2404,7 +2452,7 @@ DwarfDebug::computeSizeAndOffset(DIE *Die, unsigned Offset, bool Last) { // Size the DIE attribute values. for (unsigned i = 0, N = Values.size(); i < N; ++i) // Size attribute value. - Offset += Values[i]->SizeOf(TD, AbbrevData[i].getForm()); + Offset += Values[i]->SizeOf(Asm, AbbrevData[i].getForm()); // Size the DIE children if any. if (!Children.empty()) { @@ -2436,50 +2484,48 @@ void DwarfDebug::computeSizeAndOffsets() { CompileUnitOffsets[ModuleCU] = 0; } -/// emitInitial - Emit initial Dwarf declarations. This is necessary for cc -/// tools to recognize the object file contains Dwarf information. -void DwarfDebug::emitInitial() { - // Check to see if we already emitted intial headers. - if (didInitial) return; - didInitial = true; +/// EmitSectionSym - 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; +} +/// EmitSectionLabels - 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. - if (MAI->doesDwarfRequireFrameSection()) { - Asm->OutStreamer.SwitchSection(TLOF.getDwarfFrameSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("section_debug_frame")); - } - - Asm->OutStreamer.SwitchSection(TLOF.getDwarfInfoSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("section_info")); - Asm->OutStreamer.SwitchSection(TLOF.getDwarfAbbrevSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("section_abbrev")); - Asm->OutStreamer.SwitchSection(TLOF.getDwarfARangesSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("section_aranges")); - - if (const MCSection *LineInfoDirective = TLOF.getDwarfMacroInfoSection()) { - Asm->OutStreamer.SwitchSection(LineInfoDirective); - Asm->OutStreamer.EmitLabel(getTempLabel("section_macinfo")); - } - - Asm->OutStreamer.SwitchSection(TLOF.getDwarfLineSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("section_line")); - Asm->OutStreamer.SwitchSection(TLOF.getDwarfLocSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("section_loc")); - Asm->OutStreamer.SwitchSection(TLOF.getDwarfPubNamesSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("section_pubnames")); - Asm->OutStreamer.SwitchSection(TLOF.getDwarfPubTypesSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("section_pubtypes")); - Asm->OutStreamer.SwitchSection(TLOF.getDwarfStrSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("section_str")); - Asm->OutStreamer.SwitchSection(TLOF.getDwarfRangesSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("section_ranges")); - - Asm->OutStreamer.SwitchSection(TLOF.getTextSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("text_begin")); - Asm->OutStreamer.SwitchSection(TLOF.getDataSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("data_begin")); + if (Asm->MAI->doesDwarfRequireFrameSection()) { + DwarfFrameSectionSym = + EmitSectionSym(Asm, TLOF.getDwarfFrameSection(), "section_debug_frame"); + } + + DwarfInfoSectionSym = + EmitSectionSym(Asm, TLOF.getDwarfInfoSection(), "section_info"); + DwarfAbbrevSectionSym = + EmitSectionSym(Asm, TLOF.getDwarfAbbrevSection(), "section_abbrev"); + EmitSectionSym(Asm, TLOF.getDwarfARangesSection()); + + if (const MCSection *MacroInfo = TLOF.getDwarfMacroInfoSection()) + EmitSectionSym(Asm, MacroInfo); + + EmitSectionSym(Asm, TLOF.getDwarfLineSection()); + EmitSectionSym(Asm, TLOF.getDwarfLocSection()); + EmitSectionSym(Asm, TLOF.getDwarfPubNamesSection()); + EmitSectionSym(Asm, TLOF.getDwarfPubTypesSection()); + DwarfStrSectionSym = + EmitSectionSym(Asm, TLOF.getDwarfStrSection(), "section_str"); + EmitSectionSym(Asm, TLOF.getDwarfRangesSection()); + + TextSectionSym = EmitSectionSym(Asm, TLOF.getTextSection(), "text_begin"); + EmitSectionSym(Asm, TLOF.getDataSection()); } /// emitDIE - Recusively Emits a debug information entry. @@ -2490,12 +2536,12 @@ void DwarfDebug::emitDIE(DIE *Die) { const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1]; // Emit the code (index) for the abbreviation. - if (Asm->VerboseAsm) + if (Asm->isVerbose()) Asm->OutStreamer.AddComment("Abbrev [" + Twine(AbbrevNumber) + "] 0x" + Twine::utohexstr(Die->getOffset()) + ":0x" + Twine::utohexstr(Die->getSize()) + " " + dwarf::TagString(Abbrev->getTag())); - EmitULEB128(AbbrevNumber); + Asm->EmitULEB128(AbbrevNumber); const SmallVector<DIEValue*, 32> &Values = Die->getValues(); const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev->getData(); @@ -2506,7 +2552,7 @@ void DwarfDebug::emitDIE(DIE *Die) { unsigned Form = AbbrevData[i].getForm(); assert(Form && "Too many attributes for DIE (check abbreviation)"); - if (Asm->VerboseAsm) + if (Asm->isVerbose()) Asm->OutStreamer.AddComment(dwarf::AttributeString(Attr)); switch (Attr) { @@ -2522,7 +2568,7 @@ void DwarfDebug::emitDIE(DIE *Die) { } default: // Emit an attribute using the defined form. - Values[i]->EmitValue(this, Form); + Values[i]->EmitValue(Asm, Form); break; } } @@ -2534,7 +2580,7 @@ void DwarfDebug::emitDIE(DIE *Die) { for (unsigned j = 0, M = Children.size(); j < M; ++j) emitDIE(Children[j]); - if (Asm->VerboseAsm) + if (Asm->isVerbose()) Asm->OutStreamer.AddComment("End Of Children Mark"); Asm->EmitInt8(0); } @@ -2549,7 +2595,8 @@ void DwarfDebug::emitDebugInfo() { DIE *Die = ModuleCU->getCUDie(); // Emit the compile units header. - Asm->OutStreamer.EmitLabel(getDWLabel("info_begin", ModuleCU->getID())); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("info_begin", + ModuleCU->getID())); // Emit size of content not including length itself unsigned ContentSize = Die->getSize() + @@ -2563,10 +2610,10 @@ void DwarfDebug::emitDebugInfo() { Asm->OutStreamer.AddComment("DWARF version number"); Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->OutStreamer.AddComment("Offset Into Abbrev. Section"); - EmitSectionOffset(getTempLabel("abbrev_begin"),getTempLabel("section_abbrev"), - true); + Asm->EmitSectionOffset(Asm->GetTempSymbol("abbrev_begin"), + DwarfAbbrevSectionSym); Asm->OutStreamer.AddComment("Address Size (in bytes)"); - Asm->EmitInt8(TD->getPointerSize()); + Asm->EmitInt8(Asm->getTargetData().getPointerSize()); emitDIE(Die); // FIXME - extra padding for gdb bug. @@ -2575,7 +2622,7 @@ void DwarfDebug::emitDebugInfo() { Asm->EmitInt8(0); Asm->EmitInt8(0); Asm->EmitInt8(0); - Asm->OutStreamer.EmitLabel(getDWLabel("info_end", ModuleCU->getID())); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("info_end", ModuleCU->getID())); } /// emitAbbreviations - Emit the abbreviation section. @@ -2587,7 +2634,7 @@ void DwarfDebug::emitAbbreviations() const { Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfAbbrevSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("abbrev_begin")); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("abbrev_begin")); // For each abbrevation. for (unsigned i = 0, N = Abbreviations.size(); i < N; ++i) { @@ -2595,16 +2642,16 @@ void DwarfDebug::emitAbbreviations() const { const DIEAbbrev *Abbrev = Abbreviations[i]; // Emit the abbrevations code (base 1 index.) - EmitULEB128(Abbrev->getNumber(), "Abbreviation Code"); + Asm->EmitULEB128(Abbrev->getNumber(), "Abbreviation Code"); // Emit the abbreviations data. - Abbrev->Emit(this); + Abbrev->Emit(Asm); } // Mark end of abbreviations. - EmitULEB128(0, "EOM(3)"); + Asm->EmitULEB128(0, "EOM(3)"); - Asm->OutStreamer.EmitLabel(getTempLabel("abbrev_end")); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("abbrev_end")); } } @@ -2617,14 +2664,15 @@ void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) { Asm->EmitInt8(0); Asm->OutStreamer.AddComment("Op size"); - Asm->EmitInt8(TD->getPointerSize() + 1); + Asm->EmitInt8(Asm->getTargetData().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(getDWLabel("section_end", SectionEnd), - TD->getPointerSize(), 0/*AddrSpace*/); + Asm->OutStreamer.EmitSymbolValue(Asm->GetTempSymbol("section_end",SectionEnd), + Asm->getTargetData().getPointerSize(), + 0/*AddrSpace*/); // Mark end of matrix. Asm->OutStreamer.AddComment("DW_LNE_end_sequence"); @@ -2638,7 +2686,7 @@ void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) { void DwarfDebug::emitDebugLines() { // If the target is using .loc/.file, the assembler will be emitting the // .debug_line table automatically. - if (MAI->hasDotLocAndDotFile()) + if (Asm->MAI->hasDotLocAndDotFile()) return; // Minimum line delta, thus ranging from -10..(255-10). @@ -2652,16 +2700,17 @@ void DwarfDebug::emitDebugLines() { // Construct the section header. Asm->OutStreamer.AddComment("Length of Source Line Info"); - EmitDifference(getTempLabel("line_end"), getTempLabel("line_begin"), true); - Asm->OutStreamer.EmitLabel(getTempLabel("line_begin")); + Asm->EmitLabelDifference(Asm->GetTempSymbol("line_end"), + Asm->GetTempSymbol("line_begin"), 4); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("line_begin")); Asm->OutStreamer.AddComment("DWARF version number"); Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->OutStreamer.AddComment("Prolog Length"); - EmitDifference(getTempLabel("line_prolog_end"), - getTempLabel("line_prolog_begin"), true); - Asm->OutStreamer.EmitLabel(getTempLabel("line_prolog_begin")); + Asm->EmitLabelDifference(Asm->GetTempSymbol("line_prolog_end"), + Asm->GetTempSymbol("line_prolog_begin"), 4); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("line_prolog_begin")); Asm->OutStreamer.AddComment("Minimum Instruction Length"); Asm->EmitInt8(1); @@ -2697,7 +2746,7 @@ void DwarfDebug::emitDebugLines() { // Emit directories. for (unsigned DI = 1, DE = getNumSourceDirectories()+1; DI != DE; ++DI) { const std::string &Dir = getSourceDirectoryName(DI); - if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("Directory"); + if (Asm->isVerbose()) Asm->OutStreamer.AddComment("Directory"); Asm->OutStreamer.EmitBytes(StringRef(Dir.c_str(), Dir.size()+1), 0); } @@ -2709,18 +2758,18 @@ void DwarfDebug::emitDebugLines() { // Remember source id starts at 1. std::pair<unsigned, unsigned> Id = getSourceDirectoryAndFileIds(SI); const std::string &FN = getSourceFileName(Id.second); - if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("Source"); + if (Asm->isVerbose()) Asm->OutStreamer.AddComment("Source"); Asm->OutStreamer.EmitBytes(StringRef(FN.c_str(), FN.size()+1), 0); - EmitULEB128(Id.first, "Directory #"); - EmitULEB128(0, "Mod date"); - EmitULEB128(0, "File size"); + Asm->EmitULEB128(Id.first, "Directory #"); + Asm->EmitULEB128(0, "Mod date"); + Asm->EmitULEB128(0, "File size"); } Asm->OutStreamer.AddComment("End of files"); Asm->EmitInt8(0); - Asm->OutStreamer.EmitLabel(getTempLabel("line_prolog_end")); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("line_prolog_end")); // A sequence for each text section. unsigned SecSrcLinesSize = SectionSourceLines.size(); @@ -2754,13 +2803,14 @@ void DwarfDebug::emitDebugLines() { Asm->OutStreamer.AddComment("Extended Op"); Asm->EmitInt8(0); Asm->OutStreamer.AddComment("Op size"); - Asm->EmitInt8(TD->getPointerSize() + 1); + Asm->EmitInt8(Asm->getTargetData().getPointerSize() + 1); Asm->OutStreamer.AddComment("DW_LNE_set_address"); Asm->EmitInt8(dwarf::DW_LNE_set_address); Asm->OutStreamer.AddComment("Location label"); - Asm->OutStreamer.EmitSymbolValue(Label, TD->getPointerSize(), + Asm->OutStreamer.EmitSymbolValue(Label, + Asm->getTargetData().getPointerSize(), 0/*AddrSpace*/); // If change of source, then switch to the new source. @@ -2768,7 +2818,7 @@ void DwarfDebug::emitDebugLines() { Source = LineInfo.getSourceID(); Asm->OutStreamer.AddComment("DW_LNS_set_file"); Asm->EmitInt8(dwarf::DW_LNS_set_file); - EmitULEB128(Source, "New Source"); + Asm->EmitULEB128(Source, "New Source"); } // If change of line. @@ -2789,7 +2839,7 @@ void DwarfDebug::emitDebugLines() { // ... otherwise use long hand. Asm->OutStreamer.AddComment("DW_LNS_advance_line"); Asm->EmitInt8(dwarf::DW_LNS_advance_line); - EmitSLEB128(Offset, "Line Offset"); + Asm->EmitSLEB128(Offset, "Line Offset"); Asm->OutStreamer.AddComment("DW_LNS_copy"); Asm->EmitInt8(dwarf::DW_LNS_copy); } @@ -2809,55 +2859,56 @@ void DwarfDebug::emitDebugLines() { // put into it, emit an empty table. emitEndOfLineMatrix(1); - Asm->OutStreamer.EmitLabel(getTempLabel("line_end")); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("line_end")); } /// emitCommonDebugFrame - Emit common frame info into a debug frame section. /// void DwarfDebug::emitCommonDebugFrame() { - if (!MAI->doesDwarfRequireFrameSection()) + if (!Asm->MAI->doesDwarfRequireFrameSection()) return; - int stackGrowth = - Asm->TM.getFrameInfo()->getStackGrowthDirection() == - TargetFrameInfo::StackGrowsUp ? - TD->getPointerSize() : -TD->getPointerSize(); + int stackGrowth = Asm->getTargetData().getPointerSize(); + if (Asm->TM.getFrameInfo()->getStackGrowthDirection() == + TargetFrameInfo::StackGrowsDown) + stackGrowth *= -1; // Start the dwarf frame section. Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfFrameSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("debug_frame_common")); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_frame_common")); Asm->OutStreamer.AddComment("Length of Common Information Entry"); - EmitDifference(getTempLabel("debug_frame_common_end"), - getTempLabel("debug_frame_common_begin"), true); + Asm->EmitLabelDifference(Asm->GetTempSymbol("debug_frame_common_end"), + Asm->GetTempSymbol("debug_frame_common_begin"), 4); - Asm->OutStreamer.EmitLabel(getTempLabel("debug_frame_common_begin")); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_frame_common_begin")); Asm->OutStreamer.AddComment("CIE Identifier Tag"); Asm->EmitInt32((int)dwarf::DW_CIE_ID); Asm->OutStreamer.AddComment("CIE Version"); Asm->EmitInt8(dwarf::DW_CIE_VERSION); Asm->OutStreamer.AddComment("CIE Augmentation"); Asm->OutStreamer.EmitIntValue(0, 1, /*addrspace*/0); // nul terminator. - EmitULEB128(1, "CIE Code Alignment Factor"); - EmitSLEB128(stackGrowth, "CIE Data Alignment Factor"); + Asm->EmitULEB128(1, "CIE Code Alignment Factor"); + Asm->EmitSLEB128(stackGrowth, "CIE Data Alignment Factor"); Asm->OutStreamer.AddComment("CIE RA Column"); + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), false)); std::vector<MachineMove> Moves; RI->getInitialFrameState(Moves); - EmitFrameMoves(0, Moves, false); + Asm->EmitFrameMoves(Moves, 0, false); Asm->EmitAlignment(2, 0, 0, false); - Asm->OutStreamer.EmitLabel(getTempLabel("debug_frame_common_end")); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_frame_common_end")); } /// emitFunctionDebugFrame - Emit per function frame info into a debug frame /// section. void DwarfDebug:: emitFunctionDebugFrame(const FunctionDebugFrameInfo &DebugFrameInfo) { - if (!MAI->doesDwarfRequireFrameSection()) + if (!Asm->MAI->doesDwarfRequireFrameSection()) return; // Start the dwarf frame section. @@ -2866,27 +2917,30 @@ emitFunctionDebugFrame(const FunctionDebugFrameInfo &DebugFrameInfo) { Asm->OutStreamer.AddComment("Length of Frame Information Entry"); MCSymbol *DebugFrameBegin = - getDWLabel("debug_frame_begin", DebugFrameInfo.Number); + Asm->GetTempSymbol("debug_frame_begin", DebugFrameInfo.Number); MCSymbol *DebugFrameEnd = - getDWLabel("debug_frame_end", DebugFrameInfo.Number); - EmitDifference(DebugFrameEnd, DebugFrameBegin, true); + Asm->GetTempSymbol("debug_frame_end", DebugFrameInfo.Number); + Asm->EmitLabelDifference(DebugFrameEnd, DebugFrameBegin, 4); Asm->OutStreamer.EmitLabel(DebugFrameBegin); Asm->OutStreamer.AddComment("FDE CIE offset"); - EmitSectionOffset(getTempLabel("debug_frame_common"), - getTempLabel("section_debug_frame"), true); + Asm->EmitSectionOffset(Asm->GetTempSymbol("debug_frame_common"), + DwarfFrameSectionSym); Asm->OutStreamer.AddComment("FDE initial location"); - MCSymbol *FuncBeginSym = getDWLabel("func_begin", DebugFrameInfo.Number); + MCSymbol *FuncBeginSym = + Asm->GetTempSymbol("func_begin", DebugFrameInfo.Number); Asm->OutStreamer.EmitSymbolValue(FuncBeginSym, - TD->getPointerSize(), 0/*AddrSpace*/); + Asm->getTargetData().getPointerSize(), + 0/*AddrSpace*/); Asm->OutStreamer.AddComment("FDE address range"); - EmitDifference(getDWLabel("func_end", DebugFrameInfo.Number), FuncBeginSym); + Asm->EmitLabelDifference(Asm->GetTempSymbol("func_end",DebugFrameInfo.Number), + FuncBeginSym, Asm->getTargetData().getPointerSize()); - EmitFrameMoves(FuncBeginSym, DebugFrameInfo.Moves, false); + Asm->EmitFrameMoves(DebugFrameInfo.Moves, FuncBeginSym, false); Asm->EmitAlignment(2, 0, 0, false); Asm->OutStreamer.EmitLabel(DebugFrameEnd); @@ -2900,22 +2954,24 @@ void DwarfDebug::emitDebugPubNames() { Asm->getObjFileLowering().getDwarfPubNamesSection()); Asm->OutStreamer.AddComment("Length of Public Names Info"); - EmitDifference(getDWLabel("pubnames_end", ModuleCU->getID()), - getDWLabel("pubnames_begin", ModuleCU->getID()), true); + Asm->EmitLabelDifference( + Asm->GetTempSymbol("pubnames_end", ModuleCU->getID()), + Asm->GetTempSymbol("pubnames_begin", ModuleCU->getID()), 4); - Asm->OutStreamer.EmitLabel(getDWLabel("pubnames_begin", ModuleCU->getID())); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubnames_begin", + ModuleCU->getID())); Asm->OutStreamer.AddComment("DWARF Version"); Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->OutStreamer.AddComment("Offset of Compilation Unit Info"); - EmitSectionOffset(getDWLabel("info_begin", ModuleCU->getID()), - getTempLabel("section_info"), true); + Asm->EmitSectionOffset(Asm->GetTempSymbol("info_begin", ModuleCU->getID()), + DwarfInfoSectionSym); Asm->OutStreamer.AddComment("Compilation Unit Length"); - EmitDifference(getDWLabel("info_end", ModuleCU->getID()), - getDWLabel("info_begin", ModuleCU->getID()), - true); + Asm->EmitLabelDifference(Asm->GetTempSymbol("info_end", ModuleCU->getID()), + Asm->GetTempSymbol("info_begin", ModuleCU->getID()), + 4); const StringMap<DIE*> &Globals = ModuleCU->getGlobals(); for (StringMap<DIE*>::const_iterator @@ -2926,14 +2982,15 @@ void DwarfDebug::emitDebugPubNames() { Asm->OutStreamer.AddComment("DIE offset"); Asm->EmitInt32(Entity->getOffset()); - if (Asm->VerboseAsm) + if (Asm->isVerbose()) Asm->OutStreamer.AddComment("External Name"); Asm->OutStreamer.EmitBytes(StringRef(Name, strlen(Name)+1), 0); } Asm->OutStreamer.AddComment("End Mark"); Asm->EmitInt32(0); - Asm->OutStreamer.EmitLabel(getDWLabel("pubnames_end", ModuleCU->getID())); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubnames_end", + ModuleCU->getID())); } void DwarfDebug::emitDebugPubTypes() { @@ -2941,22 +2998,24 @@ void DwarfDebug::emitDebugPubTypes() { Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfPubTypesSection()); Asm->OutStreamer.AddComment("Length of Public Types Info"); - EmitDifference(getDWLabel("pubtypes_end", ModuleCU->getID()), - getDWLabel("pubtypes_begin", ModuleCU->getID()), true); + Asm->EmitLabelDifference( + Asm->GetTempSymbol("pubtypes_end", ModuleCU->getID()), + Asm->GetTempSymbol("pubtypes_begin", ModuleCU->getID()), 4); - Asm->OutStreamer.EmitLabel(getDWLabel("pubtypes_begin", ModuleCU->getID())); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubtypes_begin", + ModuleCU->getID())); - if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("DWARF Version"); + if (Asm->isVerbose()) Asm->OutStreamer.AddComment("DWARF Version"); Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->OutStreamer.AddComment("Offset of Compilation ModuleCU Info"); - EmitSectionOffset(getDWLabel("info_begin", ModuleCU->getID()), - getTempLabel("section_info"), true); + Asm->EmitSectionOffset(Asm->GetTempSymbol("info_begin", ModuleCU->getID()), + DwarfInfoSectionSym); Asm->OutStreamer.AddComment("Compilation ModuleCU Length"); - EmitDifference(getDWLabel("info_end", ModuleCU->getID()), - getDWLabel("info_begin", ModuleCU->getID()), - true); + Asm->EmitLabelDifference(Asm->GetTempSymbol("info_end", ModuleCU->getID()), + Asm->GetTempSymbol("info_begin", ModuleCU->getID()), + 4); const StringMap<DIE*> &Globals = ModuleCU->getGlobalTypes(); for (StringMap<DIE*>::const_iterator @@ -2964,16 +3023,17 @@ void DwarfDebug::emitDebugPubTypes() { const char *Name = GI->getKeyData(); DIE * Entity = GI->second; - if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("DIE offset"); + if (Asm->isVerbose()) Asm->OutStreamer.AddComment("DIE offset"); Asm->EmitInt32(Entity->getOffset()); - if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("External Name"); + if (Asm->isVerbose()) Asm->OutStreamer.AddComment("External Name"); Asm->OutStreamer.EmitBytes(StringRef(Name, GI->getKeyLength()+1), 0); } Asm->OutStreamer.AddComment("End Mark"); Asm->EmitInt32(0); - Asm->OutStreamer.EmitLabel(getDWLabel("pubtypes_end", ModuleCU->getID())); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubtypes_end", + ModuleCU->getID())); } /// emitDebugStr - Emit visible names into a debug str section. @@ -3059,7 +3119,7 @@ void DwarfDebug::emitDebugMacInfo() { /// __debug_info section, and the low_pc is the starting address for the /// inlining instance. void DwarfDebug::emitDebugInlineInfo() { - if (!MAI->doesDwarfUsesInlineInfoSection()) + if (!Asm->MAI->doesDwarfUsesInlineInfoSection()) return; if (!ModuleCU) @@ -3069,15 +3129,15 @@ void DwarfDebug::emitDebugInlineInfo() { Asm->getObjFileLowering().getDwarfDebugInlineSection()); Asm->OutStreamer.AddComment("Length of Debug Inlined Information Entry"); - EmitDifference(getDWLabel("debug_inlined_end", 1), - getDWLabel("debug_inlined_begin", 1), true); + Asm->EmitLabelDifference(Asm->GetTempSymbol("debug_inlined_end", 1), + Asm->GetTempSymbol("debug_inlined_begin", 1), 4); - Asm->OutStreamer.EmitLabel(getDWLabel("debug_inlined_begin", 1)); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_inlined_begin", 1)); Asm->OutStreamer.AddComment("Dwarf Version"); Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->OutStreamer.AddComment("Address Size (in bytes)"); - Asm->EmitInt8(TD->getPointerSize()); + Asm->EmitInt8(Asm->getTargetData().getPointerSize()); for (SmallVector<MDNode *, 4>::iterator I = InlinedSPNodes.begin(), E = InlinedSPNodes.end(); I != E; ++I) { @@ -3095,23 +3155,23 @@ void DwarfDebug::emitDebugInlineInfo() { Asm->OutStreamer.EmitBytes(Name, 0); Asm->OutStreamer.EmitIntValue(0, 1, 0); // nul terminator. } else - EmitSectionOffset(getStringPoolEntry(getRealLinkageName(LName)), - getTempLabel("section_str"), true); + Asm->EmitSectionOffset(getStringPoolEntry(getRealLinkageName(LName)), + DwarfStrSectionSym); Asm->OutStreamer.AddComment("Function name"); - EmitSectionOffset(getStringPoolEntry(Name), getTempLabel("section_str"), - true); - EmitULEB128(Labels.size(), "Inline count"); + Asm->EmitSectionOffset(getStringPoolEntry(Name), DwarfStrSectionSym); + Asm->EmitULEB128(Labels.size(), "Inline count"); for (SmallVector<InlineInfoLabels, 4>::iterator LI = Labels.begin(), LE = Labels.end(); LI != LE; ++LI) { - if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("DIE offset"); + if (Asm->isVerbose()) Asm->OutStreamer.AddComment("DIE offset"); Asm->EmitInt32(LI->second->getOffset()); - if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("low_pc"); - Asm->OutStreamer.EmitSymbolValue(LI->first, TD->getPointerSize(), 0); + if (Asm->isVerbose()) Asm->OutStreamer.AddComment("low_pc"); + Asm->OutStreamer.EmitSymbolValue(LI->first, + Asm->getTargetData().getPointerSize(),0); } } - Asm->OutStreamer.EmitLabel(getDWLabel("debug_inlined_end", 1)); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_inlined_end", 1)); } diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index 03d9d9935f2f..c7baf5f5d38d 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -14,19 +14,14 @@ #ifndef CODEGEN_ASMPRINTER_DWARFDEBUG_H__ #define CODEGEN_ASMPRINTER_DWARFDEBUG_H__ -#include "DIE.h" -#include "DwarfPrinter.h" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/MachineLocation.h" -#include "llvm/Analysis/DebugInfo.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/raw_ostream.h" +#include "DIE.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/UniqueVector.h" -#include <string> +#include "llvm/Support/Allocator.h" namespace llvm { @@ -35,9 +30,27 @@ class DbgConcreteScope; class DbgScope; class DbgVariable; class MachineFrameInfo; +class MachineLocation; class MachineModuleInfo; class MCAsmInfo; class Timer; +class DIEAbbrev; +class DIE; +class DIEBlock; +class DIEEntry; + +class DIEnumerator; +class DIDescriptor; +class DIVariable; +class DIGlobal; +class DIGlobalVariable; +class DISubprogram; +class DIBasicType; +class DIDerivedType; +class DIType; +class DINameSpace; +class DISubrange; +class DICompositeType; //===----------------------------------------------------------------------===// /// SrcLineInfo - This class is used to record source line correspondence. @@ -58,7 +71,13 @@ public: MCSymbol *getLabel() const { return Label; } }; -class DwarfDebug : public DwarfPrinter { +class DwarfDebug { + /// Asm - Target of Dwarf emission. + AsmPrinter *Asm; + + /// MMI - Collected machine module information. + MachineModuleInfo *MMI; + //===--------------------------------------------------------------------===// // Attributes used to construct specific Dwarf sections. // @@ -120,14 +139,6 @@ class DwarfDebug : public DwarfPrinter { /// std::vector<std::vector<SrcLineInfo> > SectionSourceLines; - /// didInitial - Flag to indicate if initial emission has been done. - /// - bool didInitial; - - /// shouldEmit - Flag to indicate if debug information should be emitted. - /// - bool shouldEmit; - // CurrentFnDbgScope - Top level scope for the current function. // DbgScope *CurrentFnDbgScope; @@ -210,6 +221,14 @@ class DwarfDebug : public DwarfPrinter { std::vector<FunctionDebugFrameInfo> DebugFrames; + // Section Symbols: these are assembler temporary labels that are emitted at + // the beginning of each supported dwarf section. These are used to form + // section offsets and are created by EmitSectionLabels. + MCSymbol *DwarfFrameSectionSym, *DwarfInfoSectionSym, *DwarfAbbrevSectionSym; + MCSymbol *DwarfStrSectionSym, *TextSectionSym; + +private: + /// getSourceDirectoryAndFileIds - Return the directory and file ids that /// maps to the source id. Source id starts at 1. std::pair<unsigned, unsigned> @@ -273,10 +292,8 @@ class DwarfDebug : public DwarfPrinter { /// addDIEEntry - Add a DIE attribute data and value. /// - void addDIEEntry(DIE *Die, unsigned Attribute, unsigned Form, DIE *Entry) { - Die->addValue(Attribute, Form, createDIEEntry(Entry)); - } - + void addDIEEntry(DIE *Die, unsigned Attribute, unsigned Form, DIE *Entry); + /// addBlock - Add block data. /// void addBlock(DIE *Die, unsigned Attribute, unsigned Form, DIEBlock *Block); @@ -396,9 +413,9 @@ class DwarfDebug : public DwarfPrinter { /// constructScopeDIE - Construct a DIE for this scope. DIE *constructScopeDIE(DbgScope *Scope); - /// emitInitial - Emit initial Dwarf declarations. This is necessary for cc - /// tools to recognize the object file contains Dwarf information. - void emitInitial(); + /// EmitSectionLabels - Emit initial Dwarf sections with a label at + /// the start of each one. + void EmitSectionLabels(); /// emitDIE - Recusively Emits a debug information entry. /// @@ -487,8 +504,8 @@ class DwarfDebug : public DwarfPrinter { /// GetOrCreateSourceID - 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. + /// in the SourceIds map. This can update DirectoryNames and SourceFileNames + /// maps as well. unsigned GetOrCreateSourceID(StringRef DirName, StringRef FileName); void constructCompileUnit(MDNode *N); @@ -503,44 +520,17 @@ class DwarfDebug : public DwarfPrinter { /// DIType getBlockByrefType(DIType Ty, std::string Name); -public: - //===--------------------------------------------------------------------===// - // Main entry points. - // - DwarfDebug(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T); - virtual ~DwarfDebug(); - - /// ShouldEmitDwarfDebug - Returns true if Dwarf debugging declarations should - /// be emitted. - bool ShouldEmitDwarfDebug() const { return shouldEmit; } - - /// beginModule - Emit all Dwarf sections that should come prior to the - /// content. - void beginModule(Module *M, MachineModuleInfo *MMI); - - /// endModule - Emit all Dwarf sections that should come after the content. - /// - void endModule(); - - /// beginFunction - Gather pre-function debug information. Assumes being - /// emitted immediately after the function entry point. - void beginFunction(const MachineFunction *MF); - - /// endFunction - Gather and emit post-function debug information. - /// - void endFunction(const MachineFunction *MF); - /// recordSourceLine - Register a source line with debug info. Returns the /// unique label that was emitted and which provides correspondence to /// the source line list. MCSymbol *recordSourceLine(unsigned Line, unsigned Col, MDNode *Scope); - + /// getSourceLineCount - Return the number of source lines in the debug /// info. unsigned getSourceLineCount() const { return Lines.size(); } - + /// getOrCreateSourceID - Public version of GetOrCreateSourceID. This can be /// timed. 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 @@ -548,13 +538,36 @@ public: /// well. unsigned getOrCreateSourceID(const std::string &DirName, const std::string &FileName); - + /// extractScopeInformation - Scan machine instructions in this function /// and collect DbgScopes. Return true, if atleast one scope was found. bool extractScopeInformation(); - + /// collectVariableInfo - Populate DbgScope entries with variables' info. void collectVariableInfo(); + +public: + //===--------------------------------------------------------------------===// + // Main entry points. + // + DwarfDebug(AsmPrinter *A, Module *M); + ~DwarfDebug(); + + /// beginModule - Emit all Dwarf sections that should come prior to the + /// content. + void beginModule(Module *M); + + /// endModule - Emit all Dwarf sections that should come after the content. + /// + void endModule(); + + /// beginFunction - Gather pre-function debug information. Assumes being + /// emitted immediately after the function entry point. + void beginFunction(const MachineFunction *MF); + + /// endFunction - Gather and emit post-function debug information. + /// + void endFunction(const MachineFunction *MF); /// beginScope - Process beginning of a scope. void beginScope(const MachineInstr *MI); diff --git a/lib/CodeGen/AsmPrinter/DwarfException.cpp b/lib/CodeGen/AsmPrinter/DwarfException.cpp index 8b616b012614..72c97a43085c 100644 --- a/lib/CodeGen/AsmPrinter/DwarfException.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfException.cpp @@ -13,6 +13,7 @@ #include "DwarfException.h" #include "llvm/Module.h" +#include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" @@ -27,6 +28,7 @@ #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameInfo.h" #include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Support/Dwarf.h" @@ -37,9 +39,8 @@ #include "llvm/ADT/Twine.h" using namespace llvm; -DwarfException::DwarfException(raw_ostream &OS, AsmPrinter *A, - const MCAsmInfo *T) - : DwarfPrinter(OS, A, T), shouldEmitTable(false),shouldEmitMoves(false), +DwarfException::DwarfException(AsmPrinter *A) + : Asm(A), MMI(Asm->MMI), shouldEmitTable(false), shouldEmitMoves(false), shouldEmitTableModule(false), shouldEmitMovesModule(false), ExceptionTimer(0) { if (TimePassesIsEnabled) @@ -55,10 +56,10 @@ DwarfException::~DwarfException() { /// in every non-empty .debug_frame section. void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { // Size and sign of stack growth. - int stackGrowth = - Asm->TM.getFrameInfo()->getStackGrowthDirection() == - TargetFrameInfo::StackGrowsUp ? - TD->getPointerSize() : -TD->getPointerSize(); + int stackGrowth = Asm->getTargetData().getPointerSize(); + if (Asm->TM.getFrameInfo()->getStackGrowthDirection() == + TargetFrameInfo::StackGrowsDown) + stackGrowth *= -1; const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); @@ -67,24 +68,25 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { MCSymbol *EHFrameSym; if (TLOF.isFunctionEHFrameSymbolPrivate()) - EHFrameSym = getDWLabel("EH_frame", Index); + EHFrameSym = Asm->GetTempSymbol("EH_frame", Index); else EHFrameSym = Asm->OutContext.GetOrCreateSymbol(Twine("EH_frame") + Twine(Index)); Asm->OutStreamer.EmitLabel(EHFrameSym); - Asm->OutStreamer.EmitLabel(getDWLabel("section_eh_frame", Index)); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("section_eh_frame", Index)); // Define base labels. - Asm->OutStreamer.EmitLabel(getDWLabel("eh_frame_common", Index)); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_frame_common", Index)); // Define the eh frame length. Asm->OutStreamer.AddComment("Length of Common Information Entry"); - EmitDifference(getDWLabel("eh_frame_common_end", Index), - getDWLabel("eh_frame_common_begin", Index), true); + Asm->EmitLabelDifference(Asm->GetTempSymbol("eh_frame_common_end", Index), + Asm->GetTempSymbol("eh_frame_common_begin", Index), + 4); // EH frame header. - Asm->OutStreamer.EmitLabel(getDWLabel("eh_frame_common_begin", Index)); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_frame_common_begin",Index)); Asm->OutStreamer.AddComment("CIE Identifier Tag"); Asm->OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/); Asm->OutStreamer.AddComment("DW_CIE_VERSION"); @@ -105,7 +107,7 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { if (PersonalityFn) { // There is a personality function. *APtr++ = 'P'; - AugmentationSize += 1 + SizeOfEncodedValue(PerEncoding); + AugmentationSize += 1 + Asm->GetSizeOfEncodedValue(PerEncoding); } if (UsesLSDA[Index]) { @@ -127,36 +129,39 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { Asm->OutStreamer.EmitBytes(StringRef(Augmentation, strlen(Augmentation)+1),0); // Round out reader. - EmitULEB128(1, "CIE Code Alignment Factor"); - EmitSLEB128(stackGrowth, "CIE Data Alignment Factor"); + Asm->EmitULEB128(1, "CIE Code Alignment Factor"); + Asm->EmitSLEB128(stackGrowth, "CIE Data Alignment Factor"); Asm->OutStreamer.AddComment("CIE Return Address Column"); + + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), true)); if (Augmentation[0]) { - EmitULEB128(AugmentationSize, "Augmentation Size"); + Asm->EmitULEB128(AugmentationSize, "Augmentation Size"); // If there is a personality, we need to indicate the function's location. if (PersonalityFn) { - EmitEncodingByte(PerEncoding, "Personality"); + Asm->EmitEncodingByte(PerEncoding, "Personality"); Asm->OutStreamer.AddComment("Personality"); - EmitReference(PersonalityFn, PerEncoding); + Asm->EmitReference(PersonalityFn, PerEncoding); } if (UsesLSDA[Index]) - EmitEncodingByte(LSDAEncoding, "LSDA"); + Asm->EmitEncodingByte(LSDAEncoding, "LSDA"); if (FDEEncoding != dwarf::DW_EH_PE_absptr) - EmitEncodingByte(FDEEncoding, "FDE"); + Asm->EmitEncodingByte(FDEEncoding, "FDE"); } // Indicate locations of general callee saved registers in frame. std::vector<MachineMove> Moves; RI->getInitialFrameState(Moves); - EmitFrameMoves(0, Moves, true); + Asm->EmitFrameMoves(Moves, 0, true); // On Darwin the linker honors the alignment of eh_frame, which means it must // be 8-byte on 64-bit targets to match what gcc does. Otherwise you get // holes which confuse readers of eh_frame. - Asm->EmitAlignment(TD->getPointerSize() == 4 ? 2 : 3, 0, 0, false); - Asm->OutStreamer.EmitLabel(getDWLabel("eh_frame_common_end", Index)); + Asm->EmitAlignment(Asm->getTargetData().getPointerSize() == 4 ? 2 : 3, + 0, 0, false); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_frame_common_end", Index)); } /// EmitFDE - Emit the Frame Description Entry (FDE) for the function. @@ -178,13 +183,13 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym,MCSA_Global); // If corresponding function is weak definition, this should be too. - if (TheFunc->isWeakForLinker() && MAI->getWeakDefDirective()) + if (TheFunc->isWeakForLinker() && Asm->MAI->getWeakDefDirective()) Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym, MCSA_WeakDefinition); // If corresponding function is hidden, this should be too. if (TheFunc->hasHiddenVisibility()) - if (MCSymbolAttr HiddenAttr = MAI->getHiddenVisibilityAttr()) + if (MCSymbolAttr HiddenAttr = Asm->MAI->getHiddenVisibilityAttr()) Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym, HiddenAttr); @@ -194,14 +199,14 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { // info is to be available for non-EH uses. if (!EHFrameInfo.hasCalls && !UnwindTablesMandatory && (!TheFunc->isWeakForLinker() || - !MAI->getWeakDefDirective() || + !Asm->MAI->getWeakDefDirective() || TLOF.getSupportsWeakOmittedEHFrame())) { Asm->OutStreamer.EmitAssignment(EHFrameInfo.FunctionEHSym, MCConstantExpr::Create(0, Asm->OutContext)); // This name has no connection to the function, so it might get // dead-stripped when the function is not, erroneously. Prohibit // dead-stripping unconditionally. - if (MAI->hasNoDeadStrip()) + if (Asm->MAI->hasNoDeadStrip()) Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym, MCSA_NoDeadStrip); } else { @@ -209,52 +214,58 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { // EH frame header. Asm->OutStreamer.AddComment("Length of Frame Information Entry"); - EmitDifference(getDWLabel("eh_frame_end", EHFrameInfo.Number), - getDWLabel("eh_frame_begin", EHFrameInfo.Number), - true); + Asm->EmitLabelDifference( + Asm->GetTempSymbol("eh_frame_end", EHFrameInfo.Number), + Asm->GetTempSymbol("eh_frame_begin", EHFrameInfo.Number), 4); - Asm->OutStreamer.EmitLabel(getDWLabel("eh_frame_begin",EHFrameInfo.Number)); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_frame_begin", + EHFrameInfo.Number)); Asm->OutStreamer.AddComment("FDE CIE offset"); - EmitSectionOffset(getDWLabel("eh_frame_begin", EHFrameInfo.Number), - getDWLabel("eh_frame_common", - EHFrameInfo.PersonalityIndex), - true, true); + Asm->EmitLabelDifference( + Asm->GetTempSymbol("eh_frame_begin", EHFrameInfo.Number), + Asm->GetTempSymbol("eh_frame_common", + EHFrameInfo.PersonalityIndex), 4); - MCSymbol *EHFuncBeginSym = getDWLabel("eh_func_begin", EHFrameInfo.Number); + MCSymbol *EHFuncBeginSym = + Asm->GetTempSymbol("eh_func_begin", EHFrameInfo.Number); Asm->OutStreamer.AddComment("FDE initial location"); - EmitReference(EHFuncBeginSym, FDEEncoding); + Asm->EmitReference(EHFuncBeginSym, FDEEncoding); Asm->OutStreamer.AddComment("FDE address range"); - EmitDifference(getDWLabel("eh_func_end", EHFrameInfo.Number),EHFuncBeginSym, - SizeOfEncodedValue(FDEEncoding) == 4); + Asm->EmitLabelDifference(Asm->GetTempSymbol("eh_func_end", + EHFrameInfo.Number), + EHFuncBeginSym, + Asm->GetSizeOfEncodedValue(FDEEncoding)); // If there is a personality and landing pads then point to the language // specific data area in the exception table. if (MMI->getPersonalities()[0] != NULL) { - unsigned Size = SizeOfEncodedValue(LSDAEncoding); + unsigned Size = Asm->GetSizeOfEncodedValue(LSDAEncoding); - EmitULEB128(Size, "Augmentation size"); + Asm->EmitULEB128(Size, "Augmentation size"); Asm->OutStreamer.AddComment("Language Specific Data Area"); if (EHFrameInfo.hasLandingPads) - EmitReference(getDWLabel("exception", EHFrameInfo.Number),LSDAEncoding); + Asm->EmitReference(Asm->GetTempSymbol("exception", EHFrameInfo.Number), + LSDAEncoding); else Asm->OutStreamer.EmitIntValue(0, Size/*size*/, 0/*addrspace*/); } else { - EmitULEB128(0, "Augmentation size"); + Asm->EmitULEB128(0, "Augmentation size"); } // Indicate locations of function specific callee saved registers in frame. - EmitFrameMoves(EHFuncBeginSym, EHFrameInfo.Moves, true); + Asm->EmitFrameMoves(EHFrameInfo.Moves, EHFuncBeginSym, true); // On Darwin the linker honors the alignment of eh_frame, which means it // must be 8-byte on 64-bit targets to match what gcc does. Otherwise you // get holes which confuse readers of eh_frame. - Asm->EmitAlignment(TD->getPointerSize() == sizeof(int32_t) ? 2 : 3, + Asm->EmitAlignment(Asm->getTargetData().getPointerSize() == 4 ? 2 : 3, 0, 0, false); - Asm->OutStreamer.EmitLabel(getDWLabel("eh_frame_end", EHFrameInfo.Number)); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_frame_end", + EHFrameInfo.Number)); // If the function is marked used, this table should be also. We cannot // make the mark unconditional in this case, since retaining the table also @@ -262,7 +273,7 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { // on unused functions (calling undefined externals) being dead-stripped to // link correctly. Yes, there really is. if (MMI->isUsedFunction(EHFrameInfo.function)) - if (MAI->hasNoDeadStrip()) + if (Asm->MAI->hasNoDeadStrip()) Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym, MCSA_NoDeadStrip); } @@ -348,7 +359,7 @@ ComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads, I = LandingPads.begin(), E = LandingPads.end(); I != E; ++I) { const LandingPadInfo *LPI = *I; const std::vector<int> &TypeIds = LPI->TypeIds; - const unsigned NumShared = PrevLPI ? SharedTypeIds(LPI, PrevLPI) : 0; + unsigned NumShared = PrevLPI ? SharedTypeIds(LPI, PrevLPI) : 0; unsigned SizeSiteActions = 0; if (NumShared < TypeIds.size()) { @@ -356,7 +367,7 @@ ComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads, unsigned PrevAction = (unsigned)-1; if (NumShared) { - const unsigned SizePrevIds = PrevLPI->TypeIds.size(); + unsigned SizePrevIds = PrevLPI->TypeIds.size(); assert(Actions.size()); PrevAction = Actions.size() - 1; SizeAction = @@ -465,7 +476,7 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, bool PreviousIsInvoke = false; // Visit all instructions in order of address. - for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); + for (MachineFunction::const_iterator I = Asm->MF->begin(), E = Asm->MF->end(); I != E; ++I) { for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end(); MI != E; ++MI) { @@ -496,7 +507,7 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, // create a call-site entry with no landing pad for the region between the // try-ranges. if (SawPotentiallyThrowing && - MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) { + Asm->MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) { CallSiteEntry Site = { LastLabel, BeginLabel, 0, 0 }; CallSites.push_back(Site); PreviousIsInvoke = false; @@ -519,7 +530,7 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, // Try to merge with the previous call-site. SJLJ doesn't do this if (PreviousIsInvoke && - MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) { + Asm->MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) { CallSiteEntry &Prev = CallSites.back(); if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) { // Extend the range of the previous entry. @@ -529,7 +540,7 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, } // Otherwise, create a new call-site. - if (MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) + if (Asm->MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) CallSites.push_back(Site); else { // SjLj EH must maintain the call sites in the order assigned @@ -548,7 +559,7 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, // function may throw, create a call-site entry with no landing pad for the // region following the try-range. if (SawPotentiallyThrowing && - MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) { + Asm->MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) { CallSiteEntry Site = { LastLabel, 0, 0, 0 }; CallSites.push_back(Site); } @@ -616,18 +627,19 @@ void DwarfException::EmitExceptionTable() { // Final tallies. // Call sites. - const unsigned SiteStartSize = SizeOfEncodedValue(dwarf::DW_EH_PE_udata4); - const unsigned SiteLengthSize = SizeOfEncodedValue(dwarf::DW_EH_PE_udata4); - const unsigned LandingPadSize = SizeOfEncodedValue(dwarf::DW_EH_PE_udata4); - bool IsSJLJ = MAI->getExceptionHandlingType() == ExceptionHandling::SjLj; + bool IsSJLJ = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::SjLj; bool HaveTTData = IsSJLJ ? (!TypeInfos.empty() || !FilterIds.empty()) : true; + unsigned CallSiteTableLength; - if (IsSJLJ) CallSiteTableLength = 0; - else - CallSiteTableLength = CallSites.size() * - (SiteStartSize + SiteLengthSize + LandingPadSize); + else { + unsigned SiteStartSize = 4; // dwarf::DW_EH_PE_udata4 + unsigned SiteLengthSize = 4; // dwarf::DW_EH_PE_udata4 + unsigned LandingPadSize = 4; // dwarf::DW_EH_PE_udata4 + CallSiteTableLength = + CallSites.size() * (SiteStartSize + SiteLengthSize + LandingPadSize); + } for (unsigned i = 0, e = CallSites.size(); i < e; ++i) { CallSiteTableLength += MCAsmInfo::getULEB128Size(CallSites[i].Action); @@ -644,7 +656,8 @@ void DwarfException::EmitExceptionTable() { // For SjLj exceptions, if there is no TypeInfo, then we just explicitly say // that we're omitting that bit. TTypeEncoding = dwarf::DW_EH_PE_omit; - TypeFormatSize = SizeOfEncodedValue(dwarf::DW_EH_PE_absptr); + // dwarf::DW_EH_PE_absptr + TypeFormatSize = Asm->getTargetData().getPointerSize(); } else { // Okay, we have actual filters or typeinfos to emit. As such, we need to // pick a type encoding for them. We're about to emit a list of pointers to @@ -674,7 +687,7 @@ void DwarfException::EmitExceptionTable() { // in target-independent code. // TTypeEncoding = Asm->getObjFileLowering().getTTypeEncoding(); - TypeFormatSize = SizeOfEncodedValue(TTypeEncoding); + TypeFormatSize = Asm->GetSizeOfEncodedValue(TTypeEncoding); } // Begin the exception table. @@ -684,16 +697,18 @@ void DwarfException::EmitExceptionTable() { // Emit the LSDA. MCSymbol *GCCETSym = Asm->OutContext.GetOrCreateSymbol(Twine("GCC_except_table")+ - Twine(SubprogramCount)); + Twine(Asm->getFunctionNumber())); Asm->OutStreamer.EmitLabel(GCCETSym); - Asm->OutStreamer.EmitLabel(getDWLabel("exception", SubprogramCount)); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("exception", + Asm->getFunctionNumber())); if (IsSJLJ) - Asm->OutStreamer.EmitLabel(getDWLabel("_LSDA_", Asm->getFunctionNumber())); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("_LSDA_", + Asm->getFunctionNumber())); // Emit the LSDA header. - EmitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart"); - EmitEncodingByte(TTypeEncoding, "@TType"); + Asm->EmitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart"); + Asm->EmitEncodingByte(TTypeEncoding, "@TType"); // The type infos need to be aligned. GCC does this by inserting padding just // before the type infos. However, this changes the size of the exception @@ -730,16 +745,16 @@ void DwarfException::EmitExceptionTable() { if (HaveTTData) { // Account for any extra padding that will be added to the call site table // length. - EmitULEB128(TTypeBaseOffset, "@TType base offset", SizeAlign); + Asm->EmitULEB128(TTypeBaseOffset, "@TType base offset", SizeAlign); SizeAlign = 0; } // SjLj Exception handling if (IsSJLJ) { - EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site"); + Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site"); // Add extra padding if it wasn't added to the TType base offset. - EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign); + Asm->EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign); // Emit the landing pad site information. unsigned idx = 0; @@ -749,16 +764,16 @@ void DwarfException::EmitExceptionTable() { // Offset of the landing pad, counted in 16-byte bundles relative to the // @LPStart address. - EmitULEB128(idx, "Landing pad"); + Asm->EmitULEB128(idx, "Landing pad"); // Offset of the first associated action record, relative to the start of // the action table. This value is biased by 1 (1 indicates the start of // the action table), and 0 indicates that there are no actions. - EmitULEB128(S.Action, "Action"); + Asm->EmitULEB128(S.Action, "Action"); } } else { // DWARF Exception handling - assert(MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf); + assert(Asm->MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf); // The call-site table is a list of all call sites that may throw an // exception (including C++ 'throw' statements) in the procedure @@ -779,32 +794,33 @@ void DwarfException::EmitExceptionTable() { // supposed to throw. // Emit the landing pad call site table. - EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site"); + Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site"); // Add extra padding if it wasn't added to the TType base offset. - EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign); + Asm->EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign); for (SmallVectorImpl<CallSiteEntry>::const_iterator I = CallSites.begin(), E = CallSites.end(); I != E; ++I) { const CallSiteEntry &S = *I; - MCSymbol *EHFuncBeginSym = getDWLabel("eh_func_begin", SubprogramCount); + MCSymbol *EHFuncBeginSym = + Asm->GetTempSymbol("eh_func_begin", Asm->getFunctionNumber()); MCSymbol *BeginLabel = S.BeginLabel; if (BeginLabel == 0) BeginLabel = EHFuncBeginSym; MCSymbol *EndLabel = S.EndLabel; if (EndLabel == 0) - EndLabel = getDWLabel("eh_func_end", SubprogramCount); + EndLabel = Asm->GetTempSymbol("eh_func_end", Asm->getFunctionNumber()); // Offset of the call site relative to the previous call site, counted in // number of 16-byte bundles. The first call site is counted relative to // the start of the procedure fragment. Asm->OutStreamer.AddComment("Region start"); - EmitSectionOffset(BeginLabel, EHFuncBeginSym, true, true); + Asm->EmitLabelDifference(BeginLabel, EHFuncBeginSym, 4); Asm->OutStreamer.AddComment("Region length"); - EmitDifference(EndLabel, BeginLabel, true); + Asm->EmitLabelDifference(EndLabel, BeginLabel, 4); // Offset of the landing pad, counted in 16-byte bundles relative to the @@ -813,12 +829,12 @@ void DwarfException::EmitExceptionTable() { if (!S.PadLabel) Asm->OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/); else - EmitSectionOffset(S.PadLabel, EHFuncBeginSym, true, true); + Asm->EmitLabelDifference(S.PadLabel, EHFuncBeginSym, 4); // Offset of the first associated action record, relative to the start of // the action table. This value is biased by 1 (1 indicates the start of // the action table), and 0 indicates that there are no actions. - EmitULEB128(S.Action, "Action"); + Asm->EmitULEB128(S.Action, "Action"); } } @@ -838,13 +854,13 @@ void DwarfException::EmitExceptionTable() { // // Used by the runtime to match the type of the thrown exception to the // type of the catch clauses or the types in the exception specification. - EmitSLEB128(Action.ValueForTypeID, " TypeInfo index"); + Asm->EmitSLEB128(Action.ValueForTypeID, " TypeInfo index"); // Action Record // // Self-relative signed displacement in bytes of the next action record, // or 0 if there is no next action record. - EmitSLEB128(Action.NextAction, " Next action"); + Asm->EmitSLEB128(Action.NextAction, " Next action"); } // Emit the Catch TypeInfos. @@ -858,9 +874,10 @@ void DwarfException::EmitExceptionTable() { Asm->OutStreamer.AddComment("TypeInfo"); if (GV) - EmitReference(GV, TTypeEncoding); + Asm->EmitReference(GV, TTypeEncoding); else - Asm->OutStreamer.EmitIntValue(0, SizeOfEncodedValue(TTypeEncoding), 0); + Asm->OutStreamer.EmitIntValue(0,Asm->GetSizeOfEncodedValue(TTypeEncoding), + 0); } // Emit the Exception Specifications. @@ -871,7 +888,7 @@ void DwarfException::EmitExceptionTable() { for (std::vector<unsigned>::const_iterator I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) { unsigned TypeID = *I; - EmitULEB128(TypeID, TypeID != 0 ? "Exception specification" : 0); + Asm->EmitULEB128(TypeID, TypeID != 0 ? "Exception specification" : 0); } Asm->EmitAlignment(2, 0, 0, false); @@ -880,7 +897,7 @@ void DwarfException::EmitExceptionTable() { /// EndModule - Emit all exception information that should come after the /// content. void DwarfException::EndModule() { - if (MAI->getExceptionHandlingType() != ExceptionHandling::Dwarf) + if (Asm->MAI->getExceptionHandlingType() != ExceptionHandling::Dwarf) return; if (!shouldEmitMovesModule && !shouldEmitTableModule) @@ -901,21 +918,20 @@ void DwarfException::EndModule() { /// BeginFunction - Gather pre-function exception information. Assumes it's /// being emitted immediately after the function entry point. void DwarfException::BeginFunction(const MachineFunction *MF) { - if (!MMI || !MAI->doesSupportExceptionHandling()) return; - TimeRegion Timer(ExceptionTimer); - this->MF = MF; shouldEmitTable = shouldEmitMoves = false; // If any landing pads survive, we need an EH table. shouldEmitTable = !MMI->getLandingPads().empty(); // See if we need frame move info. - shouldEmitMoves = !MF->getFunction()->doesNotThrow() || UnwindTablesMandatory; + shouldEmitMoves = + !Asm->MF->getFunction()->doesNotThrow() || UnwindTablesMandatory; if (shouldEmitMoves || shouldEmitTable) // Assumes in correct section after the entry point. - Asm->OutStreamer.EmitLabel(getDWLabel("eh_func_begin", ++SubprogramCount)); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_begin", + Asm->getFunctionNumber())); shouldEmitTableModule |= shouldEmitTable; shouldEmitMovesModule |= shouldEmitMoves; @@ -927,7 +943,8 @@ void DwarfException::EndFunction() { if (!shouldEmitMoves && !shouldEmitTable) return; TimeRegion Timer(ExceptionTimer); - Asm->OutStreamer.EmitLabel(getDWLabel("eh_func_end", SubprogramCount)); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_end", + Asm->getFunctionNumber())); // Record if this personality index uses a landing pad. bool HasLandingPad = !MMI->getLandingPads().empty(); @@ -941,14 +958,15 @@ void DwarfException::EndFunction() { const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); MCSymbol *FunctionEHSym = - Asm->GetSymbolWithGlobalValueBase(MF->getFunction(), ".eh", + Asm->GetSymbolWithGlobalValueBase(Asm->MF->getFunction(), ".eh", TLOF.isFunctionEHFrameSymbolPrivate()); // Save EH frame information - EHFrames.push_back(FunctionEHFrameInfo(FunctionEHSym, SubprogramCount, + EHFrames.push_back(FunctionEHFrameInfo(FunctionEHSym, + Asm->getFunctionNumber(), MMI->getPersonalityIndex(), - MF->getFrameInfo()->hasCalls(), + Asm->MF->getFrameInfo()->hasCalls(), !MMI->getLandingPads().empty(), MMI->getFrameMoves(), - MF->getFunction())); + Asm->MF->getFunction())); } diff --git a/lib/CodeGen/AsmPrinter/DwarfException.h b/lib/CodeGen/AsmPrinter/DwarfException.h index 4bc4a458c04e..f35c0b616c1f 100644 --- a/lib/CodeGen/AsmPrinter/DwarfException.h +++ b/lib/CodeGen/AsmPrinter/DwarfException.h @@ -14,25 +14,34 @@ #ifndef LLVM_CODEGEN_ASMPRINTER_DWARFEXCEPTION_H #define LLVM_CODEGEN_ASMPRINTER_DWARFEXCEPTION_H -#include "DIE.h" -#include "DwarfPrinter.h" -#include "llvm/CodeGen/AsmPrinter.h" #include "llvm/ADT/DenseMap.h" -#include <string> +#include <vector> namespace llvm { +template <typename T> class SmallVectorImpl; struct LandingPadInfo; class MachineModuleInfo; +class MachineMove; +class MachineInstr; +class MachineFunction; class MCAsmInfo; class MCExpr; +class MCSymbol; class Timer; -class raw_ostream; +class Function; +class AsmPrinter; //===----------------------------------------------------------------------===// /// DwarfException - Emits Dwarf exception handling directives. /// -class DwarfException : public DwarfPrinter { +class DwarfException { + /// Asm - Target of Dwarf emission. + AsmPrinter *Asm; + + /// MMI - Collected machine module information. + MachineModuleInfo *MMI; + struct FunctionEHFrameInfo { MCSymbol *FunctionEHSym; // L_foo.eh unsigned Number; @@ -166,15 +175,8 @@ public: //===--------------------------------------------------------------------===// // Main entry points. // - DwarfException(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T); - virtual ~DwarfException(); - - /// BeginModule - Emit all exception information that should come prior to the - /// content. - void BeginModule(Module *m, MachineModuleInfo *mmi) { - this->M = m; - this->MMI = mmi; - } + DwarfException(AsmPrinter *A); + ~DwarfException(); /// EndModule - Emit all exception information that should come after the /// content. diff --git a/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp b/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp deleted file mode 100644 index 17eb2e872742..000000000000 --- a/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp +++ /dev/null @@ -1,308 +0,0 @@ -//===--- lib/CodeGen/DwarfPrinter.cpp - Dwarf Printer ---------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Emit general DWARF directives. -// -//===----------------------------------------------------------------------===// - -#include "DwarfPrinter.h" -#include "llvm/Module.h" -#include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetFrameInfo.h" -#include "llvm/Target/TargetLoweringObjectFile.h" -#include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/Support/Dwarf.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/ADT/SmallString.h" -using namespace llvm; - -DwarfPrinter::DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T) -: O(OS), Asm(A), MAI(T), TD(Asm->TM.getTargetData()), - RI(Asm->TM.getRegisterInfo()), M(NULL), MF(NULL), MMI(NULL), - SubprogramCount(0) {} - - -/// getDWLabel - Return the MCSymbol corresponding to the assembler temporary -/// label with the specified stem and unique ID. -MCSymbol *DwarfPrinter::getDWLabel(const char *Name, unsigned ID) const { - // FIXME: REMOVE this. However, there is stuff in EH that passes counters in - // here that can be zero. - - //assert(ID && "Should use getTempLabel if no ID"); - if (ID == 0) return getTempLabel(Name); - return Asm->OutContext.GetOrCreateSymbol - (Twine(MAI->getPrivateGlobalPrefix()) + Twine(Name) + Twine(ID)); -} - -/// getTempLabel - Return the MCSymbol corresponding to the assembler temporary -/// label with the specified name. -MCSymbol *DwarfPrinter::getTempLabel(const char *Name) const { - return Asm->OutContext.GetOrCreateSymbol - (Twine(MAI->getPrivateGlobalPrefix()) + Name); -} - - -/// SizeOfEncodedValue - Return the size of the encoding in bytes. -unsigned DwarfPrinter::SizeOfEncodedValue(unsigned Encoding) const { - if (Encoding == dwarf::DW_EH_PE_omit) - return 0; - - switch (Encoding & 0x07) { - case dwarf::DW_EH_PE_absptr: - return TD->getPointerSize(); - case dwarf::DW_EH_PE_udata2: - return 2; - case dwarf::DW_EH_PE_udata4: - return 4; - case dwarf::DW_EH_PE_udata8: - return 8; - } - - assert(0 && "Invalid encoded value."); - return 0; -} - -static const char *DecodeDWARFEncoding(unsigned Encoding) { - switch (Encoding) { - case dwarf::DW_EH_PE_absptr: return "absptr"; - case dwarf::DW_EH_PE_omit: return "omit"; - case dwarf::DW_EH_PE_pcrel: return "pcrel"; - case dwarf::DW_EH_PE_udata4: return "udata4"; - case dwarf::DW_EH_PE_udata8: return "udata8"; - case dwarf::DW_EH_PE_sdata4: return "sdata4"; - case dwarf::DW_EH_PE_sdata8: return "sdata8"; - case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4: return "pcrel udata4"; - case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4: return "pcrel sdata4"; - case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8: return "pcrel udata8"; - case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8: return "pcrel sdata8"; - case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata4: - return "indirect pcrel udata4"; - case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata4: - return "indirect pcrel sdata4"; - case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata8: - return "indirect pcrel udata8"; - case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata8: - return "indirect pcrel sdata8"; - } - - return "<unknown encoding>"; -} - -/// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an -/// encoding. If verbose assembly output is enabled, we output comments -/// describing the encoding. Desc is an optional string saying what the -/// encoding is specifying (e.g. "LSDA"). -void DwarfPrinter::EmitEncodingByte(unsigned Val, const char *Desc) { - if (Asm->VerboseAsm) { - if (Desc != 0) - Asm->OutStreamer.AddComment(Twine(Desc)+" Encoding = " + - Twine(DecodeDWARFEncoding(Val))); - else - Asm->OutStreamer.AddComment(Twine("Encoding = ") + - DecodeDWARFEncoding(Val)); - } - - Asm->OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/); -} - -/// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value. -void DwarfPrinter::EmitCFAByte(unsigned Val) { - if (Asm->VerboseAsm) { - if (Val >= dwarf::DW_CFA_offset && Val < dwarf::DW_CFA_offset+64) - Asm->OutStreamer.AddComment("DW_CFA_offset + Reg (" + - Twine(Val-dwarf::DW_CFA_offset) + ")"); - else - Asm->OutStreamer.AddComment(dwarf::CallFrameString(Val)); - } - Asm->OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/); -} - -/// EmitSLEB128 - emit the specified signed leb128 value. -void DwarfPrinter::EmitSLEB128(int Value, const char *Desc) const { - if (Asm->VerboseAsm && Desc) - Asm->OutStreamer.AddComment(Desc); - - if (MAI->hasLEB128()) { - // FIXME: MCize. - O << "\t.sleb128\t" << Value; - Asm->OutStreamer.AddBlankLine(); - return; - } - - // If we don't have .sleb128, emit as .bytes. - int Sign = Value >> (8 * sizeof(Value) - 1); - bool IsMore; - - do { - unsigned char Byte = static_cast<unsigned char>(Value & 0x7f); - Value >>= 7; - IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; - if (IsMore) Byte |= 0x80; - Asm->OutStreamer.EmitIntValue(Byte, 1, /*addrspace*/0); - } while (IsMore); -} - -/// EmitULEB128 - emit the specified signed leb128 value. -void DwarfPrinter::EmitULEB128(unsigned Value, const char *Desc, - unsigned PadTo) const { - if (Asm->VerboseAsm && Desc) - Asm->OutStreamer.AddComment(Desc); - - if (MAI->hasLEB128() && PadTo == 0) { - // FIXME: MCize. - O << "\t.uleb128\t" << Value; - Asm->OutStreamer.AddBlankLine(); - return; - } - - // If we don't have .uleb128 or we want to emit padding, emit as .bytes. - do { - unsigned char Byte = static_cast<unsigned char>(Value & 0x7f); - Value >>= 7; - if (Value || PadTo != 0) Byte |= 0x80; - Asm->OutStreamer.EmitIntValue(Byte, 1, /*addrspace*/0); - } while (Value); - - if (PadTo) { - if (PadTo > 1) - Asm->OutStreamer.EmitFill(PadTo - 1, 0x80/*fillval*/, 0/*addrspace*/); - Asm->OutStreamer.EmitFill(1, 0/*fillval*/, 0/*addrspace*/); - } -} - - -void DwarfPrinter::EmitReference(const MCSymbol *Sym, unsigned Encoding) const { - const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); - - const MCExpr *Exp = TLOF.getExprForDwarfReference(Sym, Asm->Mang, - Asm->MMI, Encoding, - Asm->OutStreamer); - Asm->OutStreamer.EmitValue(Exp, SizeOfEncodedValue(Encoding), /*addrspace*/0); -} - -void DwarfPrinter::EmitReference(const GlobalValue *GV, unsigned Encoding)const{ - const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); - - const MCExpr *Exp = - TLOF.getExprForDwarfGlobalReference(GV, Asm->Mang, Asm->MMI, Encoding, - Asm->OutStreamer); - Asm->OutStreamer.EmitValue(Exp, SizeOfEncodedValue(Encoding), /*addrspace*/0); -} - -/// EmitDifference - Emit the difference between two labels. If this assembler -/// supports .set, we emit a .set of a temporary and then use it in the .word. -void DwarfPrinter::EmitDifference(const MCSymbol *TagHi, const MCSymbol *TagLo, - bool IsSmall) { - unsigned Size = IsSmall ? 4 : TD->getPointerSize(); - Asm->EmitLabelDifference(TagHi, TagLo, Size); -} - -void DwarfPrinter::EmitSectionOffset(const MCSymbol *Label, - const MCSymbol *Section, - bool IsSmall, bool isEH) { - bool isAbsolute; - if (isEH) - isAbsolute = MAI->isAbsoluteEHSectionOffsets(); - else - isAbsolute = MAI->isAbsoluteDebugSectionOffsets(); - - if (!isAbsolute) - return EmitDifference(Label, Section, IsSmall); - - // On COFF targets, we have to emit the weird .secrel32 directive. - if (const char *SecOffDir = MAI->getDwarfSectionOffsetDirective()) { - // FIXME: MCize. - Asm->O << SecOffDir << Label->getName(); - Asm->OutStreamer.AddBlankLine(); - } else { - unsigned Size = IsSmall ? 4 : TD->getPointerSize(); - Asm->OutStreamer.EmitSymbolValue(Label, Size, 0/*AddrSpace*/); - } -} - -/// EmitFrameMoves - Emit frame instructions to describe the layout of the -/// frame. -void DwarfPrinter::EmitFrameMoves(MCSymbol *BaseLabel, - const std::vector<MachineMove> &Moves, - bool isEH) { - int stackGrowth = TD->getPointerSize(); - if (Asm->TM.getFrameInfo()->getStackGrowthDirection() != - TargetFrameInfo::StackGrowsUp) - stackGrowth *= -1; - - for (unsigned i = 0, N = Moves.size(); i < N; ++i) { - const MachineMove &Move = Moves[i]; - MCSymbol *Label = Move.getLabel(); - // Throw out move if the label is invalid. - if (Label && !Label->isDefined()) continue; // Not emitted, in dead code. - - const MachineLocation &Dst = Move.getDestination(); - const MachineLocation &Src = Move.getSource(); - - // Advance row if new location. - if (BaseLabel && Label) { - MCSymbol *ThisSym = Label; - if (ThisSym != BaseLabel) { - EmitCFAByte(dwarf::DW_CFA_advance_loc4); - EmitDifference(ThisSym, BaseLabel, true); - BaseLabel = ThisSym; - } - } - - // If advancing cfa. - if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) { - if (!Src.isReg()) { - if (Src.getReg() == MachineLocation::VirtualFP) { - EmitCFAByte(dwarf::DW_CFA_def_cfa_offset); - } else { - EmitCFAByte(dwarf::DW_CFA_def_cfa); - EmitULEB128(RI->getDwarfRegNum(Src.getReg(), isEH), "Register"); - } - - int Offset = -Src.getOffset(); - EmitULEB128(Offset, "Offset"); - } else { - llvm_unreachable("Machine move not supported yet."); - } - } else if (Src.isReg() && - Src.getReg() == MachineLocation::VirtualFP) { - if (Dst.isReg()) { - EmitCFAByte(dwarf::DW_CFA_def_cfa_register); - EmitULEB128(RI->getDwarfRegNum(Dst.getReg(), isEH), "Register"); - } else { - llvm_unreachable("Machine move not supported yet."); - } - } else { - unsigned Reg = RI->getDwarfRegNum(Src.getReg(), isEH); - int Offset = Dst.getOffset() / stackGrowth; - - if (Offset < 0) { - EmitCFAByte(dwarf::DW_CFA_offset_extended_sf); - EmitULEB128(Reg, "Reg"); - EmitSLEB128(Offset, "Offset"); - } else if (Reg < 64) { - EmitCFAByte(dwarf::DW_CFA_offset + Reg); - EmitULEB128(Offset, "Offset"); - } else { - EmitCFAByte(dwarf::DW_CFA_offset_extended); - EmitULEB128(Reg, "Reg"); - EmitULEB128(Offset, "Offset"); - } - } - } -} diff --git a/lib/CodeGen/AsmPrinter/DwarfPrinter.h b/lib/CodeGen/AsmPrinter/DwarfPrinter.h deleted file mode 100644 index 0b94645a8c7b..000000000000 --- a/lib/CodeGen/AsmPrinter/DwarfPrinter.h +++ /dev/null @@ -1,131 +0,0 @@ -//===--- lib/CodeGen/DwarfPrinter.h - Dwarf Printer -------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Emit general DWARF directives. -// -//===----------------------------------------------------------------------===// - -#ifndef CODEGEN_ASMPRINTER_DWARFPRINTER_H__ -#define CODEGEN_ASMPRINTER_DWARFPRINTER_H__ - -#include "llvm/CodeGen/MachineLocation.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/FormattedStream.h" -#include <vector> - -namespace llvm { -class AsmPrinter; -class MachineFunction; -class MachineModuleInfo; -class Module; -class MCAsmInfo; -class TargetData; -class TargetRegisterInfo; -class GlobalValue; -class MCSymbol; -class Twine; - -class DwarfPrinter { -protected: - ~DwarfPrinter() {} - - //===-------------------------------------------------------------==---===// - // Core attributes used by the DWARF printer. - // - - /// O - Stream to .s file. - raw_ostream &O; - - /// Asm - Target of Dwarf emission. - AsmPrinter *Asm; - - /// MAI - Target asm information. - const MCAsmInfo *MAI; - - /// TD - Target data. - const TargetData *TD; - - /// RI - Register Information. - const TargetRegisterInfo *RI; - - /// M - Current module. - Module *M; - - /// MF - Current machine function. - const MachineFunction *MF; - - /// MMI - Collected machine module information. - MachineModuleInfo *MMI; - - /// SubprogramCount - The running count of functions being compiled. - unsigned SubprogramCount; - - DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T); -public: - - //===------------------------------------------------------------------===// - // Accessors. - // - const AsmPrinter *getAsm() const { return Asm; } - MachineModuleInfo *getMMI() const { return MMI; } - const MCAsmInfo *getMCAsmInfo() const { return MAI; } - const TargetData *getTargetData() const { return TD; } - - /// getDWLabel - Return the MCSymbol corresponding to the assembler temporary - /// label with the specified stem and unique ID. - MCSymbol *getDWLabel(const char *Name, unsigned ID) const; - - /// getTempLabel - Return an assembler temporary label with the specified - /// name. - MCSymbol *getTempLabel(const char *Name) const; - - /// SizeOfEncodedValue - Return the size of the encoding in bytes. - unsigned SizeOfEncodedValue(unsigned Encoding) const; - - /// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an - /// encoding. If verbose assembly output is enabled, we output comments - /// describing the encoding. Desc is a string saying what the encoding is - /// specifying (e.g. "LSDA"). - void EmitEncodingByte(unsigned Val, const char *Desc); - - /// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value. - void EmitCFAByte(unsigned Val); - - - /// EmitSLEB128 - emit the specified signed leb128 value. - void EmitSLEB128(int Value, const char *Desc) const; - - /// EmitULEB128 - emit the specified unsigned leb128 value. - void EmitULEB128(unsigned Value, const char *Desc = 0, - unsigned PadTo = 0) const; - - - /// EmitReference - Emit a reference to a label. - /// - void EmitReference(const MCSymbol *Sym, unsigned Encoding) const; - void EmitReference(const GlobalValue *GV, unsigned Encoding) const; - - /// EmitDifference - Emit the difference between two labels. - void EmitDifference(const MCSymbol *LabelHi, const MCSymbol *LabelLo, - bool IsSmall = false); - - /// EmitSectionOffset - Emit Label-Section or use a special purpose directive - /// to emit a section offset if the target has one. - void EmitSectionOffset(const MCSymbol *Label, const MCSymbol *Section, - bool IsSmall = false, bool isEH = false); - - /// EmitFrameMoves - Emit frame instructions to describe the layout of the - /// frame. - void EmitFrameMoves(MCSymbol *BaseLabel, - const std::vector<MachineMove> &Moves, bool isEH); -}; - -} // end llvm namespace - -#endif diff --git a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp deleted file mode 100644 index a2d7ab1224ee..000000000000 --- a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp +++ /dev/null @@ -1,87 +0,0 @@ -//===-- llvm/CodeGen/DwarfWriter.cpp - Dwarf 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 info into asm files. -// -//===----------------------------------------------------------------------===// - -#include "llvm/CodeGen/DwarfWriter.h" -#include "DwarfDebug.h" -#include "DwarfException.h" -#include "llvm/CodeGen/MachineModuleInfo.h" - -using namespace llvm; - -static RegisterPass<DwarfWriter> -X("dwarfwriter", "DWARF Information Writer"); -char DwarfWriter::ID = 0; - -//===----------------------------------------------------------------------===// -/// DwarfWriter Implementation -/// - -DwarfWriter::DwarfWriter() - : ImmutablePass(&ID), DD(0), DE(0) {} - -DwarfWriter::~DwarfWriter() { - delete DE; - delete DD; -} - -/// BeginModule - Emit all Dwarf sections that should come prior to the -/// content. -void DwarfWriter::BeginModule(Module *M, - MachineModuleInfo *MMI, - raw_ostream &OS, AsmPrinter *A, - const MCAsmInfo *T) { - DE = new DwarfException(OS, A, T); - DD = new DwarfDebug(OS, A, T); - DE->BeginModule(M, MMI); - DD->beginModule(M, MMI); -} - -/// EndModule - Emit all Dwarf sections that should come after the content. -/// -void DwarfWriter::EndModule() { - DE->EndModule(); - DD->endModule(); - delete DD; DD = 0; - delete DE; DE = 0; -} - -/// BeginFunction - Gather pre-function debug information. Assumes being -/// emitted immediately after the function entry point. -void DwarfWriter::BeginFunction(const MachineFunction *MF) { - DE->BeginFunction(MF); - DD->beginFunction(MF); -} - -/// EndFunction - Gather and emit post-function debug information. -/// -void DwarfWriter::EndFunction(const MachineFunction *MF) { - DD->endFunction(MF); - DE->EndFunction(); - - if (MachineModuleInfo *MMI = DD->getMMI() ? DD->getMMI() : DE->getMMI()) - // Clear function debug information. - MMI->EndFunction(); -} - -/// ShouldEmitDwarfDebug - Returns true if Dwarf debugging declarations should -/// be emitted. -bool DwarfWriter::ShouldEmitDwarfDebug() const { - return DD && DD->ShouldEmitDwarfDebug(); -} - -void DwarfWriter::BeginScope(const MachineInstr *MI) { - DD->beginScope(MI); -} -void DwarfWriter::EndScope(const MachineInstr *MI) { - DD->endScope(MI); -} diff --git a/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp b/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp index fa840e133a5e..1db178f020ec 100644 --- a/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp @@ -16,11 +16,14 @@ #include "llvm/CodeGen/GCMetadataPrinter.h" #include "llvm/Module.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCStreamer.h" +#include "llvm/Target/Mangler.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/SmallString.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" using namespace llvm; @@ -29,11 +32,8 @@ namespace { class OcamlGCMetadataPrinter : public GCMetadataPrinter { public: - void beginAssembly(raw_ostream &OS, AsmPrinter &AP, - const MCAsmInfo &MAI); - - void finishAssembly(raw_ostream &OS, AsmPrinter &AP, - const MCAsmInfo &MAI); + void beginAssembly(AsmPrinter &AP); + void finishAssembly(AsmPrinter &AP); }; } @@ -43,33 +43,34 @@ Y("ocaml", "ocaml 3.10-compatible collector"); void llvm::linkOcamlGCPrinter() { } -static void EmitCamlGlobal(const Module &M, raw_ostream &OS, AsmPrinter &AP, - const MCAsmInfo &MAI, const char *Id) { +static void EmitCamlGlobal(const Module &M, AsmPrinter &AP, const char *Id) { const std::string &MId = M.getModuleIdentifier(); - std::string Mangled; - Mangled += MAI.getGlobalPrefix(); - Mangled += "caml"; - size_t Letter = Mangled.size(); - Mangled.append(MId.begin(), std::find(MId.begin(), MId.end(), '.')); - Mangled += "__"; - Mangled += Id; - + std::string SymName; + SymName += "caml"; + size_t Letter = SymName.size(); + SymName.append(MId.begin(), std::find(MId.begin(), MId.end(), '.')); + SymName += "__"; + SymName += Id; + // Capitalize the first letter of the module name. - Mangled[Letter] = toupper(Mangled[Letter]); - - if (const char *GlobalDirective = MAI.getGlobalDirective()) - OS << GlobalDirective << Mangled << "\n"; - OS << Mangled << ":\n"; + SymName[Letter] = toupper(SymName[Letter]); + + SmallString<128> TmpStr; + AP.Mang->getNameWithPrefix(TmpStr, SymName); + + MCSymbol *Sym = AP.OutContext.GetOrCreateSymbol(TmpStr); + + AP.OutStreamer.EmitSymbolAttribute(Sym, MCSA_Global); + AP.OutStreamer.EmitLabel(Sym); } -void OcamlGCMetadataPrinter::beginAssembly(raw_ostream &OS, AsmPrinter &AP, - const MCAsmInfo &MAI) { +void OcamlGCMetadataPrinter::beginAssembly(AsmPrinter &AP) { AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getTextSection()); - EmitCamlGlobal(getModule(), OS, AP, MAI, "code_begin"); + EmitCamlGlobal(getModule(), AP, "code_begin"); AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getDataSection()); - EmitCamlGlobal(getModule(), OS, AP, MAI, "data_begin"); + EmitCamlGlobal(getModule(), AP, "data_begin"); } /// emitAssembly - Print the frametable. The ocaml frametable format is thus: @@ -88,28 +89,20 @@ void OcamlGCMetadataPrinter::beginAssembly(raw_ostream &OS, AsmPrinter &AP, /// (FrameSize and LiveOffsets would overflow). FrameTablePrinter will abort if /// either condition is detected in a function which uses the GC. /// -void OcamlGCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP, - const MCAsmInfo &MAI) { - const char *AddressDirective; - int AddressAlignLog; - if (AP.TM.getTargetData()->getPointerSize() == sizeof(int32_t)) { - AddressDirective = MAI.getData32bitsDirective(); - AddressAlignLog = 2; - } else { - AddressDirective = MAI.getData64bitsDirective(); - AddressAlignLog = 3; - } +void OcamlGCMetadataPrinter::finishAssembly(AsmPrinter &AP) { + unsigned IntPtrSize = AP.TM.getTargetData()->getPointerSize(); AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getTextSection()); - EmitCamlGlobal(getModule(), OS, AP, MAI, "code_end"); + EmitCamlGlobal(getModule(), AP, "code_end"); AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getDataSection()); - EmitCamlGlobal(getModule(), OS, AP, MAI, "data_end"); + EmitCamlGlobal(getModule(), AP, "data_end"); - OS << AddressDirective << 0 << '\n'; // FIXME: Why does ocaml emit this?? + // FIXME: Why does ocaml emit this?? + AP.OutStreamer.EmitIntValue(0, IntPtrSize, 0); AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getDataSection()); - EmitCamlGlobal(getModule(), OS, AP, MAI, "frametable"); + EmitCamlGlobal(getModule(), AP, "frametable"); for (iterator I = begin(), IE = end(); I != IE; ++I) { GCFunctionInfo &FI = **I; @@ -125,8 +118,9 @@ void OcamlGCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP, llvm_report_error(Msg.str()); // Very rude! } - OS << "\t" << MAI.getCommentString() << " live roots for " - << FI.getFunction().getName() << "\n"; + AP.OutStreamer.AddComment("live roots for " + + Twine(FI.getFunction().getName())); + AP.OutStreamer.AddBlankLine(); for (GCFunctionInfo::iterator J = FI.begin(), JE = FI.end(); J != JE; ++J) { size_t LiveCount = FI.live_size(J); @@ -139,10 +133,8 @@ void OcamlGCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP, llvm_report_error(Msg.str()); // Very rude! } - OS << AddressDirective << J->Label->getName() << '\n'; - + AP.OutStreamer.EmitSymbolValue(J->Label, IntPtrSize, 0); AP.EmitInt16(FrameSize); - AP.EmitInt16(LiveCount); for (GCFunctionInfo::live_iterator K = FI.live_begin(J), @@ -154,7 +146,7 @@ void OcamlGCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP, AP.EmitInt32(K->StackOffset); } - AP.EmitAlignment(AddressAlignLog); + AP.EmitAlignment(IntPtrSize == 4 ? 2 : 3); } } } diff --git a/lib/CodeGen/GCMetadataPrinter.cpp b/lib/CodeGen/GCMetadataPrinter.cpp index 752752f71ba3..f80e9ced0bc9 100644 --- a/lib/CodeGen/GCMetadataPrinter.cpp +++ b/lib/CodeGen/GCMetadataPrinter.cpp @@ -18,12 +18,10 @@ GCMetadataPrinter::GCMetadataPrinter() { } GCMetadataPrinter::~GCMetadataPrinter() { } -void GCMetadataPrinter::beginAssembly(raw_ostream &OS, AsmPrinter &AP, - const MCAsmInfo &MAI) { +void GCMetadataPrinter::beginAssembly(AsmPrinter &AP) { // Default is no action. } -void GCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP, - const MCAsmInfo &MAI) { +void GCMetadataPrinter::finishAssembly(AsmPrinter &AP) { // Default is no action. } diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp index 75e45efe4de1..ed57f4cb101f 100644 --- a/lib/CodeGen/LLVMTargetMachine.cpp +++ b/lib/CodeGen/LLVMTargetMachine.cpp @@ -123,18 +123,15 @@ bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, const MCAsmInfo &MAI = *getMCAsmInfo(); OwningPtr<MCStreamer> AsmStreamer; - formatted_raw_ostream *LegacyOutput; switch (FileType) { default: return true; case CGFT_AssemblyFile: { MCInstPrinter *InstPrinter = - getTarget().createMCInstPrinter(MAI.getAssemblerDialect(), MAI, Out); + getTarget().createMCInstPrinter(MAI.getAssemblerDialect(), MAI); AsmStreamer.reset(createAsmStreamer(*Context, Out, getTargetData()->isLittleEndian(), getVerboseAsm(), InstPrinter, /*codeemitter*/0)); - // Set the AsmPrinter's "O" to the output file. - LegacyOutput = &Out; break; } case CGFT_ObjectFile: { @@ -146,29 +143,17 @@ bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, return true; AsmStreamer.reset(createMachOStreamer(*Context, *TAB, Out, MCE)); - - // Any output to the asmprinter's "O" stream is bad and needs to be fixed, - // force it to come out stderr. - // FIXME: this is horrible and leaks, eventually remove the raw_ostream from - // asmprinter. - LegacyOutput = new formatted_raw_ostream(errs()); break; } case CGFT_Null: // The Null output is intended for use for performance analysis and testing, // not real users. AsmStreamer.reset(createNullStreamer(*Context)); - // Any output to the asmprinter's "O" stream is bad and needs to be fixed, - // force it to come out stderr. - // FIXME: this is horrible and leaks, eventually remove the raw_ostream from - // asmprinter. - LegacyOutput = new formatted_raw_ostream(errs()); break; } // Create the AsmPrinter, which takes ownership of AsmStreamer if successful. - FunctionPass *Printer = - getTarget().createAsmPrinter(*LegacyOutput, *this, *AsmStreamer); + FunctionPass *Printer = getTarget().createAsmPrinter(*this, *AsmStreamer); if (Printer == 0) return true; diff --git a/lib/CodeGen/MachineFunction.cpp b/lib/CodeGen/MachineFunction.cpp index beac0c630bb5..e4ed7dbac4e7 100644 --- a/lib/CodeGen/MachineFunction.cpp +++ b/lib/CodeGen/MachineFunction.cpp @@ -23,6 +23,7 @@ #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" #include "llvm/MC/MCAsmInfo.h" @@ -51,8 +52,8 @@ void ilist_traits<MachineBasicBlock>::deleteNode(MachineBasicBlock *MBB) { } MachineFunction::MachineFunction(Function *F, const TargetMachine &TM, - unsigned FunctionNum, MCContext &ctx) - : Fn(F), Target(TM), Ctx(ctx) { + unsigned FunctionNum, MachineModuleInfo &mmi) + : Fn(F), Target(TM), Ctx(mmi.getContext()), MMI(mmi) { if (TM.getRegisterInfo()) RegInfo = new (Allocator) MachineRegisterInfo(*TM.getRegisterInfo()); else diff --git a/lib/CodeGen/MachineFunctionAnalysis.cpp b/lib/CodeGen/MachineFunctionAnalysis.cpp index d3f1d8296daa..3b2eb6d388b4 100644 --- a/lib/CodeGen/MachineFunctionAnalysis.cpp +++ b/lib/CodeGen/MachineFunctionAnalysis.cpp @@ -35,10 +35,23 @@ MachineFunctionAnalysis::~MachineFunctionAnalysis() { assert(!MF && "MachineFunctionAnalysis left initialized!"); } +void MachineFunctionAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired<MachineModuleInfo>(); +} + +bool MachineFunctionAnalysis::doInitialization(Module &M) { + MachineModuleInfo *MMI = getAnalysisIfAvailable<MachineModuleInfo>(); + assert(MMI && "MMI not around yet??"); + MMI->setModule(&M); + NextFnNum = 1; return false; +} + + bool MachineFunctionAnalysis::runOnFunction(Function &F) { assert(!MF && "MachineFunctionAnalysis already initialized!"); MF = new MachineFunction(&F, TM, NextFnNum++, - getAnalysis<MachineModuleInfo>().getContext()); + getAnalysis<MachineModuleInfo>()); return false; } @@ -46,8 +59,3 @@ void MachineFunctionAnalysis::releaseMemory() { delete MF; MF = 0; } - -void MachineFunctionAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesAll(); - AU.addRequired<MachineModuleInfo>(); -} diff --git a/lib/CodeGen/MachineModuleInfo.cpp b/lib/CodeGen/MachineModuleInfo.cpp index ad4f01b7a9ad..f813a553670b 100644 --- a/lib/CodeGen/MachineModuleInfo.cpp +++ b/lib/CodeGen/MachineModuleInfo.cpp @@ -262,6 +262,7 @@ MachineModuleInfo::MachineModuleInfo(const MCAsmInfo &MAI) // Always emit some info, by default "no personality" info. Personalities.push_back(NULL); AddrLabelSymbols = 0; + TheModule = 0; } MachineModuleInfo::MachineModuleInfo() diff --git a/lib/CodeGen/MachineSink.cpp b/lib/CodeGen/MachineSink.cpp index e47ba7c2cc37..e65961901578 100644 --- a/lib/CodeGen/MachineSink.cpp +++ b/lib/CodeGen/MachineSink.cpp @@ -126,6 +126,11 @@ bool MachineSinking::ProcessBlock(MachineBasicBlock &MBB) { // Can't sink anything out of a block that has less than two successors. if (MBB.succ_size() <= 1 || MBB.empty()) return false; + // Don't bother sinking code out of unreachable blocks. In addition to being + // unprofitable, it can also lead to infinite looping, because in an unreachable + // loop there may be nowhere to stop. + if (!DT->isReachableFromEntry(&MBB)) return false; + bool MadeChange = false; // Walk the basic block bottom-up. Remember if we saw a store. diff --git a/lib/CodeGen/PrologEpilogInserter.cpp b/lib/CodeGen/PrologEpilogInserter.cpp index 2d54cd427418..27cb566d9512 100644 --- a/lib/CodeGen/PrologEpilogInserter.cpp +++ b/lib/CodeGen/PrologEpilogInserter.cpp @@ -24,7 +24,6 @@ #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/RegisterScavenging.h" #include "llvm/Target/TargetMachine.h" @@ -59,11 +58,6 @@ bool PEI::runOnMachineFunction(MachineFunction &Fn) { FrameIndexVirtualScavenging = TRI->requiresFrameIndexScavenging(Fn); FrameConstantRegMap.clear(); - // Get MachineModuleInfo so that we can track the construction of the - // frame. - if (MachineModuleInfo *MMI = getAnalysisIfAvailable<MachineModuleInfo>()) - Fn.getFrameInfo()->setMachineModuleInfo(MMI); - // Calculate the MaxCallFrameSize and HasCalls variables for the function's // frame information. Also eliminates call frame pseudo instructions. calculateCallsInformation(Fn); diff --git a/lib/CodeGen/SelectionDAG/FastISel.cpp b/lib/CodeGen/SelectionDAG/FastISel.cpp index d6f8a205c1f6..4bf41f28c250 100644 --- a/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -47,7 +47,6 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/DwarfWriter.h" #include "llvm/Analysis/DebugInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetInstrInfo.h" @@ -326,8 +325,8 @@ bool FastISel::SelectCall(User *I) { default: break; case Intrinsic::dbg_declare: { DbgDeclareInst *DI = cast<DbgDeclareInst>(I); - if (!DIDescriptor::ValidDebugInfo(DI->getVariable(), CodeGenOpt::None)||!DW - || !DW->ShouldEmitDwarfDebug()) + if (!DIDescriptor::ValidDebugInfo(DI->getVariable(), CodeGenOpt::None) || + !MF.getMMI().hasDebugInfo()) return true; Value *Address = DI->getAddress(); @@ -341,7 +340,7 @@ bool FastISel::SelectCall(User *I) { if (SI == StaticAllocaMap.end()) break; // VLAs. int FI = SI->second; if (!DI->getDebugLoc().isUnknown()) - MMI->setVariableDbgInfo(DI->getVariable(), FI, DI->getDebugLoc()); + MF.getMMI().setVariableDbgInfo(DI->getVariable(), FI, DI->getDebugLoc()); // Building the map above is target independent. Generating DBG_VALUE // inline is target dependent; do this now. @@ -400,44 +399,39 @@ bool FastISel::SelectCall(User *I) { switch (TLI.getOperationAction(ISD::EHSELECTION, VT)) { default: break; case TargetLowering::Expand: { - if (MMI) { - if (MBB->isLandingPad()) - AddCatchInfo(*cast<CallInst>(I), MMI, MBB); - else { + if (MBB->isLandingPad()) + AddCatchInfo(*cast<CallInst>(I), &MF.getMMI(), MBB); + else { #ifndef NDEBUG - CatchInfoLost.insert(cast<CallInst>(I)); + CatchInfoLost.insert(cast<CallInst>(I)); #endif - // FIXME: Mark exception selector register as live in. Hack for PR1508. - unsigned Reg = TLI.getExceptionSelectorRegister(); - if (Reg) MBB->addLiveIn(Reg); - } - + // FIXME: Mark exception selector register as live in. Hack for PR1508. unsigned Reg = TLI.getExceptionSelectorRegister(); - EVT SrcVT = TLI.getPointerTy(); - const TargetRegisterClass *RC = TLI.getRegClassFor(SrcVT); - unsigned ResultReg = createResultReg(RC); - bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg, Reg, - RC, RC); - assert(InsertedCopy && "Can't copy address registers!"); - InsertedCopy = InsertedCopy; - - // Cast the register to the type of the selector. - if (SrcVT.bitsGT(MVT::i32)) - ResultReg = FastEmit_r(SrcVT.getSimpleVT(), MVT::i32, ISD::TRUNCATE, - ResultReg); - else if (SrcVT.bitsLT(MVT::i32)) - ResultReg = FastEmit_r(SrcVT.getSimpleVT(), MVT::i32, - ISD::SIGN_EXTEND, ResultReg); - if (ResultReg == 0) - // Unhandled operand. Halt "fast" selection and bail. - return false; - - UpdateValueMap(I, ResultReg); - } else { - unsigned ResultReg = - getRegForValue(Constant::getNullValue(I->getType())); - UpdateValueMap(I, ResultReg); + if (Reg) MBB->addLiveIn(Reg); } + + unsigned Reg = TLI.getExceptionSelectorRegister(); + EVT SrcVT = TLI.getPointerTy(); + const TargetRegisterClass *RC = TLI.getRegClassFor(SrcVT); + unsigned ResultReg = createResultReg(RC); + bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg, Reg, + RC, RC); + assert(InsertedCopy && "Can't copy address registers!"); + InsertedCopy = InsertedCopy; + + // Cast the register to the type of the selector. + if (SrcVT.bitsGT(MVT::i32)) + ResultReg = FastEmit_r(SrcVT.getSimpleVT(), MVT::i32, ISD::TRUNCATE, + ResultReg); + else if (SrcVT.bitsLT(MVT::i32)) + ResultReg = FastEmit_r(SrcVT.getSimpleVT(), MVT::i32, + ISD::SIGN_EXTEND, ResultReg); + if (ResultReg == 0) + // Unhandled operand. Halt "fast" selection and bail. + return false; + + UpdateValueMap(I, ResultReg); + return true; } } @@ -734,8 +728,6 @@ FastISel::SelectOperator(User *I, unsigned Opcode) { } FastISel::FastISel(MachineFunction &mf, - MachineModuleInfo *mmi, - DwarfWriter *dw, DenseMap<const Value *, unsigned> &vm, DenseMap<const BasicBlock *, MachineBasicBlock *> &bm, DenseMap<const AllocaInst *, int> &am @@ -751,8 +743,6 @@ FastISel::FastISel(MachineFunction &mf, CatchInfoLost(cil), #endif MF(mf), - MMI(mmi), - DW(dw), MRI(MF.getRegInfo()), MFI(*MF.getFrameInfo()), MCP(*MF.getConstantPool()), diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 63ca8e67000e..d35f0da393e4 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -16,7 +16,6 @@ #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/CodeGen/DwarfWriter.h" #include "llvm/Analysis/DebugInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/Target/TargetFrameInfo.h" diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 3643ea7c5315..8c0554d186d9 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -793,7 +793,7 @@ unsigned SelectionDAG::getEVTAlignment(EVT VT) const { // EntryNode could meaningfully have debug info if we can find it... SelectionDAG::SelectionDAG(TargetLowering &tli, FunctionLoweringInfo &fli) - : TLI(tli), FLI(fli), DW(0), + : TLI(tli), FLI(fli), EntryNode(ISD::EntryToken, DebugLoc(), getVTList(MVT::Other)), Root(getEntryNode()), Ordering(0) { AllNodes.push_back(&EntryNode); @@ -801,11 +801,8 @@ SelectionDAG::SelectionDAG(TargetLowering &tli, FunctionLoweringInfo &fli) DbgInfo = new SDDbgInfo(); } -void SelectionDAG::init(MachineFunction &mf, MachineModuleInfo *mmi, - DwarfWriter *dw) { +void SelectionDAG::init(MachineFunction &mf) { MF = &mf; - MMI = mmi; - DW = dw; Context = &mf.getFunction()->getContext(); } @@ -2258,8 +2255,7 @@ bool SelectionDAG::isVerifiedDebugInfoDesc(SDValue Op) const { if (GA->getOffset() != 0) return false; GlobalVariable *GV = dyn_cast<GlobalVariable>(GA->getGlobal()); if (!GV) return false; - MachineModuleInfo *MMI = getMachineModuleInfo(); - return MMI && MMI->hasDebugInfo(); + return MF->getMMI().hasDebugInfo(); } @@ -3210,11 +3206,9 @@ static bool FindOptimalMemOpLowering(std::vector<EVT> &MemOps, NonScalarIntSafe, DAG); if (VT == MVT::Other) { - VT = TLI.getPointerTy(); - const Type *Ty = VT.getTypeForEVT(*DAG.getContext()); - if (DstAlign >= TLI.getTargetData()->getABITypeAlignment(Ty) || + if (DstAlign >= TLI.getTargetData()->getPointerPrefAlignment() || TLI.allowsUnalignedMemoryAccesses(VT)) { - VT = MVT::i64; + VT = TLI.getPointerTy(); } else { switch (DstAlign & 7) { case 0: VT = MVT::i64; break; @@ -3263,7 +3257,8 @@ static bool FindOptimalMemOpLowering(std::vector<EVT> &MemOps, static SDValue getMemcpyLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, SDValue Chain, SDValue Dst, SDValue Src, uint64_t Size, - unsigned Align, bool AlwaysInline, + unsigned Align, bool isVol, + bool AlwaysInline, const Value *DstSV, uint64_t DstSVOff, const Value *SrcSV, uint64_t SrcSVOff) { // Turn a memcpy of undef to nop. @@ -3322,7 +3317,7 @@ static SDValue getMemcpyLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, Value = getMemsetStringVal(VT, dl, DAG, TLI, Str, SrcOff); Store = DAG.getStore(Chain, dl, Value, getMemBasePlusOffset(Dst, DstOff, DAG), - DstSV, DstSVOff + DstOff, false, false, Align); + DstSV, DstSVOff + DstOff, isVol, false, Align); } else { // The type might not be legal for the target. This should only happen // if the type is smaller than a legal type, as on PPC, so the right @@ -3333,11 +3328,11 @@ static SDValue getMemcpyLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, assert(NVT.bitsGE(VT)); Value = DAG.getExtLoad(ISD::EXTLOAD, dl, NVT, Chain, getMemBasePlusOffset(Src, SrcOff, DAG), - SrcSV, SrcSVOff + SrcOff, VT, false, false, + SrcSV, SrcSVOff + SrcOff, VT, isVol, false, MinAlign(SrcAlign, SrcOff)); Store = DAG.getTruncStore(Chain, dl, Value, getMemBasePlusOffset(Dst, DstOff, DAG), - DstSV, DstSVOff + DstOff, VT, false, false, + DstSV, DstSVOff + DstOff, VT, isVol, false, Align); } OutChains.push_back(Store); @@ -3352,7 +3347,8 @@ static SDValue getMemcpyLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, static SDValue getMemmoveLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, SDValue Chain, SDValue Dst, SDValue Src, uint64_t Size, - unsigned Align,bool AlwaysInline, + unsigned Align, bool isVol, + bool AlwaysInline, const Value *DstSV, uint64_t DstSVOff, const Value *SrcSV, uint64_t SrcSVOff) { // Turn a memmove of undef to nop. @@ -3403,7 +3399,7 @@ static SDValue getMemmoveLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, Value = DAG.getLoad(VT, dl, Chain, getMemBasePlusOffset(Src, SrcOff, DAG), - SrcSV, SrcSVOff + SrcOff, false, false, SrcAlign); + SrcSV, SrcSVOff + SrcOff, isVol, false, SrcAlign); LoadValues.push_back(Value); LoadChains.push_back(Value.getValue(1)); SrcOff += VTSize; @@ -3418,7 +3414,7 @@ static SDValue getMemmoveLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, Store = DAG.getStore(Chain, dl, LoadValues[i], getMemBasePlusOffset(Dst, DstOff, DAG), - DstSV, DstSVOff + DstOff, false, false, Align); + DstSV, DstSVOff + DstOff, isVol, false, Align); OutChains.push_back(Store); DstOff += VTSize; } @@ -3430,7 +3426,7 @@ static SDValue getMemmoveLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, static SDValue getMemsetStores(SelectionDAG &DAG, DebugLoc dl, SDValue Chain, SDValue Dst, SDValue Src, uint64_t Size, - unsigned Align, + unsigned Align, bool isVol, const Value *DstSV, uint64_t DstSVOff) { // Turn a memset of undef to nop. if (Src.getOpcode() == ISD::UNDEF) @@ -3472,7 +3468,7 @@ static SDValue getMemsetStores(SelectionDAG &DAG, DebugLoc dl, SDValue Value = getMemsetValue(Src, VT, DAG, dl); SDValue Store = DAG.getStore(Chain, dl, Value, getMemBasePlusOffset(Dst, DstOff, DAG), - DstSV, DstSVOff + DstOff, false, false, 0); + DstSV, DstSVOff + DstOff, isVol, false, 0); OutChains.push_back(Store); DstOff += VTSize; } @@ -3483,7 +3479,7 @@ static SDValue getMemsetStores(SelectionDAG &DAG, DebugLoc dl, SDValue SelectionDAG::getMemcpy(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Src, SDValue Size, - unsigned Align, bool AlwaysInline, + unsigned Align, bool isVol, bool AlwaysInline, const Value *DstSV, uint64_t DstSVOff, const Value *SrcSV, uint64_t SrcSVOff) { @@ -3497,7 +3493,7 @@ SDValue SelectionDAG::getMemcpy(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Result = getMemcpyLoadsAndStores(*this, dl, Chain, Dst, Src, ConstantSize->getZExtValue(),Align, - false, DstSV, DstSVOff, SrcSV, SrcSVOff); + isVol, false, DstSV, DstSVOff, SrcSV, SrcSVOff); if (Result.getNode()) return Result; } @@ -3506,7 +3502,7 @@ SDValue SelectionDAG::getMemcpy(SDValue Chain, DebugLoc dl, SDValue Dst, // code. If the target chooses to do this, this is the next best. SDValue Result = TLI.EmitTargetCodeForMemcpy(*this, dl, Chain, Dst, Src, Size, Align, - AlwaysInline, + isVol, AlwaysInline, DstSV, DstSVOff, SrcSV, SrcSVOff); if (Result.getNode()) return Result; @@ -3516,10 +3512,16 @@ SDValue SelectionDAG::getMemcpy(SDValue Chain, DebugLoc dl, SDValue Dst, if (AlwaysInline) { assert(ConstantSize && "AlwaysInline requires a constant size!"); return getMemcpyLoadsAndStores(*this, dl, Chain, Dst, Src, - ConstantSize->getZExtValue(), Align, true, - DstSV, DstSVOff, SrcSV, SrcSVOff); + ConstantSize->getZExtValue(), Align, isVol, + true, DstSV, DstSVOff, SrcSV, SrcSVOff); } + // FIXME: If the memcpy is volatile (isVol), lowering it to a plain libc + // memcpy is not guaranteed to be safe. libc memcpys aren't required to + // respect volatile, so they may do things like read or write memory + // beyond the given memory regions. But fixing this isn't easy, and most + // people don't care. + // Emit a library call. TargetLowering::ArgListTy Args; TargetLowering::ArgListEntry Entry; @@ -3541,7 +3543,7 @@ SDValue SelectionDAG::getMemcpy(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue SelectionDAG::getMemmove(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Src, SDValue Size, - unsigned Align, + unsigned Align, bool isVol, const Value *DstSV, uint64_t DstSVOff, const Value *SrcSV, uint64_t SrcSVOff) { @@ -3555,8 +3557,8 @@ SDValue SelectionDAG::getMemmove(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Result = getMemmoveLoadsAndStores(*this, dl, Chain, Dst, Src, - ConstantSize->getZExtValue(), - Align, false, DstSV, DstSVOff, SrcSV, SrcSVOff); + ConstantSize->getZExtValue(), Align, isVol, + false, DstSV, DstSVOff, SrcSV, SrcSVOff); if (Result.getNode()) return Result; } @@ -3564,12 +3566,13 @@ SDValue SelectionDAG::getMemmove(SDValue Chain, DebugLoc dl, SDValue Dst, // Then check to see if we should lower the memmove with target-specific // code. If the target chooses to do this, this is the next best. SDValue Result = - TLI.EmitTargetCodeForMemmove(*this, dl, Chain, Dst, Src, Size, Align, + TLI.EmitTargetCodeForMemmove(*this, dl, Chain, Dst, Src, Size, Align, isVol, DstSV, DstSVOff, SrcSV, SrcSVOff); if (Result.getNode()) return Result; // Emit a library call. + assert(!isVol && "library memmove does not support volatile"); TargetLowering::ArgListTy Args; TargetLowering::ArgListEntry Entry; Entry.Ty = TLI.getTargetData()->getIntPtrType(*getContext()); @@ -3590,7 +3593,7 @@ SDValue SelectionDAG::getMemmove(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue SelectionDAG::getMemset(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Src, SDValue Size, - unsigned Align, + unsigned Align, bool isVol, const Value *DstSV, uint64_t DstSVOff) { // Check to see if we should lower the memset to stores first. @@ -3601,9 +3604,10 @@ SDValue SelectionDAG::getMemset(SDValue Chain, DebugLoc dl, SDValue Dst, if (ConstantSize->isNullValue()) return Chain; - SDValue Result = getMemsetStores(*this, dl, Chain, Dst, Src, - ConstantSize->getZExtValue(), - Align, DstSV, DstSVOff); + SDValue Result = + getMemsetStores(*this, dl, Chain, Dst, Src, ConstantSize->getZExtValue(), + Align, isVol, DstSV, DstSVOff); + if (Result.getNode()) return Result; } @@ -3611,12 +3615,13 @@ SDValue SelectionDAG::getMemset(SDValue Chain, DebugLoc dl, SDValue Dst, // Then check to see if we should lower the memset with target-specific // code. If the target chooses to do this, this is the next best. SDValue Result = - TLI.EmitTargetCodeForMemset(*this, dl, Chain, Dst, Src, Size, Align, + TLI.EmitTargetCodeForMemset(*this, dl, Chain, Dst, Src, Size, Align, isVol, DstSV, DstSVOff); if (Result.getNode()) return Result; // Emit a library call. + assert(!isVol && "library memset does not support volatile"); const Type *IntPtrTy = TLI.getTargetData()->getIntPtrType(*getContext()); TargetLowering::ArgListTy Args; TargetLowering::ArgListEntry Entry; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 879bdb2cbbb7..4bbb3dea92f4 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -40,7 +40,6 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/CodeGen/SelectionDAG.h" -#include "llvm/CodeGen/DwarfWriter.h" #include "llvm/Analysis/DebugInfo.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetData.h" @@ -3731,28 +3730,50 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { case Intrinsic::longjmp: return "_longjmp"+!TLI.usesUnderscoreLongJmp(); case Intrinsic::memcpy: { + // Assert for address < 256 since we support only user defined address + // spaces. + assert(cast<PointerType>(I.getOperand(1)->getType())->getAddressSpace() + < 256 && + cast<PointerType>(I.getOperand(2)->getType())->getAddressSpace() + < 256 && + "Unknown address space"); SDValue Op1 = getValue(I.getOperand(1)); SDValue Op2 = getValue(I.getOperand(2)); SDValue Op3 = getValue(I.getOperand(3)); unsigned Align = cast<ConstantInt>(I.getOperand(4))->getZExtValue(); - DAG.setRoot(DAG.getMemcpy(getRoot(), dl, Op1, Op2, Op3, Align, false, + bool isVol = cast<ConstantInt>(I.getOperand(5))->getZExtValue(); + DAG.setRoot(DAG.getMemcpy(getRoot(), dl, Op1, Op2, Op3, Align, isVol, false, I.getOperand(1), 0, I.getOperand(2), 0)); return 0; } case Intrinsic::memset: { + // Assert for address < 256 since we support only user defined address + // spaces. + assert(cast<PointerType>(I.getOperand(1)->getType())->getAddressSpace() + < 256 && + "Unknown address space"); SDValue Op1 = getValue(I.getOperand(1)); SDValue Op2 = getValue(I.getOperand(2)); SDValue Op3 = getValue(I.getOperand(3)); unsigned Align = cast<ConstantInt>(I.getOperand(4))->getZExtValue(); - DAG.setRoot(DAG.getMemset(getRoot(), dl, Op1, Op2, Op3, Align, + bool isVol = cast<ConstantInt>(I.getOperand(5))->getZExtValue(); + DAG.setRoot(DAG.getMemset(getRoot(), dl, Op1, Op2, Op3, Align, isVol, I.getOperand(1), 0)); return 0; } case Intrinsic::memmove: { + // Assert for address < 256 since we support only user defined address + // spaces. + assert(cast<PointerType>(I.getOperand(1)->getType())->getAddressSpace() + < 256 && + cast<PointerType>(I.getOperand(2)->getType())->getAddressSpace() + < 256 && + "Unknown address space"); SDValue Op1 = getValue(I.getOperand(1)); SDValue Op2 = getValue(I.getOperand(2)); SDValue Op3 = getValue(I.getOperand(3)); unsigned Align = cast<ConstantInt>(I.getOperand(4))->getZExtValue(); + bool isVol = cast<ConstantInt>(I.getOperand(5))->getZExtValue(); // If the source and destination are known to not be aliases, we can // lower memmove as memcpy. @@ -3761,12 +3782,12 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { Size = C->getZExtValue(); if (AA->alias(I.getOperand(1), Size, I.getOperand(2), Size) == AliasAnalysis::NoAlias) { - DAG.setRoot(DAG.getMemcpy(getRoot(), dl, Op1, Op2, Op3, Align, false, - I.getOperand(1), 0, I.getOperand(2), 0)); + DAG.setRoot(DAG.getMemcpy(getRoot(), dl, Op1, Op2, Op3, Align, isVol, + false, I.getOperand(1), 0, I.getOperand(2), 0)); return 0; } - DAG.setRoot(DAG.getMemmove(getRoot(), dl, Op1, Op2, Op3, Align, + DAG.setRoot(DAG.getMemmove(getRoot(), dl, Op1, Op2, Op3, Align, isVol, I.getOperand(1), 0, I.getOperand(2), 0)); return 0; } @@ -3776,9 +3797,6 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { if (OptLevel != CodeGenOpt::None) // FIXME: Variable debug info is not supported here. return 0; - DwarfWriter *DW = DAG.getDwarfWriter(); - if (!DW) - return 0; DbgDeclareInst &DI = cast<DbgDeclareInst>(I); if (!DIDescriptor::ValidDebugInfo(DI.getVariable(), CodeGenOpt::None)) return 0; @@ -3799,15 +3817,12 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { return 0; // VLAs. int FI = SI->second; - if (MachineModuleInfo *MMI = DAG.getMachineModuleInfo()) - if (!DI.getDebugLoc().isUnknown()) - MMI->setVariableDbgInfo(Variable, FI, DI.getDebugLoc()); + MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI(); + if (!DI.getDebugLoc().isUnknown() && MMI.hasDebugInfo()) + MMI.setVariableDbgInfo(Variable, FI, DI.getDebugLoc()); return 0; } case Intrinsic::dbg_value: { - DwarfWriter *DW = DAG.getDwarfWriter(); - if (!DW) - return 0; DbgValueInst &DI = cast<DbgValueInst>(I); if (!DIDescriptor::ValidDebugInfo(DI.getVariable(), CodeGenOpt::None)) return 0; @@ -3852,9 +3867,9 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { return 0; // VLAs. int FI = SI->second; - if (MachineModuleInfo *MMI = DAG.getMachineModuleInfo()) - if (!DI.getDebugLoc().isUnknown()) - MMI->setVariableDbgInfo(Variable, FI, DI.getDebugLoc()); + MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI(); + if (!DI.getDebugLoc().isUnknown() && MMI.hasDebugInfo()) + MMI.setVariableDbgInfo(Variable, FI, DI.getDebugLoc()); return 0; } case Intrinsic::eh_exception: { @@ -3870,10 +3885,9 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { } case Intrinsic::eh_selector: { - MachineModuleInfo *MMI = DAG.getMachineModuleInfo(); - + MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI(); if (CurMBB->isLandingPad()) - AddCatchInfo(I, MMI, CurMBB); + AddCatchInfo(I, &MMI, CurMBB); else { #ifndef NDEBUG FuncInfo.CatchInfoLost.insert(&I); @@ -3895,40 +3909,25 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { } case Intrinsic::eh_typeid_for: { - MachineModuleInfo *MMI = DAG.getMachineModuleInfo(); - - if (MMI) { - // Find the type id for the given typeinfo. - GlobalVariable *GV = ExtractTypeInfo(I.getOperand(1)); - unsigned TypeID = MMI->getTypeIDFor(GV); - Res = DAG.getConstant(TypeID, MVT::i32); - } else { - // Return something different to eh_selector. - Res = DAG.getConstant(1, MVT::i32); - } - + // Find the type id for the given typeinfo. + GlobalVariable *GV = ExtractTypeInfo(I.getOperand(1)); + unsigned TypeID = DAG.getMachineFunction().getMMI().getTypeIDFor(GV); + Res = DAG.getConstant(TypeID, MVT::i32); setValue(&I, Res); return 0; } case Intrinsic::eh_return_i32: case Intrinsic::eh_return_i64: - if (MachineModuleInfo *MMI = DAG.getMachineModuleInfo()) { - MMI->setCallsEHReturn(true); - DAG.setRoot(DAG.getNode(ISD::EH_RETURN, dl, - MVT::Other, - getControlRoot(), - getValue(I.getOperand(1)), - getValue(I.getOperand(2)))); - } else { - setValue(&I, DAG.getConstant(0, TLI.getPointerTy())); - } - + DAG.getMachineFunction().getMMI().setCallsEHReturn(true); + DAG.setRoot(DAG.getNode(ISD::EH_RETURN, dl, + MVT::Other, + getControlRoot(), + getValue(I.getOperand(1)), + getValue(I.getOperand(2)))); return 0; case Intrinsic::eh_unwind_init: - if (MachineModuleInfo *MMI = DAG.getMachineModuleInfo()) { - MMI->setCallsUnwindInit(true); - } + DAG.getMachineFunction().getMMI().setCallsUnwindInit(true); return 0; case Intrinsic::eh_dwarf_cfa: { EVT VT = getValue(I.getOperand(1)).getValueType(); @@ -3947,12 +3946,12 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { return 0; } case Intrinsic::eh_sjlj_callsite: { - MachineModuleInfo *MMI = DAG.getMachineModuleInfo(); + MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI(); ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(1)); assert(CI && "Non-constant call site value in eh.sjlj.callsite!"); - assert(MMI->getCurrentCallSite() == 0 && "Overlapping call sites!"); + assert(MMI.getCurrentCallSite() == 0 && "Overlapping call sites!"); - MMI->setCurrentCallSite(CI->getZExtValue()); + MMI.setCurrentCallSite(CI->getZExtValue()); return 0; } @@ -4337,7 +4336,7 @@ void SelectionDAGBuilder::LowerCallTo(CallSite CS, SDValue Callee, const PointerType *PT = cast<PointerType>(CS.getCalledValue()->getType()); const FunctionType *FTy = cast<FunctionType>(PT->getElementType()); const Type *RetTy = FTy->getReturnType(); - MachineModuleInfo *MMI = DAG.getMachineModuleInfo(); + MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI(); MCSymbol *BeginLabel = 0; TargetLowering::ArgListTy Args; @@ -4395,18 +4394,18 @@ void SelectionDAGBuilder::LowerCallTo(CallSite CS, SDValue Callee, Args.push_back(Entry); } - if (LandingPad && MMI) { + if (LandingPad) { // Insert a label before the invoke call to mark the try range. This can be // used to detect deletion of the invoke via the MachineModuleInfo. - BeginLabel = MMI->getContext().CreateTempSymbol(); + BeginLabel = MMI.getContext().CreateTempSymbol(); // For SjLj, keep track of which landing pads go with which invokes // so as to maintain the ordering of pads in the LSDA. - unsigned CallSiteIndex = MMI->getCurrentCallSite(); + unsigned CallSiteIndex = MMI.getCurrentCallSite(); if (CallSiteIndex) { - MMI->setCallSiteBeginLabel(BeginLabel, CallSiteIndex); + MMI.setCallSiteBeginLabel(BeginLabel, CallSiteIndex); // Now that the call site is handled, stop tracking it. - MMI->setCurrentCallSite(0); + MMI.setCurrentCallSite(0); } // Both PendingLoads and PendingExports must be flushed here; @@ -4497,14 +4496,14 @@ void SelectionDAGBuilder::LowerCallTo(CallSite CS, SDValue Callee, else HasTailCall = true; - if (LandingPad && MMI) { + if (LandingPad) { // Insert a label at the end of the invoke call to mark the try range. This // can be used to detect deletion of the invoke via the MachineModuleInfo. - MCSymbol *EndLabel = MMI->getContext().CreateTempSymbol(); + MCSymbol *EndLabel = MMI.getContext().CreateTempSymbol(); DAG.setRoot(DAG.getEHLabel(getCurDebugLoc(), getRoot(), EndLabel)); // Inform MachineModuleInfo of range. - MMI->addInvoke(LandingPad, BeginLabel, EndLabel); + MMI.addInvoke(LandingPad, BeginLabel, EndLabel); } } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h index 9f027729b75e..fdcba0f0bc72 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -56,7 +56,6 @@ class InsertValueInst; class Instruction; class LoadInst; class MachineBasicBlock; -class MachineFunction; class MachineInstr; class MachineRegisterInfo; class PHINode; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index d54566b8cd3a..9b137a52f7c3 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -41,7 +41,6 @@ #include "llvm/CodeGen/ScheduleHazardRecognizer.h" #include "llvm/CodeGen/SchedulerRegistry.h" #include "llvm/CodeGen/SelectionDAG.h" -#include "llvm/CodeGen/DwarfWriter.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameInfo.h" @@ -303,8 +302,6 @@ void SelectionDAGISel::getAnalysisUsage(AnalysisUsage &AU) const { AU.addPreserved<AliasAnalysis>(); AU.addRequired<GCModuleInfo>(); AU.addPreserved<GCModuleInfo>(); - AU.addRequired<DwarfWriter>(); - AU.addPreserved<DwarfWriter>(); MachineFunctionPass::getAnalysisUsage(AU); } @@ -331,9 +328,7 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) { RegInfo = &MF->getRegInfo(); DEBUG(dbgs() << "\n\n\n=== " << Fn.getName() << "\n"); - MachineModuleInfo *MMI = getAnalysisIfAvailable<MachineModuleInfo>(); - DwarfWriter *DW = getAnalysisIfAvailable<DwarfWriter>(); - CurDAG->init(*MF, MMI, DW); + CurDAG->init(*MF); FuncInfo->set(Fn, *MF, EnableFastISel); SDB->init(GFI, *AA); @@ -342,7 +337,7 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) { // Mark landing pad. FuncInfo->MBBMap[Invoke->getSuccessor(1)]->setIsLandingPad(); - SelectAllBasicBlocks(Fn, *MF, MMI, DW, TII); + SelectAllBasicBlocks(Fn, *MF, TII); // If the first basic block in the function has live ins that need to be // copied into vregs, emit the copies into the top of the block before @@ -844,15 +839,11 @@ void SelectionDAGISel::DoInstructionSelection() { void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, MachineFunction &MF, - MachineModuleInfo *MMI, - DwarfWriter *DW, const TargetInstrInfo &TII) { // Initialize the Fast-ISel state, if needed. FastISel *FastIS = 0; if (EnableFastISel) - FastIS = TLI.createFastISel(MF, MMI, DW, - FuncInfo->ValueMap, - FuncInfo->MBBMap, + FastIS = TLI.createFastISel(MF, FuncInfo->ValueMap, FuncInfo->MBBMap, FuncInfo->StaticAllocaMap #ifndef NDEBUG , FuncInfo->CatchInfoLost @@ -888,10 +879,10 @@ void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, } } - if (MMI && BB->isLandingPad()) { + if (BB->isLandingPad()) { // Add a label to mark the beginning of the landing pad. Deletion of the // landing pad can thus be detected via the MachineModuleInfo. - MCSymbol *Label = MMI->addLandingPad(BB); + MCSymbol *Label = MF.getMMI().addLandingPad(BB); const TargetInstrDesc &II = TII.get(TargetOpcode::EH_LABEL); BuildMI(BB, SDB->getCurDebugLoc(), II).addSym(Label); @@ -925,7 +916,7 @@ void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, if (I == E) // No catch info found - try to extract some from the successor. - CopyCatchInfo(Br->getSuccessor(0), LLVMBB, MMI, *FuncInfo); + CopyCatchInfo(Br->getSuccessor(0), LLVMBB, &MF.getMMI(), *FuncInfo); } } diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp index a2df2d09b85c..7b8ab9ed3f58 100644 --- a/lib/ExecutionEngine/JIT/JITEmitter.cpp +++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp @@ -825,7 +825,8 @@ void JITEmitter::processDebugLoc(DebugLoc DL, bool BeforePrintingInsn) { if (!BeforePrintingInsn) return; // FIXME: This is horribly inefficient. - DILocation CurDLT(DL.getAsMDNode(CurFn->getContext())); + DILocation CurDLT(DL.getAsMDNode( + EmissionDetails.MF->getFunction()->getContext())); if (CurDLT.getScope().getNode() != 0 && PrevDLT.getNode() !=CurDLT.getNode()){ JITEvent_EmittedFunctionDetails::LineStart NextLine; diff --git a/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp b/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp index 2baf97911d59..9c01b7329a5c 100644 --- a/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp +++ b/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp @@ -19,6 +19,7 @@ #define DEBUG_TYPE "oprofile-jit-event-listener" #include "llvm/Function.h" #include "llvm/Metadata.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/Analysis/DebugInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/ExecutionEngine/JITEventListener.h" @@ -77,10 +78,10 @@ class FilenameCache { DenseMap<AssertingVH<MDNode>, std::string> Filenames; public: - const char *getFilename(DIScope Scope) { - std::string &Filename = Filenames[Scope.getNode()]; + const char *getFilename(MDNode *Scope) { + std::string &Filename = Filenames[Scope]; if (Filename.empty()) { - Filename = Scope.getFilename(); + Filename = DIScope(Scope).getFilename(); } return Filename.c_str(); } @@ -91,9 +92,9 @@ static debug_line_info LineStartToOProfileFormat( uintptr_t Address, DebugLoc Loc) { debug_line_info Result; Result.vma = Address; - DILocation DILoc = MF.getDILocation(Loc); - Result.lineno = DILoc.getLineNumber(); - Result.filename = Filenames.getFilename(DILoc.getScope()); + Result.lineno = Loc.getLine(); + Result.filename = Filenames.getFilename( + Loc.getScope(MF.getFunction()->getContext())); DEBUG(dbgs() << "Mapping " << reinterpret_cast<void*>(Result.vma) << " to " << Result.filename << ":" << Result.lineno << "\n"); return Result; diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp index c96ff82b308d..f0da694a19e5 100644 --- a/lib/MC/MCAsmInfo.cpp +++ b/lib/MC/MCAsmInfo.cpp @@ -60,8 +60,6 @@ MCAsmInfo::MCAsmInfo() { LinkOnceDirective = 0; HiddenVisibilityAttr = MCSA_Hidden; ProtectedVisibilityAttr = MCSA_Protected; - AbsoluteDebugSectionOffsets = false; - AbsoluteEHSectionOffsets = false; HasLEB128 = false; HasDotLocAndDotFile = false; SupportsDebugInformation = false; diff --git a/lib/MC/MCAsmInfoCOFF.cpp b/lib/MC/MCAsmInfoCOFF.cpp index 5170206c729b..7fc7d7abb232 100644 --- a/lib/MC/MCAsmInfoCOFF.cpp +++ b/lib/MC/MCAsmInfoCOFF.cpp @@ -31,8 +31,6 @@ MCAsmInfoCOFF::MCAsmInfoCOFF() { // Set up DWARF directives HasLEB128 = true; // Target asm supports leb128 directives (little-endian) - AbsoluteDebugSectionOffsets = true; - AbsoluteEHSectionOffsets = false; SupportsDebugInformation = true; DwarfSectionOffsetDirective = "\t.secrel32\t"; HasMicrosoftFastStdCallMangling = true; diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index 7a23aecf2970..2c7e1c4c90d1 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -68,6 +68,9 @@ public: /// isVerboseAsm - Return true if this streamer supports verbose assembly at /// all. virtual bool isVerboseAsm() const { return IsVerboseAsm; } + + /// hasRawTextSupport - We support EmitRawText. + virtual bool hasRawTextSupport() const { return true; } /// AddComment - Add a comment that can be emitted to the generated .s /// file if applicable as a QoI issue to make the output of the compiler @@ -145,6 +148,11 @@ public: virtual void EmitInstruction(const MCInst &Inst); + /// EmitRawText - If this file is backed by a assembly streamer, this dumps + /// the specified string in the output .s file. This capability is + /// indicated by the hasRawTextSupport() predicate. + virtual void EmitRawText(StringRef String); + virtual void Finish(); /// @} @@ -195,7 +203,6 @@ void MCAsmStreamer::EmitCommentsAndEOL() { CommentStream.resync(); } - static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) { assert(Bytes && "Invalid size!"); return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8)); @@ -628,12 +635,22 @@ void MCAsmStreamer::EmitInstruction(const MCInst &Inst) { // If we have an AsmPrinter, use that to print, otherwise print the MCInst. if (InstPrinter) - InstPrinter->printInst(&Inst); + InstPrinter->printInst(&Inst, OS); else Inst.print(OS, &MAI); EmitEOL(); } +/// EmitRawText - If this file is backed by a assembly streamer, this dumps +/// the specified string in the output .s file. This capability is +/// indicated by the hasRawTextSupport() predicate. +void MCAsmStreamer::EmitRawText(StringRef String) { + if (!String.empty() && String.back() == '\n') + String = String.substr(0, String.size()-1); + OS << String; + EmitEOL(); +} + void MCAsmStreamer::Finish() { OS.flush(); } diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 24616b40b8e3..4e62689c51ee 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -138,7 +138,7 @@ const AsmToken &AsmParser::Lex() { return *tok; } -bool AsmParser::Run(bool NoInitialTextSection) { +bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { // Create the initial section, if requested. // // FIXME: Target hook & command line option for initial section. @@ -190,7 +190,9 @@ bool AsmParser::Run(bool NoInitialTextSection) { TheCondState.Ignore != StartingCondState.Ignore) return TokError("unmatched .ifs or .elses"); - if (!HadError) + // Finalize the output stream if there are no errors and if the client wants + // us to. + if (!HadError && !NoFinalize) Out.Finish(); return HadError; diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index 703acc4e5991..4f484a27d320 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -10,6 +10,9 @@ #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCExpr.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" +#include <cstdlib> using namespace llvm; MCStreamer::MCStreamer(MCContext &_Context) : Context(_Context), CurSection(0) { @@ -44,3 +47,18 @@ void MCStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue, for (uint64_t i = 0, e = NumBytes; i != e; ++i) EmitValue(E, 1, AddrSpace); } + +/// EmitRawText - If this file is backed by a assembly streamer, this dumps +/// the specified string in the output .s file. This capability is +/// indicated by the hasRawTextSupport() predicate. +void MCStreamer::EmitRawText(StringRef String) { + errs() << "EmitRawText called on an MCStreamer that doesn't support it, " + " something must not be fully mc'ized\n"; + abort(); +} + +void MCStreamer::EmitRawText(const Twine &T) { + SmallString<128> Str; + T.toVector(Str); + EmitRawText(Str.str()); +} diff --git a/lib/Support/MemoryBuffer.cpp b/lib/Support/MemoryBuffer.cpp index 4f135ead182c..2b95089b5246 100644 --- a/lib/Support/MemoryBuffer.cpp +++ b/lib/Support/MemoryBuffer.cpp @@ -71,13 +71,12 @@ namespace { class MemoryBufferMem : public MemoryBuffer { std::string FileID; public: - MemoryBufferMem(const char *Start, const char *End, StringRef FID, - bool Copy = false) + MemoryBufferMem(StringRef InputData, StringRef FID, bool Copy = false) : FileID(FID) { if (!Copy) - init(Start, End); + init(InputData.data(), InputData.data()+InputData.size()); else - initCopyOf(Start, End); + initCopyOf(InputData.data(), InputData.data()+InputData.size()); } virtual const char *getBufferIdentifier() const { @@ -88,19 +87,17 @@ public: /// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note /// that EndPtr[0] must be a null byte and be accessible! -MemoryBuffer *MemoryBuffer::getMemBuffer(const char *StartPtr, - const char *EndPtr, +MemoryBuffer *MemoryBuffer::getMemBuffer(StringRef InputData, const char *BufferName) { - return new MemoryBufferMem(StartPtr, EndPtr, BufferName); + return new MemoryBufferMem(InputData, BufferName); } /// getMemBufferCopy - Open the specified memory range as a MemoryBuffer, /// copying the contents and taking ownership of it. This has no requirements /// on EndPtr[0]. -MemoryBuffer *MemoryBuffer::getMemBufferCopy(const char *StartPtr, - const char *EndPtr, +MemoryBuffer *MemoryBuffer::getMemBufferCopy(StringRef InputData, const char *BufferName) { - return new MemoryBufferMem(StartPtr, EndPtr, BufferName, true); + return new MemoryBufferMem(InputData, BufferName, true); } /// getNewUninitMemBuffer - Allocate a new MemoryBuffer of the specified size @@ -112,7 +109,7 @@ MemoryBuffer *MemoryBuffer::getNewUninitMemBuffer(size_t Size, char *Buf = (char *)malloc(Size+1); if (!Buf) return 0; Buf[Size] = 0; - MemoryBufferMem *SB = new MemoryBufferMem(Buf, Buf+Size, BufferName); + MemoryBufferMem *SB = new MemoryBufferMem(StringRef(Buf, Size), BufferName); // The memory for this buffer is owned by the MemoryBuffer. SB->MustDeleteBuffer = true; return SB; diff --git a/lib/Support/SourceMgr.cpp b/lib/Support/SourceMgr.cpp index 83c7964ca00c..4e7520c9d339 100644 --- a/lib/Support/SourceMgr.cpp +++ b/lib/Support/SourceMgr.cpp @@ -168,13 +168,21 @@ SMDiagnostic SourceMgr::GetMessage(SMLoc Loc, const std::string &Msg, } PrintedMsg += Msg; - return SMDiagnostic(CurMB->getBufferIdentifier(), FindLineNumber(Loc, CurBuf), + return SMDiagnostic(Loc, + CurMB->getBufferIdentifier(), FindLineNumber(Loc, CurBuf), Loc.getPointer()-LineStart, PrintedMsg, LineStr, ShowLine); } void SourceMgr::PrintMessage(SMLoc Loc, const std::string &Msg, const char *Type, bool ShowLine) const { + // Report the message with the diagnostic handler if present. + if (DiagHandler) { + DiagHandler(GetMessage(Loc, Msg, Type, ShowLine), + DiagContext, DiagLocCookie); + return; + } + raw_ostream &OS = errs(); int CurBuf = FindBufferContainingLoc(Loc); diff --git a/lib/Support/regengine.inc b/lib/Support/regengine.inc index 0f27cfd4b5b8..bf55543dab8a 100644 --- a/lib/Support/regengine.inc +++ b/lib/Support/regengine.inc @@ -72,11 +72,11 @@ struct match { struct re_guts *g; int eflags; llvm_regmatch_t *pmatch; /* [nsub+1] (0 element unused) */ - char *offp; /* offsets work from here */ - char *beginp; /* start of string -- virtual NUL precedes */ - char *endp; /* end of string -- virtual NUL here */ - char *coldp; /* can be no match starting before here */ - char **lastpos; /* [nplus+1] */ + const char *offp; /* offsets work from here */ + const char *beginp; /* start of string -- virtual NUL precedes */ + const char *endp; /* end of string -- virtual NUL here */ + const char *coldp; /* can be no match starting before here */ + const char **lastpos; /* [nplus+1] */ STATEVARS; states st; /* current states */ states fresh; /* states for a fresh start */ @@ -84,11 +84,14 @@ struct match { states empty; /* empty set of states */ }; -static int matcher(struct re_guts *, char *, size_t, llvm_regmatch_t[], int); -static char *dissect(struct match *, char *, char *, sopno, sopno); -static char *backref(struct match *, char *, char *, sopno, sopno, sopno, int); -static char *fast(struct match *, char *, char *, sopno, sopno); -static char *slow(struct match *, char *, char *, sopno, sopno); +static int matcher(struct re_guts *, const char *, size_t, + llvm_regmatch_t[], int); +static const char *dissect(struct match *, const char *, const char *, sopno, + sopno); +static const char *backref(struct match *, const char *, const char *, sopno, + sopno, sopno, int); +static const char *fast(struct match *, const char *, const char *, sopno, sopno); +static const char *slow(struct match *, const char *, const char *, sopno, sopno); static states step(struct re_guts *, sopno, sopno, states, int, states); #define MAX_RECURSION 100 #define BOL (OUT+1) @@ -125,18 +128,19 @@ static int nope = 0; - matcher - the actual matching engine */ static int /* 0 success, REG_NOMATCH failure */ -matcher(struct re_guts *g, char *string, size_t nmatch, llvm_regmatch_t pmatch[], +matcher(struct re_guts *g, const char *string, size_t nmatch, + llvm_regmatch_t pmatch[], int eflags) { - char *endp; + const char *endp; size_t i; struct match mv; struct match *m = &mv; - char *dp; + const char *dp; const sopno gf = g->firststate+1; /* +1 for OEND */ const sopno gl = g->laststate; - char *start; - char *stop; + const char *start; + const char *stop; /* simplify the situation where possible */ if (g->cflags®_NOSUB) @@ -216,7 +220,7 @@ matcher(struct re_guts *g, char *string, size_t nmatch, llvm_regmatch_t pmatch[] dp = dissect(m, m->coldp, endp, gf, gl); } else { if (g->nplus > 0 && m->lastpos == NULL) - m->lastpos = (char **)malloc((g->nplus+1) * + m->lastpos = (const char **)malloc((g->nplus+1) * sizeof(char *)); if (g->nplus > 0 && m->lastpos == NULL) { free(m->pmatch); @@ -287,21 +291,22 @@ matcher(struct re_guts *g, char *string, size_t nmatch, llvm_regmatch_t pmatch[] /* - dissect - figure out what matched what, no back references */ -static char * /* == stop (success) always */ -dissect(struct match *m, char *start, char *stop, sopno startst, sopno stopst) +static const char * /* == stop (success) always */ +dissect(struct match *m, const char *start, const char *stop, sopno startst, + sopno stopst) { int i; sopno ss; /* start sop of current subRE */ sopno es; /* end sop of current subRE */ - char *sp; /* start of string matched by it */ - char *stp; /* string matched by it cannot pass here */ - char *rest; /* start of rest of string */ - char *tail; /* string unmatched by rest of RE */ + const char *sp; /* start of string matched by it */ + const char *stp; /* string matched by it cannot pass here */ + const char *rest; /* start of rest of string */ + const char *tail; /* string unmatched by rest of RE */ sopno ssub; /* start sop of subsubRE */ sopno esub; /* end sop of subsubRE */ - char *ssp; /* start of string matched by subsubRE */ - char *sep; /* end of string matched by subsubRE */ - char *oldssp; /* previous ssp */ + const char *ssp; /* start of string matched by subsubRE */ + const char *sep; /* end of string matched by subsubRE */ + const char *oldssp; /* previous ssp */ AT("diss", start, stop, startst, stopst); sp = start; @@ -360,7 +365,7 @@ dissect(struct match *m, char *start, char *stop, sopno startst, sopno stopst) esub = es - 1; /* did innards match? */ if (slow(m, sp, rest, ssub, esub) != NULL) { - char *dp = dissect(m, sp, rest, ssub, esub); + const char *dp = dissect(m, sp, rest, ssub, esub); (void)dp; /* avoid warning if assertions off */ assert(dp == rest); } else /* no */ @@ -400,7 +405,7 @@ dissect(struct match *m, char *start, char *stop, sopno startst, sopno stopst) assert(sep == rest); /* must exhaust substring */ assert(slow(m, ssp, sep, ssub, esub) == rest); { - char *dp = dissect(m, ssp, sep, ssub, esub); + const char *dp = dissect(m, ssp, sep, ssub, esub); (void)dp; /* avoid warning if assertions off */ assert(dp == sep); } @@ -438,7 +443,7 @@ dissect(struct match *m, char *start, char *stop, sopno startst, sopno stopst) assert(OP(m->g->strip[esub]) == O_CH); } { - char *dp = dissect(m, sp, rest, ssub, esub); + const char *dp = dissect(m, sp, rest, ssub, esub); (void)dp; /* avoid warning if assertions off */ assert(dp == rest); } @@ -474,17 +479,17 @@ dissect(struct match *m, char *start, char *stop, sopno startst, sopno stopst) /* - backref - figure out what matched what, figuring in back references */ -static char * /* == stop (success) or NULL (failure) */ -backref(struct match *m, char *start, char *stop, sopno startst, sopno stopst, - sopno lev, int rec) /* PLUS nesting level */ +static const char * /* == stop (success) or NULL (failure) */ +backref(struct match *m, const char *start, const char *stop, sopno startst, + sopno stopst, sopno lev, int rec) /* PLUS nesting level */ { int i; sopno ss; /* start sop of current subRE */ - char *sp; /* start of string matched by it */ + const char *sp; /* start of string matched by it */ sopno ssub; /* start sop of subsubRE */ sopno esub; /* end sop of subsubRE */ - char *ssp; /* start of string matched by subsubRE */ - char *dp; + const char *ssp; /* start of string matched by subsubRE */ + const char *dp; size_t len; int hard; sop s; @@ -674,18 +679,19 @@ backref(struct match *m, char *start, char *stop, sopno startst, sopno stopst, /* - fast - step through the string at top speed */ -static char * /* where tentative match ended, or NULL */ -fast(struct match *m, char *start, char *stop, sopno startst, sopno stopst) +static const char * /* where tentative match ended, or NULL */ +fast(struct match *m, const char *start, const char *stop, sopno startst, + sopno stopst) { states st = m->st; states fresh = m->fresh; states tmp = m->tmp; - char *p = start; + const char *p = start; int c = (start == m->beginp) ? OUT : *(start-1); int lastc; /* previous c */ int flagch; int i; - char *coldp; /* last p after which no match was underway */ + const char *coldp; /* last p after which no match was underway */ CLEAR(st); SET1(st, startst); @@ -758,18 +764,19 @@ fast(struct match *m, char *start, char *stop, sopno startst, sopno stopst) /* - slow - step through the string more deliberately */ -static char * /* where it ended */ -slow(struct match *m, char *start, char *stop, sopno startst, sopno stopst) +static const char * /* where it ended */ +slow(struct match *m, const char *start, const char *stop, sopno startst, + sopno stopst) { states st = m->st; states empty = m->empty; states tmp = m->tmp; - char *p = start; + const char *p = start; int c = (start == m->beginp) ? OUT : *(start-1); int lastc; /* previous c */ int flagch; int i; - char *matchp; /* last p at which a match ended */ + const char *matchp; /* last p at which a match ended */ AT("slow", start, stop, startst, stopst); CLEAR(st); diff --git a/lib/Support/regexec.c b/lib/Support/regexec.c index 7d70f6e16c78..41fb2ea46c9a 100644 --- a/lib/Support/regexec.c +++ b/lib/Support/regexec.c @@ -155,7 +155,7 @@ llvm_regexec(const llvm_regex_t *preg, const char *string, size_t nmatch, eflags = GOODFLAGS(eflags); if (g->nstates <= (long)(CHAR_BIT*sizeof(states1)) && !(eflags®_LARGE)) - return(smatcher(g, (char *)string, nmatch, pmatch, eflags)); + return(smatcher(g, string, nmatch, pmatch, eflags)); else - return(lmatcher(g, (char *)string, nmatch, pmatch, eflags)); + return(lmatcher(g, string, nmatch, pmatch, eflags)); } diff --git a/lib/Target/ARM/ARM.td b/lib/Target/ARM/ARM.td index 6486a608e46d..8d9c62253cdd 100644 --- a/lib/Target/ARM/ARM.td +++ b/lib/Target/ARM/ARM.td @@ -140,23 +140,7 @@ include "ARMCallingConv.td" include "ARMInstrInfo.td" -def ARMInstrInfo : InstrInfo { - // Define how we want to layout our target-specific information field. - let TSFlagsFields = ["AddrModeBits", - "SizeFlag", - "IndexModeBits", - "Form", - "isUnaryDataProc", - "canXformTo16Bit", - "Dom"]; - let TSFlagsShifts = [0, - 4, - 7, - 9, - 15, - 16, - 17]; -} +def ARMInstrInfo : InstrInfo; //===----------------------------------------------------------------------===// // Declare the target which we are implementing diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index b6c81f6910aa..77fb0c3cdbd0 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -861,7 +861,8 @@ CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain, DebugLoc dl) { SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), MVT::i32); return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getByValAlign(), - /*AlwaysInline=*/false, NULL, 0, NULL, 0); + /*isVolatile=*/false, /*AlwaysInline=*/false, + NULL, 0, NULL, 0); } /// LowerMemOpCallTo - Store the argument to the stack. @@ -2053,7 +2054,7 @@ ARMTargetLowering::EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, SDValue Chain, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, - bool AlwaysInline, + bool isVolatile, bool AlwaysInline, const Value *DstSV, uint64_t DstSVOff, const Value *SrcSV, uint64_t SrcSVOff){ // Do repeated 4-byte loads and stores. To be improved. @@ -2089,7 +2090,7 @@ ARMTargetLowering::EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, Loads[i] = DAG.getLoad(VT, dl, Chain, DAG.getNode(ISD::ADD, dl, MVT::i32, Src, DAG.getConstant(SrcOff, MVT::i32)), - SrcSV, SrcSVOff + SrcOff, false, false, 0); + SrcSV, SrcSVOff + SrcOff, isVolatile, false, 0); TFOps[i] = Loads[i].getValue(1); SrcOff += VTSize; } @@ -2100,7 +2101,7 @@ ARMTargetLowering::EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, TFOps[i] = DAG.getStore(Chain, dl, Loads[i], DAG.getNode(ISD::ADD, dl, MVT::i32, Dst, DAG.getConstant(DstOff, MVT::i32)), - DstSV, DstSVOff + DstOff, false, false, 0); + DstSV, DstSVOff + DstOff, isVolatile, false, 0); DstOff += VTSize; } Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i); diff --git a/lib/Target/ARM/ARMISelLowering.h b/lib/Target/ARM/ARMISelLowering.h index f8f8adc70af8..fa33ad307506 100644 --- a/lib/Target/ARM/ARMISelLowering.h +++ b/lib/Target/ARM/ARMISelLowering.h @@ -305,7 +305,7 @@ namespace llvm { SDValue Chain, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, - bool AlwaysInline, + bool isVolatile, bool AlwaysInline, const Value *DstSV, uint64_t DstSVOff, const Value *SrcSV, uint64_t SrcSVOff); SDValue LowerCallResult(SDValue Chain, SDValue InFlag, diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td index 4427e50bbdb1..b466d0dd994e 100644 --- a/lib/Target/ARM/ARMInstrFormats.td +++ b/lib/Target/ARM/ARMInstrFormats.td @@ -185,28 +185,25 @@ class InstTemplate<AddrMode am, SizeFlagVal sz, IndexMode im, : Instruction { let Namespace = "ARM"; - // TSFlagsFields AddrMode AM = am; - bits<4> AddrModeBits = AM.Value; - SizeFlagVal SZ = sz; - bits<3> SizeFlag = SZ.Value; - IndexMode IM = im; bits<2> IndexModeBits = IM.Value; - Format F = f; bits<6> Form = F.Value; - Domain D = d; - bits<2> Dom = D.Value; - - // - // Attributes specific to ARM instructions... - // bit isUnaryDataProc = 0; bit canXformTo16Bit = 0; + // The layout of TSFlags should be kept in sync with ARMBaseInstrInfo.h. + let TSFlags{3-0} = AM.Value; + let TSFlags{6-4} = SZ.Value; + let TSFlags{8-7} = IndexModeBits; + let TSFlags{14-9} = Form; + let TSFlags{15} = isUnaryDataProc; + let TSFlags{16} = canXformTo16Bit; + let TSFlags{18-17} = D.Value; + let Constraints = cstr; let Itinerary = itin; } @@ -1317,7 +1314,7 @@ class ADI5<bits<4> opcod1, bits<2> opcod2, dag oops, dag iops, let Inst{11-8} = 0b1011; // 64-bit loads & stores operate on both NEON and VFP pipelines. - let Dom = VFPNeonDomain.Value; + let D = VFPNeonDomain; } class ASI5<bits<4> opcod1, bits<2> opcod2, dag oops, dag iops, @@ -1341,7 +1338,7 @@ class AXDI5<dag oops, dag iops, IndexMode im, InstrItinClass itin, let Inst{11-8} = 0b1011; // 64-bit loads & stores operate on both NEON and VFP pipelines. - let Dom = VFPNeonDomain.Value; + let D = VFPNeonDomain; } class AXSI5<dag oops, dag iops, IndexMode im, InstrItinClass itin, diff --git a/lib/Target/ARM/ARMMCAsmInfo.cpp b/lib/Target/ARM/ARMMCAsmInfo.cpp index 20197e487d31..53edfcad9308 100644 --- a/lib/Target/ARM/ARMMCAsmInfo.cpp +++ b/lib/Target/ARM/ARMMCAsmInfo.cpp @@ -58,7 +58,6 @@ ARMELFMCAsmInfo::ARMELFMCAsmInfo() { CommentString = "@"; HasLEB128 = true; - AbsoluteDebugSectionOffsets = true; PrivateGlobalPrefix = ".L"; WeakRefDirective = "\t.weak\t"; HasLCOMMDirective = true; diff --git a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp index ba736e3c0777..15c52946cf58 100644 --- a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp @@ -26,7 +26,6 @@ #include "llvm/Type.h" #include "llvm/Assembly/Writer.h" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/DwarfWriter.h" #include "llvm/CodeGen/MachineModuleInfoImpls.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" @@ -46,11 +45,9 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringSet.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" #include <cctype> using namespace llvm; @@ -74,9 +71,8 @@ namespace { const MachineConstantPool *MCP; public: - explicit ARMAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, - MCStreamer &Streamer) - : AsmPrinter(O, TM, Streamer), AFI(NULL), MCP(NULL) { + explicit ARMAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : AsmPrinter(TM, Streamer), AFI(NULL), MCP(NULL) { Subtarget = &TM.getSubtarget<ARMSubtarget>(); } @@ -87,80 +83,123 @@ namespace { void printInstructionThroughMCStreamer(const MachineInstr *MI); - void printOperand(const MachineInstr *MI, int OpNum, + void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O, const char *Modifier = 0); - void printSOImmOperand(const MachineInstr *MI, int OpNum); - void printSOImm2PartOperand(const MachineInstr *MI, int OpNum); - void printSORegOperand(const MachineInstr *MI, int OpNum); - void printAddrMode2Operand(const MachineInstr *MI, int OpNum); - void printAddrMode2OffsetOperand(const MachineInstr *MI, int OpNum); - void printAddrMode3Operand(const MachineInstr *MI, int OpNum); - void printAddrMode3OffsetOperand(const MachineInstr *MI, int OpNum); - void printAddrMode4Operand(const MachineInstr *MI, int OpNum, + void printSOImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O); + void printSOImm2PartOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O); + void printSORegOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O); + void printAddrMode2Operand(const MachineInstr *MI, int OpNum, + raw_ostream &O); + void printAddrMode2OffsetOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O); + void printAddrMode3Operand(const MachineInstr *MI, int OpNum, + raw_ostream &O); + void printAddrMode3OffsetOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O); + void printAddrMode4Operand(const MachineInstr *MI, int OpNum,raw_ostream &O, const char *Modifier = 0); - void printAddrMode5Operand(const MachineInstr *MI, int OpNum, + void printAddrMode5Operand(const MachineInstr *MI, int OpNum,raw_ostream &O, const char *Modifier = 0); - void printAddrMode6Operand(const MachineInstr *MI, int OpNum); - void printAddrMode6OffsetOperand(const MachineInstr *MI, int OpNum); + void printAddrMode6Operand(const MachineInstr *MI, int OpNum, + raw_ostream &O); + void printAddrMode6OffsetOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O); void printAddrModePCOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O, const char *Modifier = 0); - void printBitfieldInvMaskImmOperand (const MachineInstr *MI, int OpNum); - - void printThumbS4ImmOperand(const MachineInstr *MI, int OpNum); - void printThumbITMask(const MachineInstr *MI, int OpNum); - void printThumbAddrModeRROperand(const MachineInstr *MI, int OpNum); + void printBitfieldInvMaskImmOperand (const MachineInstr *MI, int OpNum, + raw_ostream &O); + + void printThumbS4ImmOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O); + void printThumbITMask(const MachineInstr *MI, int OpNum, raw_ostream &O); + void printThumbAddrModeRROperand(const MachineInstr *MI, int OpNum, + raw_ostream &O); void printThumbAddrModeRI5Operand(const MachineInstr *MI, int OpNum, + raw_ostream &O, unsigned Scale); - void printThumbAddrModeS1Operand(const MachineInstr *MI, int OpNum); - void printThumbAddrModeS2Operand(const MachineInstr *MI, int OpNum); - void printThumbAddrModeS4Operand(const MachineInstr *MI, int OpNum); - void printThumbAddrModeSPOperand(const MachineInstr *MI, int OpNum); - - void printT2SOOperand(const MachineInstr *MI, int OpNum); - void printT2AddrModeImm12Operand(const MachineInstr *MI, int OpNum); - void printT2AddrModeImm8Operand(const MachineInstr *MI, int OpNum); - void printT2AddrModeImm8s4Operand(const MachineInstr *MI, int OpNum); - void printT2AddrModeImm8OffsetOperand(const MachineInstr *MI, int OpNum); - void printT2AddrModeImm8s4OffsetOperand(const MachineInstr *MI, int OpNum) {} - void printT2AddrModeSoRegOperand(const MachineInstr *MI, int OpNum); - - void printCPSOptionOperand(const MachineInstr *MI, int OpNum) {} - void printMSRMaskOperand(const MachineInstr *MI, int OpNum) {} - void printNegZeroOperand(const MachineInstr *MI, int OpNum) {} - void printPredicateOperand(const MachineInstr *MI, int OpNum); - void printMandatoryPredicateOperand(const MachineInstr *MI, int OpNum); - void printSBitModifierOperand(const MachineInstr *MI, int OpNum); - void printPCLabel(const MachineInstr *MI, int OpNum); - void printRegisterList(const MachineInstr *MI, int OpNum); + void printThumbAddrModeS1Operand(const MachineInstr *MI, int OpNum, + raw_ostream &O); + void printThumbAddrModeS2Operand(const MachineInstr *MI, int OpNum, + raw_ostream &O); + void printThumbAddrModeS4Operand(const MachineInstr *MI, int OpNum, + raw_ostream &O); + void printThumbAddrModeSPOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O); + + void printT2SOOperand(const MachineInstr *MI, int OpNum, raw_ostream &O); + void printT2AddrModeImm12Operand(const MachineInstr *MI, int OpNum, + raw_ostream &O); + void printT2AddrModeImm8Operand(const MachineInstr *MI, int OpNum, + raw_ostream &O); + void printT2AddrModeImm8s4Operand(const MachineInstr *MI, int OpNum, + raw_ostream &O); + void printT2AddrModeImm8OffsetOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O); + void printT2AddrModeImm8s4OffsetOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O) {} + void printT2AddrModeSoRegOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O); + + void printCPSOptionOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O) {} + void printMSRMaskOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O) {} + void printNegZeroOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O) {} + void printPredicateOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O); + void printMandatoryPredicateOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O); + void printSBitModifierOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O); + void printPCLabel(const MachineInstr *MI, int OpNum, + raw_ostream &O); + void printRegisterList(const MachineInstr *MI, int OpNum, + raw_ostream &O); void printCPInstOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O, const char *Modifier); - void printJTBlockOperand(const MachineInstr *MI, int OpNum); - void printJT2BlockOperand(const MachineInstr *MI, int OpNum); - void printTBAddrMode(const MachineInstr *MI, int OpNum); - void printNoHashImmediate(const MachineInstr *MI, int OpNum); - void printVFPf32ImmOperand(const MachineInstr *MI, int OpNum); - void printVFPf64ImmOperand(const MachineInstr *MI, int OpNum); - - void printHex8ImmOperand(const MachineInstr *MI, int OpNum) { + void printJTBlockOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O); + void printJT2BlockOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O); + void printTBAddrMode(const MachineInstr *MI, int OpNum, + raw_ostream &O); + void printNoHashImmediate(const MachineInstr *MI, int OpNum, + raw_ostream &O); + void printVFPf32ImmOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O); + void printVFPf64ImmOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O); + + void printHex8ImmOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O) { O << "#0x" << utohexstr(MI->getOperand(OpNum).getImm() & 0xff); } - void printHex16ImmOperand(const MachineInstr *MI, int OpNum) { + void printHex16ImmOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O) { O << "#0x" << utohexstr(MI->getOperand(OpNum).getImm() & 0xffff); } - void printHex32ImmOperand(const MachineInstr *MI, int OpNum) { + void printHex32ImmOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O) { O << "#0x" << utohexstr(MI->getOperand(OpNum).getImm() & 0xffffffff); } - void printHex64ImmOperand(const MachineInstr *MI, int OpNum) { + void printHex64ImmOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O) { O << "#0x" << utohexstr(MI->getOperand(OpNum).getImm()); } virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, - unsigned AsmVariant, const char *ExtraCode); + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, unsigned AsmVariant, - const char *ExtraCode); + const char *ExtraCode, raw_ostream &O); - void printInstruction(const MachineInstr *MI); // autogenerated. + void printInstruction(const MachineInstr *MI, raw_ostream &O); // autogen static const char *getRegisterName(unsigned RegNo); virtual void EmitInstruction(const MachineInstr *MI); @@ -178,6 +217,14 @@ namespace { /// EmitMachineConstantPoolValue - Print a machine constantpool value to /// the .s file. virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { + SmallString<128> Str; + raw_svector_ostream OS(Str); + EmitMachineConstantPoolValue(MCPV, OS); + OutStreamer.EmitRawText(OS.str()); + } + + void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV, + raw_ostream &O) { switch (TM.getTargetData()->getTypeAllocSize(MCPV->getType())) { case 1: O << MAI->getData8bitsDirective(0); break; case 2: O << MAI->getData16bitsDirective(0); break; @@ -186,14 +233,11 @@ namespace { } ARMConstantPoolValue *ACPV = static_cast<ARMConstantPoolValue*>(MCPV); - SmallString<128> TmpNameStr; if (ACPV->isLSDA()) { - raw_svector_ostream(TmpNameStr) << MAI->getPrivateGlobalPrefix() << - "_LSDA_" << getFunctionNumber(); - O << TmpNameStr.str(); + O << MAI->getPrivateGlobalPrefix() << "_LSDA_" << getFunctionNumber(); } else if (ACPV->isBlockAddress()) { - O << GetBlockAddressSymbol(ACPV->getBlockAddress())->getName(); + O << *GetBlockAddressSymbol(ACPV->getBlockAddress()); } else if (ACPV->isGlobalValue()) { GlobalValue *GV = ACPV->getGV(); bool isIndirect = Subtarget->isTargetDarwin() && @@ -228,14 +272,6 @@ namespace { O << "-."; O << ')'; } - OutStreamer.AddBlankLine(); - } - - void getAnalysisUsage(AnalysisUsage &AU) const { - AsmPrinter::getAnalysisUsage(AU); - AU.setPreservesAll(); - AU.addRequired<MachineModuleInfo>(); - AU.addRequired<DwarfWriter>(); } }; } // end of anonymous namespace @@ -244,11 +280,17 @@ namespace { void ARMAsmPrinter::EmitFunctionEntryLabel() { if (AFI->isThumbFunction()) { - O << "\t.code\t16\n"; - O << "\t.thumb_func"; - if (Subtarget->isTargetDarwin()) - O << '\t' << *CurrentFnSym; - O << '\n'; + OutStreamer.EmitRawText(StringRef("\t.code\t16")); + if (!Subtarget->isTargetDarwin()) + OutStreamer.EmitRawText(StringRef("\t.thumb_func")); + else { + // This needs to emit to a temporary string to get properly quoted + // MCSymbols when they have spaces in them. + SmallString<128> Tmp; + raw_svector_ostream OS(Tmp); + OS << "\t.thumb_func\t" << *CurrentFnSym; + OutStreamer.EmitRawText(OS.str()); + } } OutStreamer.EmitLabel(CurrentFnSym); @@ -265,7 +307,7 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { } void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, - const char *Modifier) { + raw_ostream &O, const char *Modifier) { const MachineOperand &MO = MI->getOperand(OpNum); unsigned TF = MO.getTargetFlags(); @@ -276,15 +318,16 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, unsigned Reg = MO.getReg(); assert(TargetRegisterInfo::isPhysicalRegister(Reg)); if (Modifier && strcmp(Modifier, "dregpair") == 0) { - unsigned DRegLo = TRI->getSubReg(Reg, 5); // arm_dsubreg_0 - unsigned DRegHi = TRI->getSubReg(Reg, 6); // arm_dsubreg_1 + unsigned DRegLo = TM.getRegisterInfo()->getSubReg(Reg, 5);// arm_dsubreg_0 + unsigned DRegHi = TM.getRegisterInfo()->getSubReg(Reg, 6);// arm_dsubreg_1 O << '{' << getRegisterName(DRegLo) << ',' << getRegisterName(DRegHi) << '}'; } else if (Modifier && strcmp(Modifier, "lane") == 0) { unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(Reg); - unsigned DReg = TRI->getMatchingSuperReg(Reg, RegNum & 1 ? 2 : 1, - &ARM::DPR_VFP2RegClass); + unsigned DReg = + TM.getRegisterInfo()->getMatchingSuperReg(Reg, RegNum & 1 ? 2 : 1, + &ARM::DPR_VFP2RegClass); O << getRegisterName(DReg) << '[' << (RegNum & 1) << ']'; } else { assert(!MO.getSubReg() && "Subregs should be eliminated!"); @@ -319,7 +362,7 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, O << ":upper16:"; O << *Mang->getSymbol(GV); - printOffset(MO.getOffset()); + printOffset(MO.getOffset(), O); if (isCallOp && Subtarget->isTargetELF() && TM.getRelocationModel() == Reloc::PIC_) @@ -344,7 +387,7 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, } } -static void printSOImm(formatted_raw_ostream &O, int64_t V, bool VerboseAsm, +static void printSOImm(raw_ostream &O, int64_t V, bool VerboseAsm, const MCAsmInfo *MAI) { // Break it up into two parts that make up a shifter immediate. V = ARM_AM::getSOImmVal(V); @@ -359,8 +402,7 @@ static void printSOImm(formatted_raw_ostream &O, int64_t V, bool VerboseAsm, O << "#" << Imm << ", " << Rot; // Pretty printed version. if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << ' '; + O << "\t" << MAI->getCommentString() << ' '; O << (int)ARM_AM::rotr32(Imm, Rot); } } else { @@ -370,28 +412,30 @@ static void printSOImm(formatted_raw_ostream &O, int64_t V, bool VerboseAsm, /// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit /// immediate in bits 0-7. -void ARMAsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum) { +void ARMAsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O) { const MachineOperand &MO = MI->getOperand(OpNum); assert(MO.isImm() && "Not a valid so_imm value!"); - printSOImm(O, MO.getImm(), VerboseAsm, MAI); + printSOImm(O, MO.getImm(), isVerbose(), MAI); } /// printSOImm2PartOperand - SOImm is broken into two pieces using a 'mov' /// followed by an 'orr' to materialize. -void ARMAsmPrinter::printSOImm2PartOperand(const MachineInstr *MI, int OpNum) { +void ARMAsmPrinter::printSOImm2PartOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O) { const MachineOperand &MO = MI->getOperand(OpNum); assert(MO.isImm() && "Not a valid so_imm value!"); unsigned V1 = ARM_AM::getSOImmTwoPartFirst(MO.getImm()); unsigned V2 = ARM_AM::getSOImmTwoPartSecond(MO.getImm()); - printSOImm(O, V1, VerboseAsm, MAI); + printSOImm(O, V1, isVerbose(), MAI); O << "\n\torr"; - printPredicateOperand(MI, 2); + printPredicateOperand(MI, 2, O); O << "\t"; - printOperand(MI, 0); + printOperand(MI, 0, O); O << ", "; - printOperand(MI, 0); + printOperand(MI, 0, O); O << ", "; - printSOImm(O, V2, VerboseAsm, MAI); + printSOImm(O, V2, isVerbose(), MAI); } // so_reg is a 4-operand unit corresponding to register forms of the A5.1 @@ -399,7 +443,8 @@ void ARMAsmPrinter::printSOImm2PartOperand(const MachineInstr *MI, int OpNum) { // REG 0 0 - e.g. R5 // REG REG 0,SH_OPC - e.g. R5, ROR R3 // REG 0 IMM,SH_OPC - e.g. R5, LSL #3 -void ARMAsmPrinter::printSORegOperand(const MachineInstr *MI, int Op) { +void ARMAsmPrinter::printSORegOperand(const MachineInstr *MI, int Op, + raw_ostream &O) { const MachineOperand &MO1 = MI->getOperand(Op); const MachineOperand &MO2 = MI->getOperand(Op+1); const MachineOperand &MO3 = MI->getOperand(Op+2); @@ -419,13 +464,14 @@ void ARMAsmPrinter::printSORegOperand(const MachineInstr *MI, int Op) { } } -void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr *MI, int Op) { +void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr *MI, int Op, + raw_ostream &O) { const MachineOperand &MO1 = MI->getOperand(Op); const MachineOperand &MO2 = MI->getOperand(Op+1); const MachineOperand &MO3 = MI->getOperand(Op+2); if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. - printOperand(MI, Op); + printOperand(MI, Op, O); return; } @@ -451,7 +497,8 @@ void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr *MI, int Op) { O << "]"; } -void ARMAsmPrinter::printAddrMode2OffsetOperand(const MachineInstr *MI, int Op){ +void ARMAsmPrinter::printAddrMode2OffsetOperand(const MachineInstr *MI, int Op, + raw_ostream &O) { const MachineOperand &MO1 = MI->getOperand(Op); const MachineOperand &MO2 = MI->getOperand(Op+1); @@ -473,7 +520,8 @@ void ARMAsmPrinter::printAddrMode2OffsetOperand(const MachineInstr *MI, int Op){ << " #" << ShImm; } -void ARMAsmPrinter::printAddrMode3Operand(const MachineInstr *MI, int Op) { +void ARMAsmPrinter::printAddrMode3Operand(const MachineInstr *MI, int Op, + raw_ostream &O) { const MachineOperand &MO1 = MI->getOperand(Op); const MachineOperand &MO2 = MI->getOperand(Op+1); const MachineOperand &MO3 = MI->getOperand(Op+2); @@ -496,7 +544,8 @@ void ARMAsmPrinter::printAddrMode3Operand(const MachineInstr *MI, int Op) { O << "]"; } -void ARMAsmPrinter::printAddrMode3OffsetOperand(const MachineInstr *MI, int Op){ +void ARMAsmPrinter::printAddrMode3OffsetOperand(const MachineInstr *MI, int Op, + raw_ostream &O){ const MachineOperand &MO1 = MI->getOperand(Op); const MachineOperand &MO2 = MI->getOperand(Op+1); @@ -514,6 +563,7 @@ void ARMAsmPrinter::printAddrMode3OffsetOperand(const MachineInstr *MI, int Op){ } void ARMAsmPrinter::printAddrMode4Operand(const MachineInstr *MI, int Op, + raw_ostream &O, const char *Modifier) { const MachineOperand &MO2 = MI->getOperand(Op+1); ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm()); @@ -524,17 +574,18 @@ void ARMAsmPrinter::printAddrMode4Operand(const MachineInstr *MI, int Op, if (Mode == ARM_AM::ia) O << ".w"; } else { - printOperand(MI, Op); + printOperand(MI, Op, O); } } void ARMAsmPrinter::printAddrMode5Operand(const MachineInstr *MI, int Op, + raw_ostream &O, const char *Modifier) { const MachineOperand &MO1 = MI->getOperand(Op); const MachineOperand &MO2 = MI->getOperand(Op+1); if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. - printOperand(MI, Op); + printOperand(MI, Op, O); return; } @@ -560,7 +611,8 @@ void ARMAsmPrinter::printAddrMode5Operand(const MachineInstr *MI, int Op, O << "]"; } -void ARMAsmPrinter::printAddrMode6Operand(const MachineInstr *MI, int Op) { +void ARMAsmPrinter::printAddrMode6Operand(const MachineInstr *MI, int Op, + raw_ostream &O) { const MachineOperand &MO1 = MI->getOperand(Op); const MachineOperand &MO2 = MI->getOperand(Op+1); @@ -572,7 +624,8 @@ void ARMAsmPrinter::printAddrMode6Operand(const MachineInstr *MI, int Op) { O << "]"; } -void ARMAsmPrinter::printAddrMode6OffsetOperand(const MachineInstr *MI, int Op){ +void ARMAsmPrinter::printAddrMode6OffsetOperand(const MachineInstr *MI, int Op, + raw_ostream &O){ const MachineOperand &MO = MI->getOperand(Op); if (MO.getReg() == 0) O << "!"; @@ -581,9 +634,10 @@ void ARMAsmPrinter::printAddrMode6OffsetOperand(const MachineInstr *MI, int Op){ } void ARMAsmPrinter::printAddrModePCOperand(const MachineInstr *MI, int Op, + raw_ostream &O, const char *Modifier) { if (Modifier && strcmp(Modifier, "label") == 0) { - printPCLabel(MI, Op+1); + printPCLabel(MI, Op+1, O); return; } @@ -593,7 +647,8 @@ void ARMAsmPrinter::printAddrModePCOperand(const MachineInstr *MI, int Op, } void -ARMAsmPrinter::printBitfieldInvMaskImmOperand(const MachineInstr *MI, int Op) { +ARMAsmPrinter::printBitfieldInvMaskImmOperand(const MachineInstr *MI, int Op, + raw_ostream &O) { const MachineOperand &MO = MI->getOperand(Op); uint32_t v = ~MO.getImm(); int32_t lsb = CountTrailingZeros_32(v); @@ -604,12 +659,14 @@ ARMAsmPrinter::printBitfieldInvMaskImmOperand(const MachineInstr *MI, int Op) { //===--------------------------------------------------------------------===// -void ARMAsmPrinter::printThumbS4ImmOperand(const MachineInstr *MI, int Op) { +void ARMAsmPrinter::printThumbS4ImmOperand(const MachineInstr *MI, int Op, + raw_ostream &O) { O << "#" << MI->getOperand(Op).getImm() * 4; } void -ARMAsmPrinter::printThumbITMask(const MachineInstr *MI, int Op) { +ARMAsmPrinter::printThumbITMask(const MachineInstr *MI, int Op, + raw_ostream &O) { // (3 - the number of trailing zeros) is the number of then / else. unsigned Mask = MI->getOperand(Op).getImm(); unsigned CondBit0 = Mask >> 4 & 1; @@ -625,7 +682,8 @@ ARMAsmPrinter::printThumbITMask(const MachineInstr *MI, int Op) { } void -ARMAsmPrinter::printThumbAddrModeRROperand(const MachineInstr *MI, int Op) { +ARMAsmPrinter::printThumbAddrModeRROperand(const MachineInstr *MI, int Op, + raw_ostream &O) { const MachineOperand &MO1 = MI->getOperand(Op); const MachineOperand &MO2 = MI->getOperand(Op+1); O << "[" << getRegisterName(MO1.getReg()); @@ -634,13 +692,14 @@ ARMAsmPrinter::printThumbAddrModeRROperand(const MachineInstr *MI, int Op) { void ARMAsmPrinter::printThumbAddrModeRI5Operand(const MachineInstr *MI, int Op, + raw_ostream &O, unsigned Scale) { const MachineOperand &MO1 = MI->getOperand(Op); const MachineOperand &MO2 = MI->getOperand(Op+1); const MachineOperand &MO3 = MI->getOperand(Op+2); if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. - printOperand(MI, Op); + printOperand(MI, Op, O); return; } @@ -653,19 +712,23 @@ ARMAsmPrinter::printThumbAddrModeRI5Operand(const MachineInstr *MI, int Op, } void -ARMAsmPrinter::printThumbAddrModeS1Operand(const MachineInstr *MI, int Op) { - printThumbAddrModeRI5Operand(MI, Op, 1); +ARMAsmPrinter::printThumbAddrModeS1Operand(const MachineInstr *MI, int Op, + raw_ostream &O) { + printThumbAddrModeRI5Operand(MI, Op, O, 1); } void -ARMAsmPrinter::printThumbAddrModeS2Operand(const MachineInstr *MI, int Op) { - printThumbAddrModeRI5Operand(MI, Op, 2); +ARMAsmPrinter::printThumbAddrModeS2Operand(const MachineInstr *MI, int Op, + raw_ostream &O) { + printThumbAddrModeRI5Operand(MI, Op, O, 2); } void -ARMAsmPrinter::printThumbAddrModeS4Operand(const MachineInstr *MI, int Op) { - printThumbAddrModeRI5Operand(MI, Op, 4); +ARMAsmPrinter::printThumbAddrModeS4Operand(const MachineInstr *MI, int Op, + raw_ostream &O) { + printThumbAddrModeRI5Operand(MI, Op, O, 4); } -void ARMAsmPrinter::printThumbAddrModeSPOperand(const MachineInstr *MI,int Op) { +void ARMAsmPrinter::printThumbAddrModeSPOperand(const MachineInstr *MI,int Op, + raw_ostream &O) { const MachineOperand &MO1 = MI->getOperand(Op); const MachineOperand &MO2 = MI->getOperand(Op+1); O << "[" << getRegisterName(MO1.getReg()); @@ -680,7 +743,8 @@ void ARMAsmPrinter::printThumbAddrModeSPOperand(const MachineInstr *MI,int Op) { // register with shift forms. // REG 0 0 - e.g. R5 // REG IMM, SH_OPC - e.g. R5, LSL #3 -void ARMAsmPrinter::printT2SOOperand(const MachineInstr *MI, int OpNum) { +void ARMAsmPrinter::printT2SOOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O) { const MachineOperand &MO1 = MI->getOperand(OpNum); const MachineOperand &MO2 = MI->getOperand(OpNum+1); @@ -698,7 +762,8 @@ void ARMAsmPrinter::printT2SOOperand(const MachineInstr *MI, int OpNum) { } void ARMAsmPrinter::printT2AddrModeImm12Operand(const MachineInstr *MI, - int OpNum) { + int OpNum, + raw_ostream &O) { const MachineOperand &MO1 = MI->getOperand(OpNum); const MachineOperand &MO2 = MI->getOperand(OpNum+1); @@ -711,7 +776,8 @@ void ARMAsmPrinter::printT2AddrModeImm12Operand(const MachineInstr *MI, } void ARMAsmPrinter::printT2AddrModeImm8Operand(const MachineInstr *MI, - int OpNum) { + int OpNum, + raw_ostream &O) { const MachineOperand &MO1 = MI->getOperand(OpNum); const MachineOperand &MO2 = MI->getOperand(OpNum+1); @@ -727,7 +793,8 @@ void ARMAsmPrinter::printT2AddrModeImm8Operand(const MachineInstr *MI, } void ARMAsmPrinter::printT2AddrModeImm8s4Operand(const MachineInstr *MI, - int OpNum) { + int OpNum, + raw_ostream &O) { const MachineOperand &MO1 = MI->getOperand(OpNum); const MachineOperand &MO2 = MI->getOperand(OpNum+1); @@ -743,7 +810,8 @@ void ARMAsmPrinter::printT2AddrModeImm8s4Operand(const MachineInstr *MI, } void ARMAsmPrinter::printT2AddrModeImm8OffsetOperand(const MachineInstr *MI, - int OpNum) { + int OpNum, + raw_ostream &O) { const MachineOperand &MO1 = MI->getOperand(OpNum); int32_t OffImm = (int32_t)MO1.getImm(); // Don't print +0. @@ -754,7 +822,8 @@ void ARMAsmPrinter::printT2AddrModeImm8OffsetOperand(const MachineInstr *MI, } void ARMAsmPrinter::printT2AddrModeSoRegOperand(const MachineInstr *MI, - int OpNum) { + int OpNum, + raw_ostream &O) { const MachineOperand &MO1 = MI->getOperand(OpNum); const MachineOperand &MO2 = MI->getOperand(OpNum+1); const MachineOperand &MO3 = MI->getOperand(OpNum+2); @@ -775,19 +844,22 @@ void ARMAsmPrinter::printT2AddrModeSoRegOperand(const MachineInstr *MI, //===--------------------------------------------------------------------===// -void ARMAsmPrinter::printPredicateOperand(const MachineInstr *MI, int OpNum) { +void ARMAsmPrinter::printPredicateOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O) { ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm(); if (CC != ARMCC::AL) O << ARMCondCodeToString(CC); } void ARMAsmPrinter::printMandatoryPredicateOperand(const MachineInstr *MI, - int OpNum) { + int OpNum, + raw_ostream &O) { ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm(); O << ARMCondCodeToString(CC); } -void ARMAsmPrinter::printSBitModifierOperand(const MachineInstr *MI, int OpNum){ +void ARMAsmPrinter::printSBitModifierOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O){ unsigned Reg = MI->getOperand(OpNum).getReg(); if (Reg) { assert(Reg == ARM::CPSR && "Expect ARM CPSR register!"); @@ -795,25 +867,27 @@ void ARMAsmPrinter::printSBitModifierOperand(const MachineInstr *MI, int OpNum){ } } -void ARMAsmPrinter::printPCLabel(const MachineInstr *MI, int OpNum) { +void ARMAsmPrinter::printPCLabel(const MachineInstr *MI, int OpNum, + raw_ostream &O) { int Id = (int)MI->getOperand(OpNum).getImm(); O << MAI->getPrivateGlobalPrefix() << "PC" << getFunctionNumber() << "_" << Id; } -void ARMAsmPrinter::printRegisterList(const MachineInstr *MI, int OpNum) { +void ARMAsmPrinter::printRegisterList(const MachineInstr *MI, int OpNum, + raw_ostream &O) { O << "{"; for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) { if (MI->getOperand(i).isImplicit()) continue; if ((int)i != OpNum) O << ", "; - printOperand(MI, i); + printOperand(MI, i, O); } O << "}"; } void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNum, - const char *Modifier) { + raw_ostream &O, const char *Modifier) { assert(Modifier && "This operand only works with a modifier!"); // There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the // data itself. @@ -852,7 +926,8 @@ GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const { return OutContext.GetOrCreateSymbol(Name.str()); } -void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNum) { +void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O) { assert(!Subtarget->isThumb2() && "Thumb2 should use double-jump jumptables!"); const MachineOperand &MO1 = MI->getOperand(OpNum); @@ -860,7 +935,9 @@ void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNum) { unsigned JTI = MO1.getIndex(); MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm()); - OutStreamer.EmitLabel(JTISymbol); + // Can't use EmitLabel until instprinter happens, label comes out in the wrong + // order. + O << *JTISymbol << ":\n"; const char *JTEntryDirective = MAI->getData32bitsDirective(); @@ -892,13 +969,17 @@ void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNum) { } } -void ARMAsmPrinter::printJT2BlockOperand(const MachineInstr *MI, int OpNum) { +void ARMAsmPrinter::printJT2BlockOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O) { const MachineOperand &MO1 = MI->getOperand(OpNum); const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id unsigned JTI = MO1.getIndex(); MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm()); - OutStreamer.EmitLabel(JTISymbol); + + // Can't use EmitLabel until instprinter happens, label comes out in the wrong + // order. + O << *JTISymbol << ":\n"; const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); @@ -924,48 +1005,44 @@ void ARMAsmPrinter::printJT2BlockOperand(const MachineInstr *MI, int OpNum) { if (i != e-1) O << '\n'; } - - // Make sure the instruction that follows TBB is 2-byte aligned. - // FIXME: Constant island pass should insert an "ALIGN" instruction instead. - if (ByteOffset && (JTBBs.size() & 1)) { - O << '\n'; - EmitAlignment(1); - } } -void ARMAsmPrinter::printTBAddrMode(const MachineInstr *MI, int OpNum) { +void ARMAsmPrinter::printTBAddrMode(const MachineInstr *MI, int OpNum, + raw_ostream &O) { O << "[pc, " << getRegisterName(MI->getOperand(OpNum).getReg()); if (MI->getOpcode() == ARM::t2TBH) O << ", lsl #1"; O << ']'; } -void ARMAsmPrinter::printNoHashImmediate(const MachineInstr *MI, int OpNum) { +void ARMAsmPrinter::printNoHashImmediate(const MachineInstr *MI, int OpNum, + raw_ostream &O) { O << MI->getOperand(OpNum).getImm(); } -void ARMAsmPrinter::printVFPf32ImmOperand(const MachineInstr *MI, int OpNum) { +void ARMAsmPrinter::printVFPf32ImmOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O) { const ConstantFP *FP = MI->getOperand(OpNum).getFPImm(); O << '#' << FP->getValueAPF().convertToFloat(); - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << ' '; + if (isVerbose()) { + O << "\t\t" << MAI->getCommentString() << ' '; WriteAsOperand(O, FP, /*PrintType=*/false); } } -void ARMAsmPrinter::printVFPf64ImmOperand(const MachineInstr *MI, int OpNum) { +void ARMAsmPrinter::printVFPf64ImmOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O) { const ConstantFP *FP = MI->getOperand(OpNum).getFPImm(); O << '#' << FP->getValueAPF().convertToDouble(); - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << ' '; + if (isVerbose()) { + O << "\t\t" << MAI->getCommentString() << ' '; WriteAsOperand(O, FP, /*PrintType=*/false); } } bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, - unsigned AsmVariant, const char *ExtraCode){ + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O) { // Does this asm operand have a single letter operand modifier? if (ExtraCode && ExtraCode[0]) { if (ExtraCode[1] != 0) return true; // Unknown modifier. @@ -981,11 +1058,11 @@ bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, case 'c': // Don't print "#" before an immediate operand. if (!MI->getOperand(OpNum).isImm()) return true; - printNoHashImmediate(MI, OpNum); + printNoHashImmediate(MI, OpNum, O); return false; case 'P': // Print a VFP double precision register. case 'q': // Print a NEON quad precision register. - printOperand(MI, OpNum); + printOperand(MI, OpNum, O); return false; case 'Q': if (TM.getTargetData()->isLittleEndian()) @@ -1005,13 +1082,14 @@ bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, } } - printOperand(MI, OpNum); + printOperand(MI, OpNum, O); return false; } bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, unsigned AsmVariant, - const char *ExtraCode) { + const char *ExtraCode, + raw_ostream &O) { if (ExtraCode && ExtraCode[0]) return true; // Unknown modifier. @@ -1024,14 +1102,21 @@ bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { if (EnableMCInst) { printInstructionThroughMCStreamer(MI); - } else { - int Opc = MI->getOpcode(); - if (Opc == ARM::CONSTPOOL_ENTRY) - EmitAlignment(2); - - printInstruction(MI); - OutStreamer.AddBlankLine(); + return; } + + if (MI->getOpcode() == ARM::CONSTPOOL_ENTRY) + EmitAlignment(2); + + SmallString<128> Str; + raw_svector_ostream OS(Str); + printInstruction(MI, OS); + OutStreamer.EmitRawText(OS.str()); + + // Make sure the instruction that follows TBB is 2-byte aligned. + // FIXME: Constant island pass should insert an "ALIGN" instruction instead. + if (MI->getOpcode() == ARM::t2TBB) + EmitAlignment(1); } void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) { @@ -1066,38 +1151,48 @@ void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) { } // Use unified assembler syntax. - O << "\t.syntax unified\n"; + OutStreamer.EmitRawText(StringRef("\t.syntax unified")); // Emit ARM Build Attributes if (Subtarget->isTargetELF()) { // CPU Type std::string CPUString = Subtarget->getCPUString(); if (CPUString != "generic") - O << "\t.cpu " << CPUString << '\n'; + OutStreamer.EmitRawText("\t.cpu " + Twine(CPUString)); // FIXME: Emit FPU type if (Subtarget->hasVFP2()) - O << "\t.eabi_attribute " << ARMBuildAttrs::VFP_arch << ", 2\n"; + OutStreamer.EmitRawText("\t.eabi_attribute " + + Twine(ARMBuildAttrs::VFP_arch) + ", 2"); // Signal various FP modes. - if (!UnsafeFPMath) - O << "\t.eabi_attribute " << ARMBuildAttrs::ABI_FP_denormal << ", 1\n" - << "\t.eabi_attribute " << ARMBuildAttrs::ABI_FP_exceptions << ", 1\n"; - + if (!UnsafeFPMath) { + OutStreamer.EmitRawText("\t.eabi_attribute " + + Twine(ARMBuildAttrs::ABI_FP_denormal) + ", 1"); + OutStreamer.EmitRawText("\t.eabi_attribute " + + Twine(ARMBuildAttrs::ABI_FP_exceptions) + ", 1"); + } + if (FiniteOnlyFPMath()) - O << "\t.eabi_attribute " << ARMBuildAttrs::ABI_FP_number_model << ", 1\n"; + OutStreamer.EmitRawText("\t.eabi_attribute " + + Twine(ARMBuildAttrs::ABI_FP_number_model)+ ", 1"); else - O << "\t.eabi_attribute " << ARMBuildAttrs::ABI_FP_number_model << ", 3\n"; + OutStreamer.EmitRawText("\t.eabi_attribute " + + Twine(ARMBuildAttrs::ABI_FP_number_model)+ ", 3"); // 8-bytes alignment stuff. - O << "\t.eabi_attribute " << ARMBuildAttrs::ABI_align8_needed << ", 1\n" - << "\t.eabi_attribute " << ARMBuildAttrs::ABI_align8_preserved << ", 1\n"; + OutStreamer.EmitRawText("\t.eabi_attribute " + + Twine(ARMBuildAttrs::ABI_align8_needed) + ", 1"); + OutStreamer.EmitRawText("\t.eabi_attribute " + + Twine(ARMBuildAttrs::ABI_align8_preserved) + ", 1"); // Hard float. Use both S and D registers and conform to AAPCS-VFP. - if (Subtarget->isAAPCS_ABI() && FloatABIType == FloatABI::Hard) - O << "\t.eabi_attribute " << ARMBuildAttrs::ABI_HardFP_use << ", 3\n" - << "\t.eabi_attribute " << ARMBuildAttrs::ABI_VFP_args << ", 1\n"; - + if (Subtarget->isAAPCS_ABI() && FloatABIType == FloatABI::Hard) { + OutStreamer.EmitRawText("\t.eabi_attribute " + + Twine(ARMBuildAttrs::ABI_HardFP_use) + ", 3"); + OutStreamer.EmitRawText("\t.eabi_attribute " + + Twine(ARMBuildAttrs::ABI_VFP_args) + ", 1"); + } // FIXME: Should we signal R9 usage? } } @@ -1111,8 +1206,6 @@ void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) { MachineModuleInfoMachO &MMIMacho = MMI->getObjFileInfo<MachineModuleInfoMachO>(); - O << '\n'; - // Output non-lazy-pointers for external and common global variables. MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetGVStubList(); @@ -1308,10 +1401,9 @@ void ARMAsmPrinter::printInstructionThroughMCStreamer(const MachineInstr *MI) { static MCInstPrinter *createARMMCInstPrinter(const Target &T, unsigned SyntaxVariant, - const MCAsmInfo &MAI, - raw_ostream &O) { + const MCAsmInfo &MAI) { if (SyntaxVariant == 0) - return new ARMInstPrinter(O, MAI, false); + return new ARMInstPrinter(MAI, false); return 0; } diff --git a/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp index 30763a9952e4..ef5ead6e473b 100644 --- a/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp +++ b/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp @@ -98,7 +98,7 @@ static unsigned NextReg(unsigned Reg) { } } -void ARMInstPrinter::printInst(const MCInst *MI) { +void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O) { // Check for MOVs and print canonical forms, instead. if (MI->getOpcode() == ARM::MOVs) { const MCOperand &Dst = MI->getOperand(0); @@ -107,8 +107,8 @@ void ARMInstPrinter::printInst(const MCInst *MI) { const MCOperand &MO3 = MI->getOperand(3); O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm())); - printSBitModifierOperand(MI, 6); - printPredicateOperand(MI, 4); + printSBitModifierOperand(MI, 6, O); + printPredicateOperand(MI, 4, O); O << '\t' << getRegisterName(Dst.getReg()) << ", " << getRegisterName(MO1.getReg()); @@ -133,9 +133,9 @@ void ARMInstPrinter::printInst(const MCInst *MI) { const MCOperand &MO1 = MI->getOperand(2); if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::db) { O << '\t' << "push"; - printPredicateOperand(MI, 3); + printPredicateOperand(MI, 3, O); O << '\t'; - printRegisterList(MI, 5); + printRegisterList(MI, 5, O); return; } } @@ -146,9 +146,9 @@ void ARMInstPrinter::printInst(const MCInst *MI) { const MCOperand &MO1 = MI->getOperand(2); if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::ia) { O << '\t' << "pop"; - printPredicateOperand(MI, 3); + printPredicateOperand(MI, 3, O); O << '\t'; - printRegisterList(MI, 5); + printRegisterList(MI, 5, O); return; } } @@ -159,9 +159,9 @@ void ARMInstPrinter::printInst(const MCInst *MI) { const MCOperand &MO1 = MI->getOperand(2); if (ARM_AM::getAM5SubMode(MO1.getImm()) == ARM_AM::db) { O << '\t' << "vpush"; - printPredicateOperand(MI, 3); + printPredicateOperand(MI, 3, O); O << '\t'; - printRegisterList(MI, 5); + printRegisterList(MI, 5, O); return; } } @@ -172,18 +172,18 @@ void ARMInstPrinter::printInst(const MCInst *MI) { const MCOperand &MO1 = MI->getOperand(2); if (ARM_AM::getAM5SubMode(MO1.getImm()) == ARM_AM::ia) { O << '\t' << "vpop"; - printPredicateOperand(MI, 3); + printPredicateOperand(MI, 3, O); O << '\t'; - printRegisterList(MI, 5); + printRegisterList(MI, 5, O); return; } } - printInstruction(MI); + printInstruction(MI, O); } void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, - const char *Modifier) { + raw_ostream &O, const char *Modifier) { const MCOperand &Op = MI->getOperand(OpNo); if (Op.isReg()) { unsigned Reg = Op.getReg(); @@ -247,7 +247,8 @@ static void printSOImm(raw_ostream &O, int64_t V, bool VerboseAsm, /// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit /// immediate in bits 0-7. -void ARMInstPrinter::printSOImmOperand(const MCInst *MI, unsigned OpNum) { +void ARMInstPrinter::printSOImmOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { const MCOperand &MO = MI->getOperand(OpNum); assert(MO.isImm() && "Not a valid so_imm value!"); printSOImm(O, MO.getImm(), VerboseAsm, &MAI); @@ -255,7 +256,8 @@ void ARMInstPrinter::printSOImmOperand(const MCInst *MI, unsigned OpNum) { /// printSOImm2PartOperand - SOImm is broken into two pieces using a 'mov' /// followed by an 'orr' to materialize. -void ARMInstPrinter::printSOImm2PartOperand(const MCInst *MI, unsigned OpNum) { +void ARMInstPrinter::printSOImm2PartOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { // FIXME: REMOVE this method. abort(); } @@ -265,7 +267,8 @@ void ARMInstPrinter::printSOImm2PartOperand(const MCInst *MI, unsigned OpNum) { // REG 0 0 - e.g. R5 // REG REG 0,SH_OPC - e.g. R5, ROR R3 // REG 0 IMM,SH_OPC - e.g. R5, LSL #3 -void ARMInstPrinter::printSORegOperand(const MCInst *MI, unsigned OpNum) { +void ARMInstPrinter::printSORegOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { const MCOperand &MO1 = MI->getOperand(OpNum); const MCOperand &MO2 = MI->getOperand(OpNum+1); const MCOperand &MO3 = MI->getOperand(OpNum+2); @@ -286,13 +289,14 @@ void ARMInstPrinter::printSORegOperand(const MCInst *MI, unsigned OpNum) { } -void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op) { +void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op, + raw_ostream &O) { const MCOperand &MO1 = MI->getOperand(Op); const MCOperand &MO2 = MI->getOperand(Op+1); const MCOperand &MO3 = MI->getOperand(Op+2); if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. - printOperand(MI, Op); + printOperand(MI, Op, O); return; } @@ -319,7 +323,8 @@ void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op) { } void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI, - unsigned OpNum) { + unsigned OpNum, + raw_ostream &O) { const MCOperand &MO1 = MI->getOperand(OpNum); const MCOperand &MO2 = MI->getOperand(OpNum+1); @@ -341,7 +346,8 @@ void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI, << " #" << ShImm; } -void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned OpNum) { +void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { const MCOperand &MO1 = MI->getOperand(OpNum); const MCOperand &MO2 = MI->getOperand(OpNum+1); const MCOperand &MO3 = MI->getOperand(OpNum+2); @@ -362,7 +368,8 @@ void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned OpNum) { } void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI, - unsigned OpNum) { + unsigned OpNum, + raw_ostream &O) { const MCOperand &MO1 = MI->getOperand(OpNum); const MCOperand &MO2 = MI->getOperand(OpNum+1); @@ -381,6 +388,7 @@ void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI, void ARMInstPrinter::printAddrMode4Operand(const MCInst *MI, unsigned OpNum, + raw_ostream &O, const char *Modifier) { const MCOperand &MO2 = MI->getOperand(OpNum+1); ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm()); @@ -391,17 +399,18 @@ void ARMInstPrinter::printAddrMode4Operand(const MCInst *MI, unsigned OpNum, if (Mode == ARM_AM::ia) O << ".w"; } else { - printOperand(MI, OpNum); + printOperand(MI, OpNum, O); } } void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum, + raw_ostream &O, const char *Modifier) { const MCOperand &MO1 = MI->getOperand(OpNum); const MCOperand &MO2 = MI->getOperand(OpNum+1); if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. - printOperand(MI, OpNum); + printOperand(MI, OpNum, O); return; } @@ -425,7 +434,8 @@ void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum, O << "]"; } -void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum) { +void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { const MCOperand &MO1 = MI->getOperand(OpNum); const MCOperand &MO2 = MI->getOperand(OpNum+1); @@ -438,7 +448,8 @@ void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum) { } void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI, - unsigned OpNum) { + unsigned OpNum, + raw_ostream &O) { const MCOperand &MO = MI->getOperand(OpNum); if (MO.getReg() == 0) O << "!"; @@ -447,12 +458,14 @@ void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI, } void ARMInstPrinter::printAddrModePCOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O, const char *Modifier) { assert(0 && "FIXME: Implement printAddrModePCOperand"); } void ARMInstPrinter::printBitfieldInvMaskImmOperand (const MCInst *MI, - unsigned OpNum) { + unsigned OpNum, + raw_ostream &O) { const MCOperand &MO = MI->getOperand(OpNum); uint32_t v = ~MO.getImm(); int32_t lsb = CountTrailingZeros_32(v); @@ -461,7 +474,8 @@ void ARMInstPrinter::printBitfieldInvMaskImmOperand (const MCInst *MI, O << '#' << lsb << ", #" << width; } -void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum) { +void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { O << "{"; for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) { if (i != OpNum) O << ", "; @@ -470,7 +484,8 @@ void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum) { O << "}"; } -void ARMInstPrinter::printCPSOptionOperand(const MCInst *MI, unsigned OpNum) { +void ARMInstPrinter::printCPSOptionOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { const MCOperand &Op = MI->getOperand(OpNum); unsigned option = Op.getImm(); unsigned mode = option & 31; @@ -492,7 +507,8 @@ void ARMInstPrinter::printCPSOptionOperand(const MCInst *MI, unsigned OpNum) { O << '#' << mode; } -void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum) { +void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { const MCOperand &Op = MI->getOperand(OpNum); unsigned Mask = Op.getImm(); if (Mask) { @@ -504,7 +520,8 @@ void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum) { } } -void ARMInstPrinter::printNegZeroOperand(const MCInst *MI, unsigned OpNum){ +void ARMInstPrinter::printNegZeroOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { const MCOperand &Op = MI->getOperand(OpNum); O << '#'; if (Op.getImm() < 0) @@ -513,19 +530,22 @@ void ARMInstPrinter::printNegZeroOperand(const MCInst *MI, unsigned OpNum){ O << Op.getImm(); } -void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum) { +void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm(); if (CC != ARMCC::AL) O << ARMCondCodeToString(CC); } void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI, - unsigned OpNum) { + unsigned OpNum, + raw_ostream &O) { ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm(); O << ARMCondCodeToString(CC); } -void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum){ +void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { if (MI->getOperand(OpNum).getReg()) { assert(MI->getOperand(OpNum).getReg() == ARM::CPSR && "Expect ARM CPSR register!"); @@ -536,26 +556,31 @@ void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum){ void ARMInstPrinter::printCPInstOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O, const char *Modifier) { // FIXME: remove this. abort(); } -void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum) { +void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { O << MI->getOperand(OpNum).getImm(); } -void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum) { +void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { // FIXME: remove this. abort(); } -void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum) { +void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { O << "#" << MI->getOperand(OpNum).getImm() * 4; } -void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum) { +void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { // (3 - the number of trailing zeros) is the number of then / else. unsigned Mask = MI->getOperand(OpNum).getImm(); unsigned CondBit0 = Mask >> 4 & 1; @@ -570,8 +595,8 @@ void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum) { } } -void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op) -{ +void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op, + raw_ostream &O) { const MCOperand &MO1 = MI->getOperand(Op); const MCOperand &MO2 = MI->getOperand(Op+1); O << "[" << getRegisterName(MO1.getReg()); @@ -579,13 +604,14 @@ void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op) } void ARMInstPrinter::printThumbAddrModeRI5Operand(const MCInst *MI, unsigned Op, + raw_ostream &O, unsigned Scale) { const MCOperand &MO1 = MI->getOperand(Op); const MCOperand &MO2 = MI->getOperand(Op+1); const MCOperand &MO3 = MI->getOperand(Op+2); if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. - printOperand(MI, Op); + printOperand(MI, Op, O); return; } @@ -597,22 +623,23 @@ void ARMInstPrinter::printThumbAddrModeRI5Operand(const MCInst *MI, unsigned Op, O << "]"; } -void ARMInstPrinter::printThumbAddrModeS1Operand(const MCInst *MI, unsigned Op) -{ - printThumbAddrModeRI5Operand(MI, Op, 1); +void ARMInstPrinter::printThumbAddrModeS1Operand(const MCInst *MI, unsigned Op, + raw_ostream &O) { + printThumbAddrModeRI5Operand(MI, Op, O, 1); } -void ARMInstPrinter::printThumbAddrModeS2Operand(const MCInst *MI, unsigned Op) -{ - printThumbAddrModeRI5Operand(MI, Op, 2); +void ARMInstPrinter::printThumbAddrModeS2Operand(const MCInst *MI, unsigned Op, + raw_ostream &O) { + printThumbAddrModeRI5Operand(MI, Op, O, 2); } -void ARMInstPrinter::printThumbAddrModeS4Operand(const MCInst *MI, unsigned Op) -{ - printThumbAddrModeRI5Operand(MI, Op, 4); +void ARMInstPrinter::printThumbAddrModeS4Operand(const MCInst *MI, unsigned Op, + raw_ostream &O) { + printThumbAddrModeRI5Operand(MI, Op, O, 4); } -void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI,unsigned Op) { +void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op, + raw_ostream &O) { const MCOperand &MO1 = MI->getOperand(Op); const MCOperand &MO2 = MI->getOperand(Op+1); O << "[" << getRegisterName(MO1.getReg()); @@ -621,7 +648,8 @@ void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI,unsigned Op) { O << "]"; } -void ARMInstPrinter::printTBAddrMode(const MCInst *MI, unsigned OpNum) { +void ARMInstPrinter::printTBAddrMode(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { O << "[pc, " << getRegisterName(MI->getOperand(OpNum).getReg()); if (MI->getOpcode() == ARM::t2TBH) O << ", lsl #1"; @@ -632,7 +660,8 @@ void ARMInstPrinter::printTBAddrMode(const MCInst *MI, unsigned OpNum) { // register with shift forms. // REG 0 0 - e.g. R5 // REG IMM, SH_OPC - e.g. R5, LSL #3 -void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum) { +void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { const MCOperand &MO1 = MI->getOperand(OpNum); const MCOperand &MO2 = MI->getOperand(OpNum+1); @@ -649,7 +678,8 @@ void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum) { } void ARMInstPrinter::printT2AddrModeImm12Operand(const MCInst *MI, - unsigned OpNum) { + unsigned OpNum, + raw_ostream &O) { const MCOperand &MO1 = MI->getOperand(OpNum); const MCOperand &MO2 = MI->getOperand(OpNum+1); @@ -662,7 +692,8 @@ void ARMInstPrinter::printT2AddrModeImm12Operand(const MCInst *MI, } void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI, - unsigned OpNum) { + unsigned OpNum, + raw_ostream &O) { const MCOperand &MO1 = MI->getOperand(OpNum); const MCOperand &MO2 = MI->getOperand(OpNum+1); @@ -678,7 +709,8 @@ void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI, } void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI, - unsigned OpNum) { + unsigned OpNum, + raw_ostream &O) { const MCOperand &MO1 = MI->getOperand(OpNum); const MCOperand &MO2 = MI->getOperand(OpNum+1); @@ -694,7 +726,8 @@ void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI, } void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(const MCInst *MI, - unsigned OpNum) { + unsigned OpNum, + raw_ostream &O) { const MCOperand &MO1 = MI->getOperand(OpNum); int32_t OffImm = (int32_t)MO1.getImm(); // Don't print +0. @@ -705,7 +738,8 @@ void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(const MCInst *MI, } void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(const MCInst *MI, - unsigned OpNum) { + unsigned OpNum, + raw_ostream &O) { const MCOperand &MO1 = MI->getOperand(OpNum); int32_t OffImm = (int32_t)MO1.getImm() / 4; // Don't print +0. @@ -716,7 +750,8 @@ void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(const MCInst *MI, } void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI, - unsigned OpNum) { + unsigned OpNum, + raw_ostream &O) { const MCOperand &MO1 = MI->getOperand(OpNum); const MCOperand &MO2 = MI->getOperand(OpNum+1); const MCOperand &MO3 = MI->getOperand(OpNum+2); @@ -734,11 +769,13 @@ void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI, O << "]"; } -void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum) { +void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { O << '#' << MI->getOperand(OpNum).getImm(); } -void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum) { +void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { O << '#' << MI->getOperand(OpNum).getImm(); } diff --git a/lib/Target/ARM/AsmPrinter/ARMInstPrinter.h b/lib/Target/ARM/AsmPrinter/ARMInstPrinter.h index d41b5dfa6c5b..dd006fc52e74 100644 --- a/lib/Target/ARM/AsmPrinter/ARMInstPrinter.h +++ b/lib/Target/ARM/AsmPrinter/ARMInstPrinter.h @@ -22,79 +22,96 @@ namespace llvm { class ARMInstPrinter : public MCInstPrinter { bool VerboseAsm; public: - ARMInstPrinter(raw_ostream &O, const MCAsmInfo &MAI, bool verboseAsm) - : MCInstPrinter(O, MAI), VerboseAsm(verboseAsm) {} + ARMInstPrinter(const MCAsmInfo &MAI, bool verboseAsm) + : MCInstPrinter(MAI), VerboseAsm(verboseAsm) {} - virtual void printInst(const MCInst *MI); + virtual void printInst(const MCInst *MI, raw_ostream &O); // Autogenerated by tblgen. - void printInstruction(const MCInst *MI); + void printInstruction(const MCInst *MI, raw_ostream &O); static const char *getRegisterName(unsigned RegNo); - void printOperand(const MCInst *MI, unsigned OpNo, + void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O, const char *Modifier = 0); - void printSOImmOperand(const MCInst *MI, unsigned OpNum); - void printSOImm2PartOperand(const MCInst *MI, unsigned OpNum); + void printSOImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printSOImm2PartOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); - void printSORegOperand(const MCInst *MI, unsigned OpNum); - void printAddrMode2Operand(const MCInst *MI, unsigned OpNum); - void printAddrMode2OffsetOperand(const MCInst *MI, unsigned OpNum); - void printAddrMode3Operand(const MCInst *MI, unsigned OpNum); - void printAddrMode3OffsetOperand(const MCInst *MI, unsigned OpNum); - void printAddrMode4Operand(const MCInst *MI, unsigned OpNum, + void printSORegOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printAddrMode2Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printAddrMode2OffsetOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O); + void printAddrMode3Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printAddrMode3OffsetOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O); + void printAddrMode4Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O, const char *Modifier = 0); - void printAddrMode5Operand(const MCInst *MI, unsigned OpNum, + void printAddrMode5Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O, const char *Modifier = 0); - void printAddrMode6Operand(const MCInst *MI, unsigned OpNum); - void printAddrMode6OffsetOperand(const MCInst *MI, unsigned OpNum); - void printAddrModePCOperand(const MCInst *MI, unsigned OpNum, + void printAddrMode6Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printAddrMode6OffsetOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O); + void printAddrModePCOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O, const char *Modifier = 0); - void printBitfieldInvMaskImmOperand(const MCInst *MI, unsigned OpNum); + void printBitfieldInvMaskImmOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O); - void printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum); - void printThumbITMask(const MCInst *MI, unsigned OpNum); - void printThumbAddrModeRROperand(const MCInst *MI, unsigned OpNum); + void printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printThumbITMask(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printThumbAddrModeRROperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O); void printThumbAddrModeRI5Operand(const MCInst *MI, unsigned OpNum, - unsigned Scale); - void printThumbAddrModeS1Operand(const MCInst *MI, unsigned OpNum); - void printThumbAddrModeS2Operand(const MCInst *MI, unsigned OpNum); - void printThumbAddrModeS4Operand(const MCInst *MI, unsigned OpNum); - void printThumbAddrModeSPOperand(const MCInst *MI, unsigned OpNum); + raw_ostream &O, unsigned Scale); + void printThumbAddrModeS1Operand(const MCInst *MI, unsigned OpNum, + raw_ostream &O); + void printThumbAddrModeS2Operand(const MCInst *MI, unsigned OpNum, + raw_ostream &O); + void printThumbAddrModeS4Operand(const MCInst *MI, unsigned OpNum, + raw_ostream &O); + void printThumbAddrModeSPOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O); - void printT2SOOperand(const MCInst *MI, unsigned OpNum); - void printT2AddrModeImm12Operand(const MCInst *MI, unsigned OpNum); - void printT2AddrModeImm8Operand(const MCInst *MI, unsigned OpNum); - void printT2AddrModeImm8s4Operand(const MCInst *MI, unsigned OpNum); - void printT2AddrModeImm8OffsetOperand(const MCInst *MI, unsigned OpNum); - void printT2AddrModeImm8s4OffsetOperand(const MCInst *MI, unsigned OpNum); - void printT2AddrModeSoRegOperand(const MCInst *MI, unsigned OpNum); + void printT2SOOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printT2AddrModeImm12Operand(const MCInst *MI, unsigned OpNum, + raw_ostream &O); + void printT2AddrModeImm8Operand(const MCInst *MI, unsigned OpNum, + raw_ostream &O); + void printT2AddrModeImm8s4Operand(const MCInst *MI, unsigned OpNum, + raw_ostream &O); + void printT2AddrModeImm8OffsetOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O); + void printT2AddrModeImm8s4OffsetOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O); + void printT2AddrModeSoRegOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O); - void printCPSOptionOperand(const MCInst *MI, unsigned OpNum); - void printMSRMaskOperand(const MCInst *MI, unsigned OpNum); - void printNegZeroOperand(const MCInst *MI, unsigned OpNum); - void printPredicateOperand(const MCInst *MI, unsigned OpNum); - void printMandatoryPredicateOperand(const MCInst *MI, unsigned OpNum); - void printSBitModifierOperand(const MCInst *MI, unsigned OpNum); - void printRegisterList(const MCInst *MI, unsigned OpNum); - void printCPInstOperand(const MCInst *MI, unsigned OpNum, + void printCPSOptionOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printMSRMaskOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printNegZeroOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printPredicateOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printMandatoryPredicateOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O); + void printSBitModifierOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O); + void printRegisterList(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printCPInstOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O, const char *Modifier); - void printJTBlockOperand(const MCInst *MI, unsigned OpNum) {} - void printJT2BlockOperand(const MCInst *MI, unsigned OpNum) {} - void printTBAddrMode(const MCInst *MI, unsigned OpNum); - void printNoHashImmediate(const MCInst *MI, unsigned OpNum); - void printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum); - void printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum); - void printHex8ImmOperand(const MCInst *MI, int OpNum) {} - void printHex16ImmOperand(const MCInst *MI, int OpNum) {} - void printHex32ImmOperand(const MCInst *MI, int OpNum) {} - void printHex64ImmOperand(const MCInst *MI, int OpNum) {} + void printJTBlockOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O) {} + void printJT2BlockOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O) {} + void printTBAddrMode(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printNoHashImmediate(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printHex8ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O) {} + void printHex16ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O) {} + void printHex32ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O) {} + void printHex64ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O) {} - void printPCLabel(const MCInst *MI, unsigned OpNum); + void printPCLabel(const MCInst *MI, unsigned OpNum, raw_ostream &O); // FIXME: Implement. - void PrintSpecial(const MCInst *MI, const char *Kind) {} + void PrintSpecial(const MCInst *MI, raw_ostream &O, const char *Kind) {} }; } diff --git a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp index 04313400b8d9..47c31043d9c0 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp @@ -380,11 +380,18 @@ bool ARMDisassembler::getInstruction(MCInst &MI, raw_ostream &os) const { // The machine instruction. uint32_t insn; + uint8_t bytes[4]; // We want to read exactly 4 bytes of data. - if (Region.readBytes(Address, 4, (uint8_t*)&insn, NULL) == -1) + if (Region.readBytes(Address, 4, (uint8_t*)bytes, NULL) == -1) return false; + // Encoded as a small-endian 32-bit word in the stream. + insn = (bytes[3] << 24) | + (bytes[2] << 16) | + (bytes[1] << 8) | + (bytes[0] << 0); + unsigned Opcode = decodeARMInstruction(insn); ARMFormat Format = ARMFormats[Opcode]; Size = 4; @@ -414,9 +421,15 @@ bool ThumbDisassembler::getInstruction(MCInst &MI, const MemoryObject &Region, uint64_t Address, raw_ostream &os) const { - // The machine instruction. + // The Thumb instruction stream is a sequence of halhwords. + + // This represents the first halfword as well as the machine instruction + // passed to decodeThumbInstruction(). For 16-bit Thumb instruction, the top + // halfword of insn is 0x00 0x00; otherwise, the first halfword is moved to + // the top half followed by the second halfword. uint32_t insn = 0; - uint32_t insn1 = 0; + // Possible second halfword. + uint16_t insn1 = 0; // A6.1 Thumb instruction set encoding // @@ -429,9 +442,12 @@ bool ThumbDisassembler::getInstruction(MCInst &MI, // Otherwise, the halfword is a 16-bit instruction. // Read 2 bytes of data first. - if (Region.readBytes(Address, 2, (uint8_t*)&insn, NULL) == -1) + uint8_t bytes[2]; + if (Region.readBytes(Address, 2, (uint8_t*)bytes, NULL) == -1) return false; + // Encoded as a small-endian 16-bit halfword in the stream. + insn = (bytes[1] << 8) | bytes[0]; unsigned bits15_11 = slice(insn, 15, 11); bool IsThumb2 = false; @@ -439,8 +455,10 @@ bool ThumbDisassembler::getInstruction(MCInst &MI, // { 0b11101 /* 0x1D */, 0b11110 /* 0x1E */, ob11111 /* 0x1F */ }. if (bits15_11 == 0x1D || bits15_11 == 0x1E || bits15_11 == 0x1F) { IsThumb2 = true; - if (Region.readBytes(Address + 2, 2, (uint8_t*)&insn1, NULL) == -1) + if (Region.readBytes(Address + 2, 2, (uint8_t*)bytes, NULL) == -1) return false; + // Encoded as a small-endian 16-bit halfword in the stream. + insn1 = (bytes[1] << 8) | bytes[0]; insn = (insn << 16 | insn1); } diff --git a/lib/Target/ARM/Disassembler/Makefile b/lib/Target/ARM/Disassembler/Makefile deleted file mode 100644 index 031b6aca5a48..000000000000 --- a/lib/Target/ARM/Disassembler/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/ARM/Disassembler/Makefile ----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMARMDisassembler - -# Hack: we need to include 'main' arm target directory to grab private headers -CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/lib/Target/ARM/Makefile b/lib/Target/ARM/Makefile index b7ed14abed78..a8dd38cb362e 100644 --- a/lib/Target/ARM/Makefile +++ b/lib/Target/ARM/Makefile @@ -16,9 +16,8 @@ BUILT_SOURCES = ARMGenRegisterInfo.h.inc ARMGenRegisterNames.inc \ ARMGenRegisterInfo.inc ARMGenInstrNames.inc \ ARMGenInstrInfo.inc ARMGenAsmWriter.inc \ ARMGenDAGISel.inc ARMGenSubtarget.inc \ - ARMGenCodeEmitter.inc ARMGenCallingConv.inc \ - ARMGenDecoderTables.inc + ARMGenCodeEmitter.inc ARMGenCallingConv.inc -DIRS = AsmPrinter AsmParser Disassembler TargetInfo +DIRS = AsmPrinter AsmParser TargetInfo include $(LEVEL)/Makefile.common diff --git a/lib/Target/Alpha/Alpha.td b/lib/Target/Alpha/Alpha.td index 6efdf554e176..4508eda897d2 100644 --- a/lib/Target/Alpha/Alpha.td +++ b/lib/Target/Alpha/Alpha.td @@ -47,11 +47,7 @@ include "AlphaSchedule.td" include "AlphaInstrInfo.td" -def AlphaInstrInfo : InstrInfo { - // Define how we want to layout our target-specific information field. - // let TSFlagsFields = []; - // let TSFlagsShifts = []; -} +def AlphaInstrInfo : InstrInfo; //===----------------------------------------------------------------------===// // Alpha Processor Definitions diff --git a/lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp b/lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp index 093cf0528030..2a1f5559053f 100644 --- a/lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp +++ b/lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp @@ -20,7 +20,6 @@ #include "llvm/Type.h" #include "llvm/Assembly/Writer.h" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/DwarfWriter.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCSymbol.h" @@ -28,8 +27,8 @@ #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegistry.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FormattedStream.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; namespace { @@ -37,40 +36,42 @@ namespace { /// Unique incrementer for label values for referencing Global values. /// - explicit AlphaAsmPrinter(formatted_raw_ostream &o, TargetMachine &tm, - MCStreamer &Streamer) - : AsmPrinter(o, tm, Streamer) {} + explicit AlphaAsmPrinter(TargetMachine &tm, MCStreamer &Streamer) + : AsmPrinter(tm, Streamer) {} virtual const char *getPassName() const { return "Alpha Assembly Printer"; } - void printInstruction(const MachineInstr *MI); + void printInstruction(const MachineInstr *MI, raw_ostream &O); void EmitInstruction(const MachineInstr *MI) { - printInstruction(MI); - OutStreamer.AddBlankLine(); + SmallString<128> Str; + raw_svector_ostream OS(Str); + printInstruction(MI, OS); + OutStreamer.EmitRawText(OS.str()); } static const char *getRegisterName(unsigned RegNo); - void printOp(const MachineOperand &MO, bool IsCallOp = false); - void printOperand(const MachineInstr *MI, int opNum); - void printBaseOffsetPair(const MachineInstr *MI, int i, bool brackets=true); + void printOp(const MachineOperand &MO, raw_ostream &O); + void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); + void printBaseOffsetPair(const MachineInstr *MI, int i, raw_ostream &O, + bool brackets=true); virtual void EmitFunctionBodyStart(); virtual void EmitFunctionBodyEnd(); void EmitStartOfAsmFile(Module &M); bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode); + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); bool PrintAsmMemoryOperand(const MachineInstr *MI, - unsigned OpNo, - unsigned AsmVariant, - const char *ExtraCode); + unsigned OpNo, unsigned AsmVariant, + const char *ExtraCode, raw_ostream &O); }; } // end of anonymous namespace #include "AlphaGenAsmWriter.inc" -void AlphaAsmPrinter::printOperand(const MachineInstr *MI, int opNum) -{ +void AlphaAsmPrinter::printOperand(const MachineInstr *MI, int opNum, + raw_ostream &O) { const MachineOperand &MO = MI->getOperand(opNum); if (MO.getType() == MachineOperand::MO_Register) { assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && @@ -80,12 +81,12 @@ void AlphaAsmPrinter::printOperand(const MachineInstr *MI, int opNum) O << MO.getImm(); assert(MO.getImm() < (1 << 30)); } else { - printOp(MO); + printOp(MO, O); } } -void AlphaAsmPrinter::printOp(const MachineOperand &MO, bool IsCallOp) { +void AlphaAsmPrinter::printOp(const MachineOperand &MO, raw_ostream &O) { switch (MO.getType()) { case MachineOperand::MO_Register: O << getRegisterName(MO.getReg()); @@ -126,40 +127,37 @@ void AlphaAsmPrinter::printOp(const MachineOperand &MO, bool IsCallOp) { /// EmitFunctionBodyStart - Targets can override this to emit stuff before /// the first basic block in the function. void AlphaAsmPrinter::EmitFunctionBodyStart() { - O << "\t.ent " << *CurrentFnSym << "\n"; + OutStreamer.EmitRawText("\t.ent " + Twine(CurrentFnSym->getName())); } /// EmitFunctionBodyEnd - Targets can override this to emit stuff after /// the last basic block in the function. void AlphaAsmPrinter::EmitFunctionBodyEnd() { - O << "\t.end " << *CurrentFnSym << "\n"; + OutStreamer.EmitRawText("\t.end " + Twine(CurrentFnSym->getName())); } void AlphaAsmPrinter::EmitStartOfAsmFile(Module &M) { - if (TM.getSubtarget<AlphaSubtarget>().hasCT()) - O << "\t.arch ev6\n"; //This might need to be ev67, so leave this test here - else - O << "\t.arch ev6\n"; - O << "\t.set noat\n"; + OutStreamer.EmitRawText(StringRef("\t.arch ev6")); + OutStreamer.EmitRawText(StringRef("\t.set noat")); } /// PrintAsmOperand - Print out an operand for an inline asm expression. /// bool AlphaAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, - const char *ExtraCode) { - printOperand(MI, OpNo); + const char *ExtraCode, raw_ostream &O) { + printOperand(MI, OpNo, O); return false; } bool AlphaAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, - unsigned OpNo, - unsigned AsmVariant, - const char *ExtraCode) { + unsigned OpNo, unsigned AsmVariant, + const char *ExtraCode, + raw_ostream &O) { if (ExtraCode && ExtraCode[0]) return true; // Unknown modifier. O << "0("; - printOperand(MI, OpNo); + printOperand(MI, OpNo, O); O << ")"; return false; } diff --git a/lib/Target/Blackfin/AsmPrinter/BlackfinAsmPrinter.cpp b/lib/Target/Blackfin/AsmPrinter/BlackfinAsmPrinter.cpp index 1c6d841cf3eb..6ba258beb2b8 100644 --- a/lib/Target/Blackfin/AsmPrinter/BlackfinAsmPrinter.cpp +++ b/lib/Target/Blackfin/AsmPrinter/BlackfinAsmPrinter.cpp @@ -19,7 +19,6 @@ #include "llvm/DerivedTypes.h" #include "llvm/Module.h" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/DwarfWriter.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineInstr.h" @@ -33,33 +32,36 @@ #include "llvm/Target/TargetRegistry.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; namespace { class BlackfinAsmPrinter : public AsmPrinter { public: - BlackfinAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, - MCStreamer &Streamer) - : AsmPrinter(O, TM, Streamer) {} + BlackfinAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : AsmPrinter(TM, Streamer) {} virtual const char *getPassName() const { return "Blackfin Assembly Printer"; } - void printOperand(const MachineInstr *MI, int opNum); - void printMemoryOperand(const MachineInstr *MI, int opNum); - void printInstruction(const MachineInstr *MI); // autogenerated. + void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); + void printMemoryOperand(const MachineInstr *MI, int opNum, raw_ostream &O); + void printInstruction(const MachineInstr *MI, raw_ostream &O);// autogen'd. static const char *getRegisterName(unsigned RegNo); void EmitInstruction(const MachineInstr *MI) { - printInstruction(MI); - OutStreamer.AddBlankLine(); + SmallString<128> Str; + raw_svector_ostream OS(Str); + printInstruction(MI, OS); + OutStreamer.EmitRawText(OS.str()); } bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode); + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode); + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); }; } // end of anonymous namespace @@ -69,8 +71,9 @@ extern "C" void LLVMInitializeBlackfinAsmPrinter() { RegisterAsmPrinter<BlackfinAsmPrinter> X(TheBlackfinTarget); } -void BlackfinAsmPrinter::printOperand(const MachineInstr *MI, int opNum) { - const MachineOperand &MO = MI->getOperand (opNum); +void BlackfinAsmPrinter::printOperand(const MachineInstr *MI, int opNum, + raw_ostream &O) { + const MachineOperand &MO = MI->getOperand(opNum); switch (MO.getType()) { case MachineOperand::MO_Register: assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && @@ -86,7 +89,7 @@ void BlackfinAsmPrinter::printOperand(const MachineInstr *MI, int opNum) { return; case MachineOperand::MO_GlobalAddress: O << *Mang->getSymbol(MO.getGlobal()); - printOffset(MO.getOffset()); + printOffset(MO.getOffset(), O); break; case MachineOperand::MO_ExternalSymbol: O << *GetExternalSymbolSymbol(MO.getSymbolName()); @@ -105,22 +108,23 @@ void BlackfinAsmPrinter::printOperand(const MachineInstr *MI, int opNum) { } } -void BlackfinAsmPrinter::printMemoryOperand(const MachineInstr *MI, int opNum) { - printOperand(MI, opNum); +void BlackfinAsmPrinter::printMemoryOperand(const MachineInstr *MI, int opNum, + raw_ostream &O) { + printOperand(MI, opNum, O); if (MI->getOperand(opNum+1).isImm() && MI->getOperand(opNum+1).getImm() == 0) return; O << " + "; - printOperand(MI, opNum+1); + printOperand(MI, opNum+1, O); } /// PrintAsmOperand - Print out an operand for an inline asm expression. /// bool BlackfinAsmPrinter::PrintAsmOperand(const MachineInstr *MI, - unsigned OpNo, - unsigned AsmVariant, - const char *ExtraCode) { + unsigned OpNo, unsigned AsmVariant, + const char *ExtraCode, + raw_ostream &O) { if (ExtraCode && ExtraCode[0]) { if (ExtraCode[1] != 0) return true; // Unknown modifier. @@ -131,7 +135,7 @@ bool BlackfinAsmPrinter::PrintAsmOperand(const MachineInstr *MI, } } - printOperand(MI, OpNo); + printOperand(MI, OpNo, O); return false; } @@ -139,12 +143,13 @@ bool BlackfinAsmPrinter::PrintAsmOperand(const MachineInstr *MI, bool BlackfinAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, - const char *ExtraCode) { + const char *ExtraCode, + raw_ostream &O) { if (ExtraCode && ExtraCode[0]) return true; // Unknown modifier O << '['; - printOperand(MI, OpNo); + printOperand(MI, OpNo, O); O << ']'; return false; diff --git a/lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp b/lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp index 857ddcf92a5f..0ef36e550d03 100644 --- a/lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp +++ b/lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp @@ -30,17 +30,17 @@ #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetRegistry.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; namespace { class SPUAsmPrinter : public AsmPrinter { public: - explicit SPUAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, - MCStreamer &Streamer) : - AsmPrinter(O, TM, Streamer) {} + explicit SPUAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) : + AsmPrinter(TM, Streamer) {} virtual const char *getPassName() const { return "STI CBEA SPU Assembly Printer"; @@ -52,44 +52,48 @@ namespace { /// printInstruction - This method is automatically generated by tablegen /// from the instruction set description. - void printInstruction(const MachineInstr *MI); + void printInstruction(const MachineInstr *MI, raw_ostream &OS); static const char *getRegisterName(unsigned RegNo); void EmitInstruction(const MachineInstr *MI) { - printInstruction(MI); - OutStreamer.AddBlankLine(); + SmallString<128> Str; + raw_svector_ostream OS(Str); + printInstruction(MI, OS); + OutStreamer.EmitRawText(OS.str()); } - void printOp(const MachineOperand &MO); + void printOp(const MachineOperand &MO, raw_ostream &OS); /// printRegister - Print register according to target requirements. /// - void printRegister(const MachineOperand &MO, bool R0AsZero) { + void printRegister(const MachineOperand &MO, bool R0AsZero, raw_ostream &O){ unsigned RegNo = MO.getReg(); assert(TargetRegisterInfo::isPhysicalRegister(RegNo) && "Not physreg??"); O << getRegisterName(RegNo); } - void printOperand(const MachineInstr *MI, unsigned OpNo) { + void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { const MachineOperand &MO = MI->getOperand(OpNo); if (MO.isReg()) { O << getRegisterName(MO.getReg()); } else if (MO.isImm()) { O << MO.getImm(); } else { - printOp(MO); + printOp(MO, O); } } bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode); + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode); + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); void - printS7ImmOperand(const MachineInstr *MI, unsigned OpNo) + printS7ImmOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { int value = MI->getOperand(OpNo).getImm(); value = (value << (32 - 7)) >> (32 - 7); @@ -100,7 +104,7 @@ namespace { } void - printU7ImmOperand(const MachineInstr *MI, unsigned OpNo) + printU7ImmOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { unsigned int value = MI->getOperand(OpNo).getImm(); assert(value < (1 << 8) && "Invalid u7 argument"); @@ -108,45 +112,45 @@ namespace { } void - printShufAddr(const MachineInstr *MI, unsigned OpNo) + printShufAddr(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { char value = MI->getOperand(OpNo).getImm(); O << (int) value; O << "("; - printOperand(MI, OpNo+1); + printOperand(MI, OpNo+1, O); O << ")"; } void - printS16ImmOperand(const MachineInstr *MI, unsigned OpNo) + printS16ImmOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { O << (short) MI->getOperand(OpNo).getImm(); } void - printU16ImmOperand(const MachineInstr *MI, unsigned OpNo) + printU16ImmOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { O << (unsigned short)MI->getOperand(OpNo).getImm(); } void - printU32ImmOperand(const MachineInstr *MI, unsigned OpNo) + printU32ImmOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { O << (unsigned)MI->getOperand(OpNo).getImm(); } void - printMemRegReg(const MachineInstr *MI, unsigned OpNo) { + printMemRegReg(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { // When used as the base register, r0 reads constant zero rather than // the value contained in the register. For this reason, the darwin // assembler requires that we print r0 as 0 (no r) when used as the base. const MachineOperand &MO = MI->getOperand(OpNo); O << getRegisterName(MO.getReg()) << ", "; - printOperand(MI, OpNo+1); + printOperand(MI, OpNo+1, O); } void - printU18ImmOperand(const MachineInstr *MI, unsigned OpNo) + printU18ImmOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { unsigned int value = MI->getOperand(OpNo).getImm(); assert(value <= (1 << 19) - 1 && "Invalid u18 argument"); @@ -154,7 +158,7 @@ namespace { } void - printS10ImmOperand(const MachineInstr *MI, unsigned OpNo) + printS10ImmOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16) >> 16); @@ -164,7 +168,7 @@ namespace { } void - printU10ImmOperand(const MachineInstr *MI, unsigned OpNo) + printU10ImmOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16) >> 16); @@ -173,7 +177,7 @@ namespace { } void - printDFormAddr(const MachineInstr *MI, unsigned OpNo) + printDFormAddr(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { assert(MI->getOperand(OpNo).isImm() && "printDFormAddr first operand is not immediate"); @@ -182,18 +186,18 @@ namespace { assert((value16 >= -(1 << (9+4)) && value16 <= (1 << (9+4)) - 1) && "Invalid dform s10 offset argument"); O << (value16 & ~0xf) << "("; - printOperand(MI, OpNo+1); + printOperand(MI, OpNo+1, O); O << ")"; } void - printAddr256K(const MachineInstr *MI, unsigned OpNo) + printAddr256K(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { /* Note: operand 1 is an offset or symbol name. */ if (MI->getOperand(OpNo).isImm()) { - printS16ImmOperand(MI, OpNo); + printS16ImmOperand(MI, OpNo, O); } else { - printOp(MI->getOperand(OpNo)); + printOp(MI->getOperand(OpNo), O); if (MI->getOperand(OpNo+1).isImm()) { int displ = int(MI->getOperand(OpNo+1).getImm()); if (displ > 0) @@ -204,50 +208,51 @@ namespace { } } - void printCallOperand(const MachineInstr *MI, unsigned OpNo) { - printOp(MI->getOperand(OpNo)); + void printCallOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { + printOp(MI->getOperand(OpNo), O); } - void printPCRelativeOperand(const MachineInstr *MI, unsigned OpNo) { + void printPCRelativeOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { // Used to generate a ".-<target>", but it turns out that the assembler // really wants the target. // // N.B.: This operand is used for call targets. Branch hints are another // animal entirely. - printOp(MI->getOperand(OpNo)); + printOp(MI->getOperand(OpNo), O); } - void printHBROperand(const MachineInstr *MI, unsigned OpNo) { + void printHBROperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { // HBR operands are generated in front of branches, hence, the // program counter plus the target. O << ".+"; - printOp(MI->getOperand(OpNo)); + printOp(MI->getOperand(OpNo), O); } - void printSymbolHi(const MachineInstr *MI, unsigned OpNo) { + void printSymbolHi(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { if (MI->getOperand(OpNo).isImm()) { - printS16ImmOperand(MI, OpNo); + printS16ImmOperand(MI, OpNo, O); } else { - printOp(MI->getOperand(OpNo)); + printOp(MI->getOperand(OpNo), O); O << "@h"; } } - void printSymbolLo(const MachineInstr *MI, unsigned OpNo) { + void printSymbolLo(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { if (MI->getOperand(OpNo).isImm()) { - printS16ImmOperand(MI, OpNo); + printS16ImmOperand(MI, OpNo, O); } else { - printOp(MI->getOperand(OpNo)); + printOp(MI->getOperand(OpNo), O); O << "@l"; } } /// Print local store address - void printSymbolLSA(const MachineInstr *MI, unsigned OpNo) { - printOp(MI->getOperand(OpNo)); + void printSymbolLSA(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { + printOp(MI->getOperand(OpNo), O); } - void printROTHNeg7Imm(const MachineInstr *MI, unsigned OpNo) { + void printROTHNeg7Imm(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { if (MI->getOperand(OpNo).isImm()) { int value = (int) MI->getOperand(OpNo).getImm(); assert((value >= 0 && value < 16) @@ -258,15 +263,13 @@ namespace { } } - void printROTNeg7Imm(const MachineInstr *MI, unsigned OpNo) { - if (MI->getOperand(OpNo).isImm()) { - int value = (int) MI->getOperand(OpNo).getImm(); - assert((value >= 0 && value <= 32) - && "Invalid negated immediate rotate 7-bit argument"); - O << -value; - } else { - llvm_unreachable("Invalid/non-immediate rotate amount in printRotateNeg7Imm"); - } + void printROTNeg7Imm(const MachineInstr *MI, unsigned OpNo, raw_ostream &O){ + assert(MI->getOperand(OpNo).isImm() && + "Invalid/non-immediate rotate amount in printRotateNeg7Imm"); + int value = (int) MI->getOperand(OpNo).getImm(); + assert((value >= 0 && value <= 32) + && "Invalid negated immediate rotate 7-bit argument"); + O << -value; } }; } // end of anonymous namespace @@ -274,7 +277,7 @@ namespace { // Include the auto-generated portion of the assembly writer #include "SPUGenAsmWriter.inc" -void SPUAsmPrinter::printOp(const MachineOperand &MO) { +void SPUAsmPrinter::printOp(const MachineOperand &MO, raw_ostream &O) { switch (MO.getType()) { case MachineOperand::MO_Immediate: llvm_report_error("printOp() does not handle immediate values"); @@ -323,7 +326,7 @@ void SPUAsmPrinter::printOp(const MachineOperand &MO) { /// bool SPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, - const char *ExtraCode) { + const char *ExtraCode, raw_ostream &O) { // Does this asm operand have a single letter operand modifier? if (ExtraCode && ExtraCode[0]) { if (ExtraCode[1] != 0) return true; // Unknown modifier. @@ -341,17 +344,17 @@ bool SPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, } } - printOperand(MI, OpNo); + printOperand(MI, OpNo, O); return false; } bool SPUAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, - unsigned OpNo, - unsigned AsmVariant, - const char *ExtraCode) { + unsigned OpNo, unsigned AsmVariant, + const char *ExtraCode, + raw_ostream &O) { if (ExtraCode && ExtraCode[0]) return true; // Unknown modifier. - printMemRegReg(MI, OpNo); + printMemRegReg(MI, OpNo, O); return false; } diff --git a/lib/Target/CellSPU/SPURegisterInfo.cpp b/lib/Target/CellSPU/SPURegisterInfo.cpp index ad034ebcd839..ffac58182aec 100644 --- a/lib/Target/CellSPU/SPURegisterInfo.cpp +++ b/lib/Target/CellSPU/SPURegisterInfo.cpp @@ -451,11 +451,11 @@ void SPURegisterInfo::emitPrologue(MachineFunction &MF) const MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB MachineBasicBlock::iterator MBBI = MBB.begin(); MachineFrameInfo *MFI = MF.getFrameInfo(); - MachineModuleInfo *MMI = MFI->getMachineModuleInfo(); + MachineModuleInfo &MMI = MF.getMMI(); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); // Prepare for debug frame info. - bool hasDebugInfo = MMI && MMI->hasDebugInfo(); + bool hasDebugInfo = MMI.hasDebugInfo(); MCSymbol *FrameLabel = 0; // Move MBBI back to the beginning of the function. @@ -473,7 +473,7 @@ void SPURegisterInfo::emitPrologue(MachineFunction &MF) const FrameSize = -(FrameSize + SPUFrameInfo::minStackSize()); if (hasDebugInfo) { // Mark effective beginning of when frame pointer becomes valid. - FrameLabel = MMI->getContext().CreateTempSymbol(); + FrameLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(SPU::DBG_LABEL)).addSym(FrameLabel); } @@ -516,7 +516,7 @@ void SPURegisterInfo::emitPrologue(MachineFunction &MF) const } if (hasDebugInfo) { - std::vector<MachineMove> &Moves = MMI->getFrameMoves(); + std::vector<MachineMove> &Moves = MMI.getFrameMoves(); // Show update of SP. MachineLocation SPDst(MachineLocation::VirtualFP); @@ -535,7 +535,7 @@ void SPURegisterInfo::emitPrologue(MachineFunction &MF) const } // Mark effective beginning of when frame pointer is ready. - MCSymbol *ReadyLabel = MMI->getContext().CreateTempSymbol(); + MCSymbol *ReadyLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(SPU::DBG_LABEL)).addSym(ReadyLabel); MachineLocation FPDst(SPU::R1); @@ -552,7 +552,7 @@ void SPURegisterInfo::emitPrologue(MachineFunction &MF) const // Insert terminator label BuildMI(MBB, MBBI, dl, TII.get(SPU::DBG_LABEL)) - .addSym(MMI->getContext().CreateTempSymbol()); + .addSym(MMI.getContext().CreateTempSymbol()); } } } diff --git a/lib/Target/MBlaze/AsmPrinter/MBlazeAsmPrinter.cpp b/lib/Target/MBlaze/AsmPrinter/MBlazeAsmPrinter.cpp index ee2c7c8e05fb..b1df926864e6 100644 --- a/lib/Target/MBlaze/AsmPrinter/MBlazeAsmPrinter.cpp +++ b/lib/Target/MBlaze/AsmPrinter/MBlazeAsmPrinter.cpp @@ -23,7 +23,6 @@ #include "llvm/DerivedTypes.h" #include "llvm/Module.h" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/DwarfWriter.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -37,13 +36,10 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegistry.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/Support/MathExtras.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" #include <cctype> using namespace llvm; @@ -52,9 +48,8 @@ namespace { class MBlazeAsmPrinter : public AsmPrinter { const MBlazeSubtarget *Subtarget; public: - explicit MBlazeAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, - MCStreamer &Streamer) - : AsmPrinter(O, TM, Streamer) { + explicit MBlazeAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : AsmPrinter(TM, Streamer) { Subtarget = &TM.getSubtarget<MBlazeSubtarget>(); } @@ -63,31 +58,32 @@ namespace { } bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode); - void printOperand(const MachineInstr *MI, int opNum); - void printUnsignedImm(const MachineInstr *MI, int opNum); - void printFSLImm(const MachineInstr *MI, int opNum); - void printMemOperand(const MachineInstr *MI, int opNum, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); + void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); + void printUnsignedImm(const MachineInstr *MI, int opNum, raw_ostream &O); + void printFSLImm(const MachineInstr *MI, int opNum, raw_ostream &O); + void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O, const char *Modifier = 0); - void printFCCOperand(const MachineInstr *MI, int opNum, + void printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O, const char *Modifier = 0); - void printSavedRegsBitmask(); - void printHex32(unsigned int Value); + void printSavedRegsBitmask(raw_ostream &OS); const char *emitCurrentABIString(); void emitFrameDirective(); - void printInstruction(const MachineInstr *MI); // autogenerated. + void printInstruction(const MachineInstr *MI, raw_ostream &O); void EmitInstruction(const MachineInstr *MI) { - printInstruction(MI); - O << '\n'; + SmallString<128> Str; + raw_svector_ostream OS(Str); + printInstruction(MI, OS); + OutStreamer.EmitRawText(OS.str()); } virtual void EmitFunctionBodyStart(); virtual void EmitFunctionBodyEnd(); static const char *getRegisterName(unsigned RegNo); virtual void EmitFunctionEntryLabel(); - void EmitStartOfAsmFile(Module &M); }; } // end of anonymous namespace @@ -128,9 +124,17 @@ namespace { // Mask directives //===----------------------------------------------------------------------===// +// Print a 32 bit hex number with all numbers. +static void printHex32(unsigned int Value, raw_ostream &O) { + O << "0x"; + for (int i = 7; i >= 0; i--) + O << utohexstr((Value & (0xF << (i*4))) >> (i*4)); +} + + // Create a bitmask with all callee saved registers for CPU or Floating Point // registers. For CPU registers consider RA, GP and FP for saving if necessary. -void MBlazeAsmPrinter::printSavedRegsBitmask() { +void MBlazeAsmPrinter::printSavedRegsBitmask(raw_ostream &O) { const TargetRegisterInfo &RI = *TM.getRegisterInfo(); const MBlazeFunctionInfo *MBlazeFI = MF->getInfo<MBlazeFunctionInfo>(); @@ -156,15 +160,8 @@ void MBlazeAsmPrinter::printSavedRegsBitmask() { getRegisterNumbering(RI.getRARegister())); // Print CPUBitmask - O << "\t.mask \t"; printHex32(CPUBitmask); O << ',' - << MBlazeFI->getCPUTopSavedRegOff() << '\n'; -} - -// Print a 32 bit hex number with all numbers. -void MBlazeAsmPrinter::printHex32(unsigned int Value) { - O << "0x"; - for (int i = 7; i >= 0; i--) - O << utohexstr( (Value & (0xF << (i*4))) >> (i*4) ); + O << "\t.mask \t"; printHex32(CPUBitmask, O); + O << ',' << MBlazeFI->getCPUTopSavedRegOff() << '\n'; } //===----------------------------------------------------------------------===// @@ -180,122 +177,127 @@ void MBlazeAsmPrinter::emitFrameDirective() { unsigned stackSize = MF->getFrameInfo()->getStackSize(); - O << "\t.frame\t" << getRegisterName(stackReg) - << ',' << stackSize << ',' - << getRegisterName(returnReg) - << '\n'; + OutStreamer.EmitRawText("\t.frame\t" + Twine(getRegisterName(stackReg)) + + "," + Twine(stackSize) + "," + + Twine(getRegisterName(returnReg))); } void MBlazeAsmPrinter::EmitFunctionEntryLabel() { - O << "\t.ent\t" << *CurrentFnSym << '\n'; - OutStreamer.EmitLabel(CurrentFnSym); + OutStreamer.EmitRawText("\t.ent\t" + Twine(CurrentFnSym->getName())); + OutStreamer.EmitLabel(CurrentFnSym); } /// EmitFunctionBodyStart - Targets can override this to emit stuff before /// the first basic block in the function. void MBlazeAsmPrinter::EmitFunctionBodyStart() { emitFrameDirective(); - printSavedRegsBitmask(); + + SmallString<128> Str; + raw_svector_ostream OS(Str); + printSavedRegsBitmask(OS); + OutStreamer.EmitRawText(OS.str()); } /// EmitFunctionBodyEnd - Targets can override this to emit stuff after /// the last basic block in the function. void MBlazeAsmPrinter::EmitFunctionBodyEnd() { - O << "\t.end\t" << *CurrentFnSym << '\n'; + OutStreamer.EmitRawText("\t.end\t" + Twine(CurrentFnSym->getName())); } // Print out an operand for an inline asm expression. bool MBlazeAsmPrinter:: PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant,const char *ExtraCode){ + unsigned AsmVariant,const char *ExtraCode, raw_ostream &O) { // Does this asm operand have a single letter operand modifier? if (ExtraCode && ExtraCode[0]) return true; // Unknown modifier. - printOperand(MI, OpNo); + printOperand(MI, OpNo, O); return false; } -void MBlazeAsmPrinter::printOperand(const MachineInstr *MI, int opNum) { +void MBlazeAsmPrinter::printOperand(const MachineInstr *MI, int opNum, + raw_ostream &O) { const MachineOperand &MO = MI->getOperand(opNum); switch (MO.getType()) { - case MachineOperand::MO_Register: - O << getRegisterName(MO.getReg()); - break; - - case MachineOperand::MO_Immediate: - O << (int)MO.getImm(); - break; - - case MachineOperand::MO_FPImmediate: { - const ConstantFP* fp = MO.getFPImm(); - printHex32(fp->getValueAPF().bitcastToAPInt().getZExtValue()); - O << ";\t# immediate = " << *fp; - break; - } - - case MachineOperand::MO_MachineBasicBlock: - O << *MO.getMBB()->getSymbol(); - return; - - case MachineOperand::MO_GlobalAddress: - O << *Mang->getSymbol(MO.getGlobal()); - break; - - case MachineOperand::MO_ExternalSymbol: - O << *GetExternalSymbolSymbol(MO.getSymbolName()); - break; - - case MachineOperand::MO_JumpTableIndex: - O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() - << '_' << MO.getIndex(); - break; - - case MachineOperand::MO_ConstantPoolIndex: - O << MAI->getPrivateGlobalPrefix() << "CPI" - << getFunctionNumber() << "_" << MO.getIndex(); - if (MO.getOffset()) - O << "+" << MO.getOffset(); - break; - - default: - llvm_unreachable("<unknown operand type>"); + case MachineOperand::MO_Register: + O << getRegisterName(MO.getReg()); + break; + + case MachineOperand::MO_Immediate: + O << (int)MO.getImm(); + break; + + case MachineOperand::MO_FPImmediate: { + const ConstantFP *fp = MO.getFPImm(); + printHex32(fp->getValueAPF().bitcastToAPInt().getZExtValue(), O); + O << ";\t# immediate = " << *fp; + break; + } + + case MachineOperand::MO_MachineBasicBlock: + O << *MO.getMBB()->getSymbol(); + return; + + case MachineOperand::MO_GlobalAddress: + O << *Mang->getSymbol(MO.getGlobal()); + break; + + case MachineOperand::MO_ExternalSymbol: + O << *GetExternalSymbolSymbol(MO.getSymbolName()); + break; + + case MachineOperand::MO_JumpTableIndex: + O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << '_' << MO.getIndex(); + break; + + case MachineOperand::MO_ConstantPoolIndex: + O << MAI->getPrivateGlobalPrefix() << "CPI" + << getFunctionNumber() << "_" << MO.getIndex(); + if (MO.getOffset()) + O << "+" << MO.getOffset(); + break; + + default: + llvm_unreachable("<unknown operand type>"); } } -void MBlazeAsmPrinter::printUnsignedImm(const MachineInstr *MI, int opNum) { +void MBlazeAsmPrinter::printUnsignedImm(const MachineInstr *MI, int opNum, + raw_ostream &O) { const MachineOperand &MO = MI->getOperand(opNum); if (MO.getType() == MachineOperand::MO_Immediate) O << (unsigned int)MO.getImm(); else - printOperand(MI, opNum); + printOperand(MI, opNum, O); } -void MBlazeAsmPrinter::printFSLImm(const MachineInstr *MI, int opNum) { +void MBlazeAsmPrinter::printFSLImm(const MachineInstr *MI, int opNum, + raw_ostream &O) { const MachineOperand &MO = MI->getOperand(opNum); if (MO.getType() == MachineOperand::MO_Immediate) O << "rfsl" << (unsigned int)MO.getImm(); else - printOperand(MI, opNum); + printOperand(MI, opNum, O); } void MBlazeAsmPrinter:: -printMemOperand(const MachineInstr *MI, int opNum, const char *Modifier) { - printOperand(MI, opNum+1); +printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O, + const char *Modifier) { + printOperand(MI, opNum+1, O); O << ", "; - printOperand(MI, opNum); + printOperand(MI, opNum, O); } void MBlazeAsmPrinter:: -printFCCOperand(const MachineInstr *MI, int opNum, const char *Modifier) { +printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O, + const char *Modifier) { const MachineOperand& MO = MI->getOperand(opNum); O << MBlaze::MBlazeFCCToString((MBlaze::CondCode)MO.getImm()); } -void MBlazeAsmPrinter::EmitStartOfAsmFile(Module &M) { -} - // Force static initialization. extern "C" void LLVMInitializeMBlazeAsmPrinter() { RegisterAsmPrinter<MBlazeAsmPrinter> X(TheMBlazeTarget); diff --git a/lib/Target/MBlaze/MBlaze.td b/lib/Target/MBlaze/MBlaze.td index 16797529cb28..482ddd3963fb 100644 --- a/lib/Target/MBlaze/MBlaze.td +++ b/lib/Target/MBlaze/MBlaze.td @@ -25,11 +25,7 @@ include "MBlazeIntrinsics.td" include "MBlazeInstrInfo.td" include "MBlazeCallingConv.td" -def MBlazeInstrInfo : InstrInfo { - let TSFlagsFields = []; - let TSFlagsShifts = []; -} - +def MBlazeInstrInfo : InstrInfo; //===----------------------------------------------------------------------===// // Microblaze Subtarget features // diff --git a/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp b/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp index 04ac6f1949f1..56f72bbc1474 100644 --- a/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp +++ b/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp @@ -24,7 +24,6 @@ #include "llvm/Module.h" #include "llvm/Assembly/Writer.h" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/DwarfWriter.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineConstantPool.h" @@ -36,50 +35,36 @@ #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetRegistry.h" -#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; namespace { class MSP430AsmPrinter : public AsmPrinter { public: - MSP430AsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, - MCStreamer &Streamer) - : AsmPrinter(O, TM, Streamer) {} + MSP430AsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : AsmPrinter(TM, Streamer) {} virtual const char *getPassName() const { return "MSP430 Assembly Printer"; } - void printMCInst(const MCInst *MI) { - MSP430InstPrinter(O, *MAI).printInstruction(MI); - } void printOperand(const MachineInstr *MI, int OpNum, - const char* Modifier = 0); - void printPCRelImmOperand(const MachineInstr *MI, int OpNum) { - printOperand(MI, OpNum); - } + raw_ostream &O, const char* Modifier = 0); void printSrcMemOperand(const MachineInstr *MI, int OpNum, - const char* Modifier = 0); - void printCCOperand(const MachineInstr *MI, int OpNum); - void printMachineInstruction(const MachineInstr * MI); + raw_ostream &O); bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, - const char *ExtraCode); + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, - const char *ExtraCode); + const char *ExtraCode, raw_ostream &O); void EmitInstruction(const MachineInstr *MI); - - void getAnalysisUsage(AnalysisUsage &AU) const { - AsmPrinter::getAnalysisUsage(AU); - AU.setPreservesAll(); - } }; } // end of anonymous namespace void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum, - const char* Modifier) { + raw_ostream &O, const char *Modifier) { const MachineOperand &MO = MI->getOperand(OpNum); switch (MO.getType()) { default: assert(0 && "Not implemented yet!"); @@ -126,7 +111,7 @@ void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum, } void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum, - const char* Modifier) { + raw_ostream &O) { const MachineOperand &Base = MI->getOperand(OpNum); const MachineOperand &Disp = MI->getOperand(OpNum+1); @@ -135,48 +120,37 @@ void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum, // Imm here is in fact global address - print extra modifier. if (Disp.isImm() && !Base.getReg()) O << '&'; - printOperand(MI, OpNum+1, "nohash"); + printOperand(MI, OpNum+1, O, "nohash"); // Print register base field if (Base.getReg()) { O << '('; - printOperand(MI, OpNum); + printOperand(MI, OpNum, O); O << ')'; } } -void MSP430AsmPrinter::printCCOperand(const MachineInstr *MI, int OpNum) { - switch (MI->getOperand(OpNum).getImm()) { - default: assert(0 && "Unknown cond"); - case MSP430CC::COND_E: O << "eq"; break; - case MSP430CC::COND_NE: O << "ne"; break; - case MSP430CC::COND_HS: O << "hs"; break; - case MSP430CC::COND_LO: O << "lo"; break; - case MSP430CC::COND_GE: O << "ge"; break; - case MSP430CC::COND_L: O << 'l'; break; - } -} - /// PrintAsmOperand - Print out an operand for an inline asm expression. /// bool MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, - const char *ExtraCode) { + const char *ExtraCode, raw_ostream &O) { // Does this asm operand have a single letter operand modifier? if (ExtraCode && ExtraCode[0]) return true; // Unknown modifier. - printOperand(MI, OpNo); + printOperand(MI, OpNo, O); return false; } bool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, - const char *ExtraCode) { + const char *ExtraCode, + raw_ostream &O) { if (ExtraCode && ExtraCode[0]) { return true; // Unknown modifier. } - printSrcMemOperand(MI, OpNo); + printSrcMemOperand(MI, OpNo, O); return false; } @@ -191,10 +165,9 @@ void MSP430AsmPrinter::EmitInstruction(const MachineInstr *MI) { static MCInstPrinter *createMSP430MCInstPrinter(const Target &T, unsigned SyntaxVariant, - const MCAsmInfo &MAI, - raw_ostream &O) { + const MCAsmInfo &MAI) { if (SyntaxVariant == 0) - return new MSP430InstPrinter(O, MAI); + return new MSP430InstPrinter(MAI); return 0; } diff --git a/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp b/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp index d7636e68a0d6..c15d4085bc8b 100644 --- a/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp +++ b/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp @@ -28,11 +28,12 @@ using namespace llvm; #include "MSP430GenAsmWriter.inc" #undef MachineInstr -void MSP430InstPrinter::printInst(const MCInst *MI) { - printInstruction(MI); +void MSP430InstPrinter::printInst(const MCInst *MI, raw_ostream &O) { + printInstruction(MI, O); } -void MSP430InstPrinter::printPCRelImmOperand(const MCInst *MI, unsigned OpNo) { +void MSP430InstPrinter::printPCRelImmOperand(const MCInst *MI, unsigned OpNo, + raw_ostream &O) { const MCOperand &Op = MI->getOperand(OpNo); if (Op.isImm()) O << Op.getImm(); @@ -43,7 +44,7 @@ void MSP430InstPrinter::printPCRelImmOperand(const MCInst *MI, unsigned OpNo) { } void MSP430InstPrinter::printOperand(const MCInst *MI, unsigned OpNo, - const char *Modifier) { + raw_ostream &O, const char *Modifier) { assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported"); const MCOperand &Op = MI->getOperand(OpNo); if (Op.isReg()) { @@ -57,6 +58,7 @@ void MSP430InstPrinter::printOperand(const MCInst *MI, unsigned OpNo, } void MSP430InstPrinter::printSrcMemOperand(const MCInst *MI, unsigned OpNo, + raw_ostream &O, const char *Modifier) { const MCOperand &Base = MI->getOperand(OpNo); const MCOperand &Disp = MI->getOperand(OpNo+1); @@ -84,7 +86,8 @@ void MSP430InstPrinter::printSrcMemOperand(const MCInst *MI, unsigned OpNo, O << '(' << getRegisterName(Base.getReg()) << ')'; } -void MSP430InstPrinter::printCCOperand(const MCInst *MI, unsigned OpNo) { +void MSP430InstPrinter::printCCOperand(const MCInst *MI, unsigned OpNo, + raw_ostream &O) { unsigned CC = MI->getOperand(OpNo).getImm(); switch (CC) { diff --git a/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.h b/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.h index 2fac800fcd79..f0e1ce22841b 100644 --- a/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.h +++ b/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.h @@ -16,29 +16,26 @@ #include "llvm/MC/MCInstPrinter.h" -namespace llvm -{ - +namespace llvm { class MCOperand; class MSP430InstPrinter : public MCInstPrinter { public: - MSP430InstPrinter(raw_ostream &O, const MCAsmInfo &MAI) : - MCInstPrinter(O, MAI){ + MSP430InstPrinter(const MCAsmInfo &MAI) : MCInstPrinter(MAI) { } - virtual void printInst(const MCInst *MI); + virtual void printInst(const MCInst *MI, raw_ostream &O); // Autogenerated by tblgen. - void printInstruction(const MCInst *MI); + void printInstruction(const MCInst *MI, raw_ostream &O); static const char *getRegisterName(unsigned RegNo); - void printOperand(const MCInst *MI, unsigned OpNo, + void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O, const char *Modifier = 0); - void printPCRelImmOperand(const MCInst *MI, unsigned OpNo); - void printSrcMemOperand(const MCInst *MI, unsigned OpNo, + void printPCRelImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); + void printSrcMemOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O, const char *Modifier = 0); - void printCCOperand(const MCInst *MI, unsigned OpNo); + void printCCOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); }; } diff --git a/lib/Target/MSP430/MSP430.td b/lib/Target/MSP430/MSP430.td index fe533d3d2e5c..0f08e3d8ca0f 100644 --- a/lib/Target/MSP430/MSP430.td +++ b/lib/Target/MSP430/MSP430.td @@ -48,14 +48,7 @@ include "MSP430CallingConv.td" include "MSP430InstrInfo.td" -def MSP430InstrInfo : InstrInfo { - // Define how we want to layout our TargetSpecific information field... This - // should be kept up-to-date with the fields in the MSP430InstrInfo.h file. - let TSFlagsFields = ["FormBits", - "Size"]; - let TSFlagsShifts = [0, - 2]; -} +def MSP430InstrInfo : InstrInfo; def MSP430InstPrinter : AsmWriter { string AsmWriterClassName = "InstPrinter"; diff --git a/lib/Target/MSP430/MSP430InstrFormats.td b/lib/Target/MSP430/MSP430InstrFormats.td index 4ccc7df57664..73aef1facc0f 100644 --- a/lib/Target/MSP430/MSP430InstrFormats.td +++ b/lib/Target/MSP430/MSP430InstrFormats.td @@ -61,10 +61,12 @@ class MSP430Inst<dag outs, dag ins, SizeVal sz, Format f, dag InOperandList = ins; Format Form = f; - bits<2> FormBits = Form.Value; - SizeVal Sz = sz; - bits<3> Size = Sz.Value; + + // Define how we want to layout our TargetSpecific information field... This + // should be kept up-to-date with the fields in the MSP430InstrInfo.h file. + let TSFlags{1-0} = Form.Value; + let TSFlags{4-2} = Sz.Value; let AsmString = asmstr; } diff --git a/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp b/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp index 2a2d9dcaf5a6..69743715607d 100644 --- a/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp @@ -13,17 +13,12 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "mips-asm-printer" - #include "Mips.h" #include "MipsSubtarget.h" #include "MipsInstrInfo.h" #include "MipsTargetMachine.h" #include "MipsMachineFunction.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Module.h" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/DwarfWriter.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -37,22 +32,18 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegistry.h" -#include "llvm/Support/ErrorHandling.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/Support/MathExtras.h" -#include <cctype> +#include "llvm/ADT/Twine.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; namespace { class MipsAsmPrinter : public AsmPrinter { const MipsSubtarget *Subtarget; public: - explicit MipsAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, - MCStreamer &Streamer) - : AsmPrinter(O, TM, Streamer) { + explicit MipsAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : AsmPrinter(TM, Streamer) { Subtarget = &TM.getSubtarget<MipsSubtarget>(); } @@ -61,23 +52,26 @@ namespace { } bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode); - void printOperand(const MachineInstr *MI, int opNum); - void printUnsignedImm(const MachineInstr *MI, int opNum); - void printMemOperand(const MachineInstr *MI, int opNum, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); + void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); + void printUnsignedImm(const MachineInstr *MI, int opNum, raw_ostream &O); + void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O, const char *Modifier = 0); - void printFCCOperand(const MachineInstr *MI, int opNum, + void printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O, const char *Modifier = 0); - void printSavedRegsBitmask(); - void printHex32(unsigned int Value); + void printSavedRegsBitmask(raw_ostream &O); + void printHex32(unsigned int Value, raw_ostream &O); - const char *emitCurrentABIString(); + const char *getCurrentABIString() const; void emitFrameDirective(); - void printInstruction(const MachineInstr *MI); // autogenerated. + void printInstruction(const MachineInstr *MI, raw_ostream &O); // autogen'd. void EmitInstruction(const MachineInstr *MI) { - printInstruction(MI); - OutStreamer.AddBlankLine(); + SmallString<128> Str; + raw_svector_ostream OS(Str); + printInstruction(MI, OS); + OutStreamer.EmitRawText(OS.str()); } virtual void EmitFunctionBodyStart(); virtual void EmitFunctionBodyEnd(); @@ -127,7 +121,7 @@ namespace { // Create a bitmask with all callee saved registers for CPU or Floating Point // registers. For CPU registers consider RA, GP and FP for saving if necessary. -void MipsAsmPrinter::printSavedRegsBitmask() { +void MipsAsmPrinter::printSavedRegsBitmask(raw_ostream &O) { const TargetRegisterInfo &RI = *TM.getRegisterInfo(); const MipsFunctionInfo *MipsFI = MF->getInfo<MipsFunctionInfo>(); @@ -156,21 +150,19 @@ void MipsAsmPrinter::printSavedRegsBitmask() { getRegisterNumbering(RI.getRARegister())); // Print CPUBitmask - O << "\t.mask \t"; printHex32(CPUBitmask); O << ',' - << MipsFI->getCPUTopSavedRegOff() << '\n'; + O << "\t.mask \t"; printHex32(CPUBitmask, O); + O << ',' << MipsFI->getCPUTopSavedRegOff() << '\n'; // Print FPUBitmask - O << "\t.fmask\t"; printHex32(FPUBitmask); O << "," + O << "\t.fmask\t"; printHex32(FPUBitmask, O); O << "," << MipsFI->getFPUTopSavedRegOff() << '\n'; } // Print a 32 bit hex number with all numbers. -void MipsAsmPrinter:: -printHex32(unsigned int Value) -{ +void MipsAsmPrinter::printHex32(unsigned Value, raw_ostream &O) { O << "0x"; for (int i = 7; i >= 0; i--) - O << utohexstr( (Value & (0xF << (i*4))) >> (i*4) ); + O << utohexstr((Value & (0xF << (i*4))) >> (i*4)); } //===----------------------------------------------------------------------===// @@ -185,22 +177,21 @@ void MipsAsmPrinter::emitFrameDirective() { unsigned returnReg = RI.getRARegister(); unsigned stackSize = MF->getFrameInfo()->getStackSize(); - - O << "\t.frame\t" << '$' << LowercaseString(getRegisterName(stackReg)) - << ',' << stackSize << ',' - << '$' << LowercaseString(getRegisterName(returnReg)) - << '\n'; + OutStreamer.EmitRawText("\t.frame\t$" + + Twine(LowercaseString(getRegisterName(stackReg))) + + "," + Twine(stackSize) + ",$" + + Twine(LowercaseString(getRegisterName(returnReg)))); } /// Emit Set directives. -const char *MipsAsmPrinter::emitCurrentABIString() { - switch(Subtarget->getTargetABI()) { - case MipsSubtarget::O32: return "abi32"; - case MipsSubtarget::O64: return "abiO64"; - case MipsSubtarget::N32: return "abiN32"; - case MipsSubtarget::N64: return "abi64"; - case MipsSubtarget::EABI: return "eabi32"; // TODO: handle eabi64 - default: break; +const char *MipsAsmPrinter::getCurrentABIString() const { + switch (Subtarget->getTargetABI()) { + case MipsSubtarget::O32: return "abi32"; + case MipsSubtarget::O64: return "abiO64"; + case MipsSubtarget::N32: return "abiN32"; + case MipsSubtarget::N64: return "abi64"; + case MipsSubtarget::EABI: return "eabi32"; // TODO: handle eabi64 + default: break; } llvm_unreachable("Unknown Mips ABI"); @@ -208,7 +199,7 @@ const char *MipsAsmPrinter::emitCurrentABIString() { } void MipsAsmPrinter::EmitFunctionEntryLabel() { - O << "\t.ent\t" << *CurrentFnSym << '\n'; + OutStreamer.EmitRawText("\t.ent\t" + Twine(CurrentFnSym->getName())); OutStreamer.EmitLabel(CurrentFnSym); } @@ -216,7 +207,11 @@ void MipsAsmPrinter::EmitFunctionEntryLabel() { /// the first basic block in the function. void MipsAsmPrinter::EmitFunctionBodyStart() { emitFrameDirective(); - printSavedRegsBitmask(); + + SmallString<128> Str; + raw_svector_ostream OS(Str); + printSavedRegsBitmask(OS); + OutStreamer.EmitRawText(OS.str()); } /// EmitFunctionBodyEnd - Targets can override this to emit stuff after @@ -225,25 +220,26 @@ void MipsAsmPrinter::EmitFunctionBodyEnd() { // There are instruction for this macros, but they must // always be at the function end, and we can't emit and // break with BB logic. - O << "\t.set\tmacro\n"; - O << "\t.set\treorder\n"; - - O << "\t.end\t" << *CurrentFnSym << '\n'; + OutStreamer.EmitRawText(StringRef("\t.set\tmacro")); + OutStreamer.EmitRawText(StringRef("\t.set\treorder")); + OutStreamer.EmitRawText("\t.end\t" + Twine(CurrentFnSym->getName())); } // Print out an operand for an inline asm expression. bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant,const char *ExtraCode){ + unsigned AsmVariant,const char *ExtraCode, + raw_ostream &O) { // Does this asm operand have a single letter operand modifier? if (ExtraCode && ExtraCode[0]) return true; // Unknown modifier. - printOperand(MI, OpNo); + printOperand(MI, OpNo, O); return false; } -void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum) { +void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, + raw_ostream &O) { const MachineOperand &MO = MI->getOperand(opNum); bool closeP = false; @@ -307,36 +303,39 @@ void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum) { if (closeP) O << ")"; } -void MipsAsmPrinter::printUnsignedImm(const MachineInstr *MI, int opNum) { +void MipsAsmPrinter::printUnsignedImm(const MachineInstr *MI, int opNum, + raw_ostream &O) { const MachineOperand &MO = MI->getOperand(opNum); if (MO.getType() == MachineOperand::MO_Immediate) O << (unsigned short int)MO.getImm(); else - printOperand(MI, opNum); + printOperand(MI, opNum, O); } void MipsAsmPrinter:: -printMemOperand(const MachineInstr *MI, int opNum, const char *Modifier) { +printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O, + const char *Modifier) { // when using stack locations for not load/store instructions // print the same way as all normal 3 operand instructions. if (Modifier && !strcmp(Modifier, "stackloc")) { - printOperand(MI, opNum+1); + printOperand(MI, opNum+1, O); O << ", "; - printOperand(MI, opNum); + printOperand(MI, opNum, O); return; } // Load/Store memory operands -- imm($reg) // If PIC target the target is loaded as the // pattern lw $25,%call16($28) - printOperand(MI, opNum); + printOperand(MI, opNum, O); O << "("; - printOperand(MI, opNum+1); + printOperand(MI, opNum+1, O); O << ")"; } void MipsAsmPrinter:: -printFCCOperand(const MachineInstr *MI, int opNum, const char *Modifier) { +printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O, + const char *Modifier) { const MachineOperand& MO = MI->getOperand(opNum); O << Mips::MipsFCCToString((Mips::CondCode)MO.getImm()); } @@ -345,15 +344,18 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { // FIXME: Use SwitchSection. // Tell the assembler which ABI we are using - O << "\t.section .mdebug." << emitCurrentABIString() << '\n'; + OutStreamer.EmitRawText("\t.section .mdebug." + Twine(getCurrentABIString())); // TODO: handle O64 ABI - if (Subtarget->isABI_EABI()) - O << "\t.section .gcc_compiled_long" << - (Subtarget->isGP32bit() ? "32" : "64") << '\n'; + if (Subtarget->isABI_EABI()) { + if (Subtarget->isGP32bit()) + OutStreamer.EmitRawText(StringRef("\t.section .gcc_compiled_long32")); + else + OutStreamer.EmitRawText(StringRef("\t.section .gcc_compiled_long64")); + } // return to previous section - O << "\t.previous" << '\n'; + OutStreamer.EmitRawText(StringRef("\t.previous")); } // Force static initialization. diff --git a/lib/Target/Mips/Mips.td b/lib/Target/Mips/Mips.td index 79a78d86aef7..aa036aef83d0 100644 --- a/lib/Target/Mips/Mips.td +++ b/lib/Target/Mips/Mips.td @@ -24,10 +24,7 @@ include "MipsSchedule.td" include "MipsInstrInfo.td" include "MipsCallingConv.td" -def MipsInstrInfo : InstrInfo { - let TSFlagsFields = []; - let TSFlagsShifts = []; -} +def MipsInstrInfo : InstrInfo; //===----------------------------------------------------------------------===// // Mips Subtarget features // diff --git a/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp b/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp index 1001d29fd8a4..c46db46ea5b4 100644 --- a/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp +++ b/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp @@ -19,9 +19,7 @@ #include "llvm/DerivedTypes.h" #include "llvm/Function.h" #include "llvm/Module.h" -#include "llvm/CodeGen/DwarfWriter.h" #include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/DwarfWriter.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" @@ -29,23 +27,26 @@ #include "llvm/Target/TargetRegistry.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallString.h" #include <cstring> using namespace llvm; #include "PIC16GenAsmWriter.inc" -PIC16AsmPrinter::PIC16AsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, - MCStreamer &Streamer) -: AsmPrinter(O, TM, Streamer), DbgInfo(O, TM.getMCAsmInfo()) { +PIC16AsmPrinter::PIC16AsmPrinter(TargetMachine &TM, MCStreamer &Streamer) +: AsmPrinter(TM, Streamer), DbgInfo(Streamer, TM.getMCAsmInfo()) { PTLI = static_cast<PIC16TargetLowering*>(TM.getTargetLowering()); PMAI = static_cast<const PIC16MCAsmInfo*>(TM.getMCAsmInfo()); PTOF = (PIC16TargetObjectFile *)&PTLI->getObjFileLowering(); } void PIC16AsmPrinter::EmitInstruction(const MachineInstr *MI) { - printInstruction(MI); - OutStreamer.AddBlankLine(); + SmallString<128> Str; + raw_svector_ostream OS(Str); + printInstruction(MI, OS); + + OutStreamer.EmitRawText(OS.str()); } static int getFunctionColor(const Function *F) { @@ -111,33 +112,33 @@ bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) { PAN::isISR(F->getSection())); // Start the Code Section. - O << "\n"; OutStreamer.SwitchSection(fCodeSection); // Emit the frame address of the function at the beginning of code. - O << "\tretlw low(" << PAN::getFrameLabel(CurrentFnSym->getName()) << ")\n"; - O << "\tretlw high(" << PAN::getFrameLabel(CurrentFnSym->getName()) << ")\n"; + OutStreamer.EmitRawText("\tretlw low(" + + Twine(PAN::getFrameLabel(CurrentFnSym->getName())) + + ")"); + OutStreamer.EmitRawText("\tretlw high(" + + Twine(PAN::getFrameLabel(CurrentFnSym->getName())) + + ")"); // Emit function start label. - O << *CurrentFnSym << ":\n"; + OutStreamer.EmitLabel(CurrentFnSym); DebugLoc CurDL; - O << "\n"; // Print out code for the function. for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); I != E; ++I) { // Print a label for the basic block. - if (I != MF.begin()) { + if (I != MF.begin()) EmitBasicBlockStart(I); - } // Print a basic block. for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); II != E; ++II) { - // Emit the line directive if source line changed. - const DebugLoc DL = II->getDebugLoc(); + DebugLoc DL = II->getDebugLoc(); if (!DL.isUnknown() && DL != CurDL) { DbgInfo.ChangeDebugLoc(MF, DL); CurDL = DL; @@ -156,7 +157,8 @@ bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) { // printOperand - print operand of insn. -void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) { +void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum, + raw_ostream &O) { const MachineOperand &MO = MI->getOperand(opNum); const Function *F = MI->getParent()->getParent()->getFunction(); @@ -167,9 +169,7 @@ void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) { std::string RegName = getRegisterName(MO.getReg()); if ((MI->getOpcode() == PIC16::load_indirect) || (MI->getOpcode() == PIC16::store_indirect)) - { RegName.replace (0, 3, "INDF"); - } O << RegName; } return; @@ -216,7 +216,8 @@ void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) { /// printCCOperand - Print the cond code operand. /// -void PIC16AsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) { +void PIC16AsmPrinter::printCCOperand(const MachineInstr *MI, int opNum, + raw_ostream &O) { int CC = (int)MI->getOperand(opNum).getImm(); O << PIC16CondCodeToString((PIC16CC::CondCodes)CC); } @@ -228,13 +229,15 @@ void PIC16AsmPrinter::printLibcallDecls() { // If no libcalls used, return. if (LibcallDecls.empty()) return; - O << MAI->getCommentString() << "External decls for libcalls - BEGIN." <<"\n"; + OutStreamer.AddComment("External decls for libcalls - BEGIN"); + OutStreamer.AddBlankLine(); for (std::set<std::string>::const_iterator I = LibcallDecls.begin(), - E = LibcallDecls.end(); I != E; I++) { - O << MAI->getExternDirective() << *I << "\n"; - } - O << MAI->getCommentString() << "External decls for libcalls - END." <<"\n"; + E = LibcallDecls.end(); I != E; I++) + OutStreamer.EmitRawText(MAI->getExternDirective() + Twine(*I)); + + OutStreamer.AddComment("External decls for libcalls - END"); + OutStreamer.AddBlankLine(); } /// doInitialization - Perform Module level initializations here. @@ -245,8 +248,8 @@ bool PIC16AsmPrinter::doInitialization(Module &M) { bool Result = AsmPrinter::doInitialization(M); // Every asmbly contains these std headers. - O << "\n#include p16f1xxx.inc"; - O << "\n#include stdmacros.inc"; + OutStreamer.EmitRawText(StringRef("\n#include p16f1xxx.inc")); + OutStreamer.EmitRawText(StringRef("#include stdmacros.inc")); // Set the section names for all globals. for (Module::global_iterator I = M.global_begin(), E = M.global_end(); @@ -289,7 +292,8 @@ bool PIC16AsmPrinter::doInitialization(Module &M) { /// void PIC16AsmPrinter::EmitFunctionDecls(Module &M) { // Emit declarations for external functions. - O <<"\n"<<MAI->getCommentString() << "Function Declarations - BEGIN." <<"\n"; + OutStreamer.AddComment("Function Declarations - BEGIN"); + OutStreamer.AddBlankLine(); for (Module::iterator I = M.begin(), E = M.end(); I != E; I++) { if (I->isIntrinsic() || I->getName() == "@abort") continue; @@ -312,12 +316,16 @@ void PIC16AsmPrinter::EmitFunctionDecls(Module &M) { const char *directive = I->isDeclaration() ? MAI->getExternDirective() : MAI->getGlobalDirective(); - O << directive << Sym->getName() << "\n"; - O << directive << PAN::getRetvalLabel(Sym->getName()) << "\n"; - O << directive << PAN::getArgsLabel(Sym->getName()) << "\n"; + OutStreamer.EmitRawText(directive + Twine(Sym->getName())); + OutStreamer.EmitRawText(directive + + Twine(PAN::getRetvalLabel(Sym->getName()))); + OutStreamer.EmitRawText(directive + + Twine(PAN::getArgsLabel(Sym->getName()))); } - O << MAI->getCommentString() << "Function Declarations - END." <<"\n"; + OutStreamer.AddComment("Function Declarations - END"); + OutStreamer.AddBlankLine(); + } // Emit variables imported from other Modules. @@ -325,10 +333,14 @@ void PIC16AsmPrinter::EmitUndefinedVars(Module &M) { std::vector<const GlobalVariable*> Items = ExternalVarDecls; if (!Items.size()) return; - O << "\n" << MAI->getCommentString() << "Imported Variables - BEGIN" << "\n"; + OutStreamer.AddComment("Imported Variables - BEGIN"); + OutStreamer.AddBlankLine(); for (unsigned j = 0; j < Items.size(); j++) - O << MAI->getExternDirective() << *Mang->getSymbol(Items[j]) << "\n"; - O << MAI->getCommentString() << "Imported Variables - END" << "\n"; + OutStreamer.EmitRawText(MAI->getExternDirective() + + Twine(Mang->getSymbol(Items[j])->getName())); + + OutStreamer.AddComment("Imported Variables - END"); + OutStreamer.AddBlankLine(); } // Emit variables defined in this module and are available to other modules. @@ -336,10 +348,14 @@ void PIC16AsmPrinter::EmitDefinedVars(Module &M) { std::vector<const GlobalVariable*> Items = ExternalVarDefs; if (!Items.size()) return; - O << "\n" << MAI->getCommentString() << "Exported Variables - BEGIN" << "\n"; + OutStreamer.AddComment("Exported Variables - BEGIN"); + OutStreamer.AddBlankLine(); + for (unsigned j = 0; j < Items.size(); j++) - O << MAI->getGlobalDirective() << *Mang->getSymbol(Items[j]) << "\n"; - O << MAI->getCommentString() << "Exported Variables - END" << "\n"; + OutStreamer.EmitRawText(MAI->getGlobalDirective() + + Twine(Mang->getSymbol(Items[j])->getName())); + OutStreamer.AddComment("Exported Variables - END"); + OutStreamer.AddBlankLine(); } // Emit initialized data placed in ROM. @@ -356,7 +372,7 @@ bool PIC16AsmPrinter::doFinalization(Module &M) { EmitAllAutos(M); printLibcallDecls(); DbgInfo.EndModule(M); - O << "\n\t" << "END\n"; + OutStreamer.EmitRawText(StringRef("\tEND")); return AsmPrinter::doFinalization(M); } @@ -364,7 +380,6 @@ void PIC16AsmPrinter::EmitFunctionFrame(MachineFunction &MF) { const Function *F = MF.getFunction(); const TargetData *TD = TM.getTargetData(); // Emit the data section name. - O << "\n"; PIC16Section *fPDataSection = const_cast<PIC16Section *>(getObjFileLowering(). @@ -374,7 +389,8 @@ void PIC16AsmPrinter::EmitFunctionFrame(MachineFunction &MF) { OutStreamer.SwitchSection(fPDataSection); // Emit function frame label - O << PAN::getFrameLabel(CurrentFnSym->getName()) << ":\n"; + OutStreamer.EmitRawText(PAN::getFrameLabel(CurrentFnSym->getName()) + + Twine(":")); const Type *RetType = F->getReturnType(); unsigned RetSize = 0; @@ -386,10 +402,11 @@ void PIC16AsmPrinter::EmitFunctionFrame(MachineFunction &MF) { // we will need to avoid printing a global directive for Retval label // in emitExternandGloblas. if(RetSize > 0) - O << PAN::getRetvalLabel(CurrentFnSym->getName()) - << " RES " << RetSize << "\n"; + OutStreamer.EmitRawText(PAN::getRetvalLabel(CurrentFnSym->getName()) + + Twine(" RES ") + Twine(RetSize)); else - O << PAN::getRetvalLabel(CurrentFnSym->getName()) << ": \n"; + OutStreamer.EmitRawText(PAN::getRetvalLabel(CurrentFnSym->getName()) + + Twine(":")); // Emit variable to hold the space for function arguments unsigned ArgSize = 0; @@ -399,13 +416,14 @@ void PIC16AsmPrinter::EmitFunctionFrame(MachineFunction &MF) { ArgSize += TD->getTypeAllocSize(Ty); } - O << PAN::getArgsLabel(CurrentFnSym->getName()) << " RES " << ArgSize << "\n"; + OutStreamer.EmitRawText(PAN::getArgsLabel(CurrentFnSym->getName()) + + Twine(" RES ") + Twine(ArgSize)); // Emit temporary space int TempSize = PTLI->GetTmpSize(); if (TempSize > 0) - O << PAN::getTempdataLabel(CurrentFnSym->getName()) << " RES " - << TempSize << '\n'; + OutStreamer.EmitRawText(PAN::getTempdataLabel(CurrentFnSym->getName()) + + Twine(" RES ") + Twine(TempSize)); } @@ -417,7 +435,7 @@ void PIC16AsmPrinter::EmitInitializedDataSection(const PIC16Section *S) { for (unsigned j = 0; j < Items.size(); j++) { Constant *C = Items[j]->getInitializer(); int AddrSpace = Items[j]->getType()->getAddressSpace(); - O << *Mang->getSymbol(Items[j]); + OutStreamer.EmitRawText(Mang->getSymbol(Items[j])->getName()); EmitGlobalConstant(C, AddrSpace); } } @@ -436,7 +454,8 @@ EmitUninitializedDataSection(const PIC16Section *S) { Constant *C = Items[j]->getInitializer(); const Type *Ty = C->getType(); unsigned Size = TD->getTypeAllocSize(Ty); - O << *Mang->getSymbol(Items[j]) << " RES " << Size << "\n"; + OutStreamer.EmitRawText(Mang->getSymbol(Items[j])->getName() + + Twine(" RES ") + Twine(Size)); } } @@ -484,7 +503,7 @@ EmitSectionList(Module &M, const std::vector<PIC16Section *> &SList) { // Exclude llvm specific metadata sections. if (SList[i]->getName().find("llvm.") != std::string::npos) continue; - O << "\n"; + OutStreamer.AddBlankLine(); EmitSingleSection(SList[i]); } } diff --git a/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.h b/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.h index 8063fcc6fc93..e27778fbb070 100644 --- a/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.h +++ b/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.h @@ -31,8 +31,7 @@ namespace llvm { class VISIBILITY_HIDDEN PIC16AsmPrinter : public AsmPrinter { public: - explicit PIC16AsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, - MCStreamer &Streamer); + explicit PIC16AsmPrinter(TargetMachine &TM, MCStreamer &Streamer); private: virtual const char *getPassName() const { return "PIC16 Assembly Printer"; @@ -43,9 +42,9 @@ namespace llvm { } bool runOnMachineFunction(MachineFunction &F); - void printOperand(const MachineInstr *MI, int opNum); - void printCCOperand(const MachineInstr *MI, int opNum); - void printInstruction(const MachineInstr *MI); // definition autogenerated. + void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); + void printCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O); + void printInstruction(const MachineInstr *MI, raw_ostream &O); static const char *getRegisterName(unsigned RegNo); void EmitInstruction(const MachineInstr *MI); diff --git a/lib/Target/PIC16/PIC16DebugInfo.cpp b/lib/Target/PIC16/PIC16DebugInfo.cpp index a223540170a7..5d86329e9b9b 100644 --- a/lib/Target/PIC16/PIC16DebugInfo.cpp +++ b/lib/Target/PIC16/PIC16DebugInfo.cpp @@ -18,10 +18,10 @@ #include "llvm/GlobalVariable.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCStreamer.h" #include "llvm/Support/DebugLoc.h" -#include "llvm/Support/FormattedStream.h" #include "llvm/ADT/SmallString.h" - +#include "llvm/ADT/StringExtras.h" using namespace llvm; /// PopulateDebugInfo - Populate the TypeNo, Aux[] and TagName from Ty. @@ -267,7 +267,8 @@ void PIC16DbgInfo::ChangeDebugLoc(const MachineFunction &MF, /// void PIC16DbgInfo::SwitchToLine(unsigned Line, bool IsInBeginFunction) { if (CurLine == Line) return; - if (!IsInBeginFunction) O << "\n\t.line " << Line << "\n"; + if (!IsInBeginFunction) + OS.EmitRawText("\n\t.line " + Twine(Line)); CurLine = Line; } @@ -286,7 +287,7 @@ void PIC16DbgInfo::EndFunction(const MachineFunction &MF) { void PIC16DbgInfo::EndModule(Module &M) { if (! EmitDebugDirectives) return; EmitVarDebugInfo(M); - if (CurFile != "") O << "\n\t.eof"; + if (CurFile != "") OS.EmitRawText(StringRef("\n\t.eof")); } /// EmitCompositeTypeElements - Emit debug information for members of a @@ -410,22 +411,26 @@ void PIC16DbgInfo::EmitFunctEndDI(const Function *F, unsigned Line) { /// void PIC16DbgInfo::EmitAuxEntry(const std::string VarName, int Aux[], int Num, std::string TagName) { - O << "\n\t.dim " << VarName << ", 1" ; + std::string Tmp; // TagName is emitted in case of structure/union objects. - if (TagName != "") - O << ", " << TagName; + if (!TagName.empty()) Tmp += ", " + TagName; + for (int i = 0; i<Num; i++) - O << "," << (Aux[i] && 0xff); + Tmp += "," + utostr(Aux[i] && 0xff); + + OS.EmitRawText("\n\t.dim " + Twine(VarName) + ", 1" + Tmp); } /// EmitSymbol - Emit .def for a symbol. Value is offset for the member. /// -void PIC16DbgInfo::EmitSymbol(std::string Name, short Class, unsigned short - Type, unsigned long Value) { - O << "\n\t" << ".def "<< Name << ", type = " << Type << ", class = " - << Class; +void PIC16DbgInfo::EmitSymbol(std::string Name, short Class, + unsigned short Type, unsigned long Value) { + std::string Tmp; if (Value > 0) - O << ", value = " << Value; + Tmp = ", value = " + utostr(Value); + + OS.EmitRawText("\n\t.def " + Twine(Name) + ", type = " + utostr(Type) + + ", class = " + utostr(Class) + Tmp); } /// EmitVarDebugInfo - Emit debug information for all variables. @@ -447,14 +452,13 @@ void PIC16DbgInfo::EmitVarDebugInfo(Module &M) { PopulateDebugInfo(Ty, TypeNo, HasAux, Aux, TagName); // Emit debug info only if type information is availaible. if (TypeNo != PIC16Dbg::T_NULL) { - O << "\n\t.type " << VarName << ", " << TypeNo; + OS.EmitRawText("\t.type " + Twine(VarName) + ", " + Twine(TypeNo)); short ClassNo = getStorageClass(DIGV); - O << "\n\t.class " << VarName << ", " << ClassNo; - if (HasAux) + OS.EmitRawText("\t.class " + Twine(VarName) + ", " + Twine(ClassNo)); + if (HasAux) EmitAuxEntry(VarName, Aux, PIC16Dbg::AuxSize, TagName); } } - O << "\n"; } /// SwitchToCU - Switch to a new compilation unit. @@ -470,8 +474,9 @@ void PIC16DbgInfo::SwitchToCU(MDNode *CU) { if ( FilePath == CurFile ) return; // Else, close the current one and start a new. - if (CurFile != "") O << "\n\t.eof"; - O << "\n\t.file\t\"" << FilePath << "\"\n" ; + if (CurFile != "") + OS.EmitRawText(StringRef("\t.eof")); + OS.EmitRawText("\n\t.file\t\"" + Twine(FilePath) + "\""); CurFile = FilePath; CurLine = 0; } @@ -480,6 +485,6 @@ void PIC16DbgInfo::SwitchToCU(MDNode *CU) { /// void PIC16DbgInfo::EmitEOF() { if (CurFile != "") - O << "\n\t.EOF"; + OS.EmitRawText(StringRef("\t.EOF")); } diff --git a/lib/Target/PIC16/PIC16DebugInfo.h b/lib/Target/PIC16/PIC16DebugInfo.h index 54e27c7c3377..031dcf092f04 100644 --- a/lib/Target/PIC16/PIC16DebugInfo.h +++ b/lib/Target/PIC16/PIC16DebugInfo.h @@ -20,6 +20,8 @@ namespace llvm { class MachineFunction; class DebugLoc; + class MCStreamer; + namespace PIC16Dbg { enum VarType { T_NULL, @@ -88,10 +90,8 @@ namespace llvm { }; } - class formatted_raw_ostream; - class PIC16DbgInfo { - formatted_raw_ostream &O; + MCStreamer &OS; const MCAsmInfo *MAI; std::string CurFile; unsigned CurLine; @@ -101,8 +101,7 @@ namespace llvm { bool EmitDebugDirectives; public: - PIC16DbgInfo(formatted_raw_ostream &o, const MCAsmInfo *T) - : O(o), MAI(T) { + PIC16DbgInfo(MCStreamer &os, const MCAsmInfo *T) : OS(os), MAI(T) { CurFile = ""; CurLine = 0; EmitDebugDirectives = false; diff --git a/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp b/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp index 5adefd39c51b..605656493c4b 100644 --- a/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp +++ b/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp @@ -26,7 +26,6 @@ #include "llvm/Module.h" #include "llvm/Assembly/Writer.h" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/DwarfWriter.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -44,10 +43,8 @@ #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegistry.h" #include "llvm/Support/MathExtras.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSet.h" #include "llvm/ADT/SmallString.h" @@ -56,13 +53,12 @@ using namespace llvm; namespace { class PPCAsmPrinter : public AsmPrinter { protected: - DenseMap<const MCSymbol*, const MCSymbol*> TOC; + DenseMap<MCSymbol*, MCSymbol*> TOC; const PPCSubtarget &Subtarget; uint64_t LabelID; public: - explicit PPCAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, - MCStreamer &Streamer) - : AsmPrinter(O, TM, Streamer), + explicit PPCAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : AsmPrinter(TM, Streamer), Subtarget(TM.getSubtarget<PPCSubtarget>()), LabelID(0) {} virtual const char *getPassName() const { @@ -92,12 +88,12 @@ namespace { /// from the instruction set description. This method returns true if the /// machine instruction was sufficiently described to print it, otherwise it /// returns false. - void printInstruction(const MachineInstr *MI); + void printInstruction(const MachineInstr *MI, raw_ostream &O); static const char *getRegisterName(unsigned RegNo); virtual void EmitInstruction(const MachineInstr *MI); - void printOp(const MachineOperand &MO); + void printOp(const MachineOperand &MO, raw_ostream &O); /// stripRegisterPrefix - This method strips the character prefix from a /// register name so that only the number is left. Used by for linux asm. @@ -114,7 +110,7 @@ namespace { /// printRegister - Print register according to target requirements. /// - void printRegister(const MachineOperand &MO, bool R0AsZero) { + void printRegister(const MachineOperand &MO, bool R0AsZero, raw_ostream &O){ unsigned RegNo = MO.getReg(); assert(TargetRegisterInfo::isPhysicalRegister(RegNo) && "Not physreg??"); @@ -131,66 +127,76 @@ namespace { O << RegName; } - void printOperand(const MachineInstr *MI, unsigned OpNo) { + void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { const MachineOperand &MO = MI->getOperand(OpNo); if (MO.isReg()) { - printRegister(MO, false); + printRegister(MO, false, O); } else if (MO.isImm()) { O << MO.getImm(); } else { - printOp(MO); + printOp(MO, O); } } bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode); + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode); + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); - void printS5ImmOperand(const MachineInstr *MI, unsigned OpNo) { + void printS5ImmOperand(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { char value = MI->getOperand(OpNo).getImm(); value = (value << (32-5)) >> (32-5); O << (int)value; } - void printU5ImmOperand(const MachineInstr *MI, unsigned OpNo) { + void printU5ImmOperand(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { unsigned char value = MI->getOperand(OpNo).getImm(); assert(value <= 31 && "Invalid u5imm argument!"); O << (unsigned int)value; } - void printU6ImmOperand(const MachineInstr *MI, unsigned OpNo) { + void printU6ImmOperand(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { unsigned char value = MI->getOperand(OpNo).getImm(); assert(value <= 63 && "Invalid u6imm argument!"); O << (unsigned int)value; } - void printS16ImmOperand(const MachineInstr *MI, unsigned OpNo) { + void printS16ImmOperand(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { O << (short)MI->getOperand(OpNo).getImm(); } - void printU16ImmOperand(const MachineInstr *MI, unsigned OpNo) { + void printU16ImmOperand(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { O << (unsigned short)MI->getOperand(OpNo).getImm(); } - void printS16X4ImmOperand(const MachineInstr *MI, unsigned OpNo) { + void printS16X4ImmOperand(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { if (MI->getOperand(OpNo).isImm()) { O << (short)(MI->getOperand(OpNo).getImm()*4); } else { O << "lo16("; - printOp(MI->getOperand(OpNo)); + printOp(MI->getOperand(OpNo), O); if (TM.getRelocationModel() == Reloc::PIC_) O << "-\"L" << getFunctionNumber() << "$pb\")"; else O << ')'; } } - void printBranchOperand(const MachineInstr *MI, unsigned OpNo) { + void printBranchOperand(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { // Branches can take an immediate operand. This is used by the branch // selection pass to print $+8, an eight byte displacement from the PC. if (MI->getOperand(OpNo).isImm()) { O << "$+" << MI->getOperand(OpNo).getImm()*4; } else { - printOp(MI->getOperand(OpNo)); + printOp(MI->getOperand(OpNo), O); } } - void printCallOperand(const MachineInstr *MI, unsigned OpNo) { + void printCallOperand(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { const MachineOperand &MO = MI->getOperand(OpNo); if (TM.getRelocationModel() != Reloc::Static) { if (MO.getType() == MachineOperand::MO_GlobalAddress) { @@ -223,21 +229,22 @@ namespace { } } - printOp(MI->getOperand(OpNo)); + printOp(MI->getOperand(OpNo), O); } - void printAbsAddrOperand(const MachineInstr *MI, unsigned OpNo) { + void printAbsAddrOperand(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { O << (int)MI->getOperand(OpNo).getImm()*4; } - void printPICLabel(const MachineInstr *MI, unsigned OpNo) { + void printPICLabel(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { O << "\"L" << getFunctionNumber() << "$pb\"\n"; O << "\"L" << getFunctionNumber() << "$pb\":"; } - void printSymbolHi(const MachineInstr *MI, unsigned OpNo) { + void printSymbolHi(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { if (MI->getOperand(OpNo).isImm()) { - printS16ImmOperand(MI, OpNo); + printS16ImmOperand(MI, OpNo, O); } else { if (Subtarget.isDarwin()) O << "ha16("; - printOp(MI->getOperand(OpNo)); + printOp(MI->getOperand(OpNo), O); if (TM.getRelocationModel() == Reloc::PIC_) O << "-\"L" << getFunctionNumber() << "$pb\""; if (Subtarget.isDarwin()) @@ -246,12 +253,12 @@ namespace { O << "@ha"; } } - void printSymbolLo(const MachineInstr *MI, unsigned OpNo) { + void printSymbolLo(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { if (MI->getOperand(OpNo).isImm()) { - printS16ImmOperand(MI, OpNo); + printS16ImmOperand(MI, OpNo, O); } else { if (Subtarget.isDarwin()) O << "lo16("; - printOp(MI->getOperand(OpNo)); + printOp(MI->getOperand(OpNo), O); if (TM.getRelocationModel() == Reloc::PIC_) O << "-\"L" << getFunctionNumber() << "$pb\""; if (Subtarget.isDarwin()) @@ -260,53 +267,55 @@ namespace { O << "@l"; } } - void printcrbitm(const MachineInstr *MI, unsigned OpNo) { + void printcrbitm(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { unsigned CCReg = MI->getOperand(OpNo).getReg(); unsigned RegNo = enumRegToMachineReg(CCReg); O << (0x80 >> RegNo); } // The new addressing mode printers. - void printMemRegImm(const MachineInstr *MI, unsigned OpNo) { - printSymbolLo(MI, OpNo); + void printMemRegImm(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { + printSymbolLo(MI, OpNo, O); O << '('; if (MI->getOperand(OpNo+1).isReg() && MI->getOperand(OpNo+1).getReg() == PPC::R0) O << "0"; else - printOperand(MI, OpNo+1); + printOperand(MI, OpNo+1, O); O << ')'; } - void printMemRegImmShifted(const MachineInstr *MI, unsigned OpNo) { + void printMemRegImmShifted(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { if (MI->getOperand(OpNo).isImm()) - printS16X4ImmOperand(MI, OpNo); + printS16X4ImmOperand(MI, OpNo, O); else - printSymbolLo(MI, OpNo); + printSymbolLo(MI, OpNo, O); O << '('; if (MI->getOperand(OpNo+1).isReg() && MI->getOperand(OpNo+1).getReg() == PPC::R0) O << "0"; else - printOperand(MI, OpNo+1); + printOperand(MI, OpNo+1, O); O << ')'; } - void printMemRegReg(const MachineInstr *MI, unsigned OpNo) { + void printMemRegReg(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { // When used as the base register, r0 reads constant zero rather than // the value contained in the register. For this reason, the darwin // assembler requires that we print r0 as 0 (no r) when used as the base. const MachineOperand &MO = MI->getOperand(OpNo); - printRegister(MO, true); + printRegister(MO, true, O); O << ", "; - printOperand(MI, OpNo+1); + printOperand(MI, OpNo+1, O); } - void printTOCEntryLabel(const MachineInstr *MI, unsigned OpNo) { + void printTOCEntryLabel(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { const MachineOperand &MO = MI->getOperand(OpNo); assert(MO.getType() == MachineOperand::MO_GlobalAddress); - const MCSymbol *Sym = Mang->getSymbol(MO.getGlobal()); + MCSymbol *Sym = Mang->getSymbol(MO.getGlobal()); // Map symbol -> label of TOC entry. - const MCSymbol *&TOCEntry = TOC[Sym]; + MCSymbol *&TOCEntry = TOC[Sym]; if (TOCEntry == 0) TOCEntry = OutContext. GetOrCreateSymbol(StringRef(MAI->getPrivateGlobalPrefix()) + @@ -316,15 +325,14 @@ namespace { } void printPredicateOperand(const MachineInstr *MI, unsigned OpNo, - const char *Modifier); + raw_ostream &O, const char *Modifier); }; /// PPCLinuxAsmPrinter - PowerPC assembly printer, customized for Linux class PPCLinuxAsmPrinter : public PPCAsmPrinter { public: - explicit PPCLinuxAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, - MCStreamer &Streamer) - : PPCAsmPrinter(O, TM, Streamer) {} + explicit PPCLinuxAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : PPCAsmPrinter(TM, Streamer) {} virtual const char *getPassName() const { return "Linux PPC Assembly Printer"; @@ -333,23 +341,14 @@ namespace { bool doFinalization(Module &M); virtual void EmitFunctionEntryLabel(); - - void getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesAll(); - AU.addRequired<MachineModuleInfo>(); - AU.addRequired<DwarfWriter>(); - PPCAsmPrinter::getAnalysisUsage(AU); - } }; /// PPCDarwinAsmPrinter - PowerPC assembly printer, customized for Darwin/Mac /// OS X class PPCDarwinAsmPrinter : public PPCAsmPrinter { - formatted_raw_ostream &OS; public: - explicit PPCDarwinAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, - MCStreamer &Streamer) - : PPCAsmPrinter(O, TM, Streamer), OS(O) {} + explicit PPCDarwinAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : PPCAsmPrinter(TM, Streamer) {} virtual const char *getPassName() const { return "Darwin PPC Assembly Printer"; @@ -359,20 +358,13 @@ namespace { void EmitStartOfAsmFile(Module &M); void EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs); - - void getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesAll(); - AU.addRequired<MachineModuleInfo>(); - AU.addRequired<DwarfWriter>(); - PPCAsmPrinter::getAnalysisUsage(AU); - } }; } // end of anonymous namespace // Include the auto-generated portion of the assembly writer #include "PPCGenAsmWriter.inc" -void PPCAsmPrinter::printOp(const MachineOperand &MO) { +void PPCAsmPrinter::printOp(const MachineOperand &MO, raw_ostream &O) { switch (MO.getType()) { case MachineOperand::MO_Immediate: llvm_unreachable("printOp() does not handle immediate values"); @@ -446,7 +438,7 @@ void PPCAsmPrinter::printOp(const MachineOperand &MO) { O << *SymToPrint; - printOffset(MO.getOffset()); + printOffset(MO.getOffset(), O); return; } @@ -460,7 +452,7 @@ void PPCAsmPrinter::printOp(const MachineOperand &MO) { /// bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, - const char *ExtraCode) { + const char *ExtraCode, raw_ostream &O) { // Does this asm operand have a single letter operand modifier? if (ExtraCode && ExtraCode[0]) { if (ExtraCode[1] != 0) return true; // Unknown modifier. @@ -469,7 +461,7 @@ bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, default: return true; // Unknown modifier. case 'c': // Don't print "$" before a global var name or constant. // PPC never has a prefix. - printOperand(MI, OpNo); + printOperand(MI, OpNo, O); return false; case 'L': // Write second word of DImode reference. // Verify that this operand has two consecutive registers. @@ -488,7 +480,7 @@ bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, } } - printOperand(MI, OpNo); + printOperand(MI, OpNo, O); return false; } @@ -498,18 +490,19 @@ bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, - const char *ExtraCode) { + const char *ExtraCode, + raw_ostream &O) { if (ExtraCode && ExtraCode[0]) return true; // Unknown modifier. assert (MI->getOperand(OpNo).isReg()); O << "0("; - printOperand(MI, OpNo); + printOperand(MI, OpNo, O); O << ")"; return false; } void PPCAsmPrinter::printPredicateOperand(const MachineInstr *MI, unsigned OpNo, - const char *Modifier) { + raw_ostream &O, const char *Modifier){ assert(Modifier && "Must specify 'cc' or 'reg' as predicate op modifier!"); unsigned Code = MI->getOperand(OpNo).getImm(); if (!strcmp(Modifier, "cc")) { @@ -530,7 +523,7 @@ void PPCAsmPrinter::printPredicateOperand(const MachineInstr *MI, unsigned OpNo, "Need to specify 'cc' or 'reg' as predicate op modifier!"); // Don't print the register for 'always'. if (Code == PPC::PRED_ALWAYS) return; - printOperand(MI, OpNo+1); + printOperand(MI, OpNo+1, O); } } @@ -539,6 +532,9 @@ void PPCAsmPrinter::printPredicateOperand(const MachineInstr *MI, unsigned OpNo, /// the current output stream. /// void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { + SmallString<128> Str; + raw_svector_ostream O(Str); + // Check for slwi/srwi mnemonics. if (MI->getOpcode() == PPC::RLWINM) { unsigned char SH = MI->getOperand(2).getImm(); @@ -553,11 +549,11 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { SH = 32-SH; } if (useSubstituteMnemonic) { - printOperand(MI, 0); + printOperand(MI, 0, O); O << ", "; - printOperand(MI, 1); + printOperand(MI, 1, O); O << ", " << (unsigned int)SH; - OutStreamer.AddBlankLine(); + OutStreamer.EmitRawText(O.str()); return; } } @@ -565,10 +561,10 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { if ((MI->getOpcode() == PPC::OR || MI->getOpcode() == PPC::OR8) && MI->getOperand(1).getReg() == MI->getOperand(2).getReg()) { O << "\tmr "; - printOperand(MI, 0); + printOperand(MI, 0, O); O << ", "; - printOperand(MI, 1); - OutStreamer.AddBlankLine(); + printOperand(MI, 1, O); + OutStreamer.EmitRawText(O.str()); return; } @@ -578,17 +574,17 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { // rldicr RA, RS, SH, 63-SH == sldi RA, RS, SH if (63-SH == ME) { O << "\tsldi "; - printOperand(MI, 0); + printOperand(MI, 0, O); O << ", "; - printOperand(MI, 1); + printOperand(MI, 1, O); O << ", " << (unsigned int)SH; - OutStreamer.AddBlankLine(); + OutStreamer.EmitRawText(O.str()); return; } } - printInstruction(MI); - OutStreamer.AddBlankLine(); + printInstruction(MI, O); + OutStreamer.EmitRawText(O.str()); } void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() { @@ -597,12 +593,13 @@ void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() { // Emit an official procedure descriptor. // FIXME 64-bit SVR4: Use MCSection here! - O << "\t.section\t\".opd\",\"aw\"\n"; - O << "\t.align 3\n"; + OutStreamer.EmitRawText(StringRef("\t.section\t\".opd\",\"aw\"")); + OutStreamer.EmitRawText(StringRef("\t.align 3")); OutStreamer.EmitLabel(CurrentFnSym); - O << "\t.quad .L." << *CurrentFnSym << ",.TOC.@tocbase\n"; - O << "\t.previous\n"; - O << ".L." << *CurrentFnSym << ":\n"; + OutStreamer.EmitRawText("\t.quad .L." + Twine(CurrentFnSym->getName()) + + ",.TOC.@tocbase"); + OutStreamer.EmitRawText(StringRef("\t.previous")); + OutStreamer.EmitRawText(".L." + Twine(CurrentFnSym->getName()) + ":"); } @@ -613,13 +610,14 @@ bool PPCLinuxAsmPrinter::doFinalization(Module &M) { if (isPPC64 && !TOC.empty()) { // FIXME 64-bit SVR4: Use MCSection here? - O << "\t.section\t\".toc\",\"aw\"\n"; + OutStreamer.EmitRawText(StringRef("\t.section\t\".toc\",\"aw\"")); // FIXME: This is nondeterminstic! - for (DenseMap<const MCSymbol*, const MCSymbol*>::iterator I = TOC.begin(), + for (DenseMap<MCSymbol*, MCSymbol*>::iterator I = TOC.begin(), E = TOC.end(); I != E; ++I) { - O << *I->second << ":\n"; - O << "\t.tc " << *I->first << "[TC]," << *I->first << '\n'; + OutStreamer.EmitLabel(I->second); + OutStreamer.EmitRawText("\t.tc " + Twine(I->first->getName()) + + "[TC]," + I->first->getName()); } } @@ -647,7 +645,7 @@ void PPCDarwinAsmPrinter::EmitStartOfAsmFile(Module &M) { if (Subtarget.isPPC64() && Directive < PPC::DIR_970) Directive = PPC::DIR_64; assert(Directive <= PPC::DIR_64 && "Directive out of range."); - O << "\t.machine " << CPUDirectives[Directive] << '\n'; + OutStreamer.EmitRawText("\t.machine " + Twine(CPUDirectives[Directive])); // Prime text sections so they are adjacent. This reduces the likelihood a // large data or debug section causes a branch to exceed 16M limit. @@ -670,14 +668,14 @@ void PPCDarwinAsmPrinter::EmitStartOfAsmFile(Module &M) { OutStreamer.SwitchSection(getObjFileLowering().getTextSection()); } -static const MCSymbol *GetLazyPtr(const MCSymbol *Sym, MCContext &Ctx) { +static MCSymbol *GetLazyPtr(MCSymbol *Sym, MCContext &Ctx) { // Remove $stub suffix, add $lazy_ptr. SmallString<128> TmpStr(Sym->getName().begin(), Sym->getName().end()-5); TmpStr += "$lazy_ptr"; return Ctx.GetOrCreateSymbol(TmpStr.str()); } -static const MCSymbol *GetAnonSym(const MCSymbol *Sym, MCContext &Ctx) { +static MCSymbol *GetAnonSym(MCSymbol *Sym, MCContext &Ctx) { // Add $tmp suffix to $stub, yielding $stub$tmp. SmallString<128> TmpStr(Sym->getName().begin(), Sym->getName().end()); TmpStr += "$tmp"; @@ -705,31 +703,41 @@ EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs) { OutStreamer.SwitchSection(StubSection); EmitAlignment(4); - const MCSymbol *Stub = Stubs[i].first; - const MCSymbol *RawSym = Stubs[i].second.getPointer(); - const MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext); - const MCSymbol *AnonSymbol = GetAnonSym(Stub, OutContext); + MCSymbol *Stub = Stubs[i].first; + MCSymbol *RawSym = Stubs[i].second.getPointer(); + MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext); + MCSymbol *AnonSymbol = GetAnonSym(Stub, OutContext); - O << *Stub << ":\n"; - O << "\t.indirect_symbol " << *RawSym << '\n'; - O << "\tmflr r0\n"; - O << "\tbcl 20,31," << *AnonSymbol << '\n'; - O << *AnonSymbol << ":\n"; - O << "\tmflr r11\n"; - O << "\taddis r11,r11,ha16(" << *LazyPtr << '-' << *AnonSymbol - << ")\n"; - O << "\tmtlr r0\n"; - O << (isPPC64 ? "\tldu" : "\tlwzu") << " r12,lo16(" << *LazyPtr - << '-' << *AnonSymbol << ")(r11)\n"; - O << "\tmtctr r12\n"; - O << "\tbctr\n"; + OutStreamer.EmitLabel(Stub); + OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); + // FIXME: MCize this. + OutStreamer.EmitRawText(StringRef("\tmflr r0")); + OutStreamer.EmitRawText("\tbcl 20,31," + Twine(AnonSymbol->getName())); + OutStreamer.EmitLabel(AnonSymbol); + OutStreamer.EmitRawText(StringRef("\tmflr r11")); + OutStreamer.EmitRawText("\taddis r11,r11,ha16("+Twine(LazyPtr->getName())+ + "-" + AnonSymbol->getName() + ")"); + OutStreamer.EmitRawText(StringRef("\tmtlr r0")); + + if (isPPC64) + OutStreamer.EmitRawText("\tldu r12,lo16(" + Twine(LazyPtr->getName()) + + "-" + AnonSymbol->getName() + ")(r11)"); + else + OutStreamer.EmitRawText("\tlwzu r12,lo16(" + Twine(LazyPtr->getName()) + + "-" + AnonSymbol->getName() + ")(r11)"); + OutStreamer.EmitRawText(StringRef("\tmtctr r12")); + OutStreamer.EmitRawText(StringRef("\tbctr")); OutStreamer.SwitchSection(LSPSection); - O << *LazyPtr << ":\n"; - O << "\t.indirect_symbol " << *RawSym << '\n'; - O << (isPPC64 ? "\t.quad" : "\t.long") << " dyld_stub_binding_helper\n"; + OutStreamer.EmitLabel(LazyPtr); + OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); + + if (isPPC64) + OutStreamer.EmitRawText(StringRef("\t.quad dyld_stub_binding_helper")); + else + OutStreamer.EmitRawText(StringRef("\t.long dyld_stub_binding_helper")); } - O << '\n'; + OutStreamer.AddBlankLine(); return; } @@ -739,26 +747,34 @@ EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs) { MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 16, SectionKind::getText()); for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { - const MCSymbol *Stub = Stubs[i].first; - const MCSymbol *RawSym = Stubs[i].second.getPointer(); - const MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext); + MCSymbol *Stub = Stubs[i].first; + MCSymbol *RawSym = Stubs[i].second.getPointer(); + MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext); OutStreamer.SwitchSection(StubSection); EmitAlignment(4); - O << *Stub << ":\n"; - O << "\t.indirect_symbol " << *RawSym << '\n'; - O << "\tlis r11,ha16(" << *LazyPtr << ")\n"; - O << (isPPC64 ? "\tldu" : "\tlwzu") << " r12,lo16(" << *LazyPtr - << ")(r11)\n"; - O << "\tmtctr r12\n"; - O << "\tbctr\n"; + OutStreamer.EmitLabel(Stub); + OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); + OutStreamer.EmitRawText("\tlis r11,ha16(" + Twine(LazyPtr->getName()) +")"); + if (isPPC64) + OutStreamer.EmitRawText("\tldu r12,lo16(" + Twine(LazyPtr->getName()) + + ")(r11)"); + else + OutStreamer.EmitRawText("\tlwzu r12,lo16(" + Twine(LazyPtr->getName()) + + ")(r11)"); + OutStreamer.EmitRawText(StringRef("\tmtctr r12")); + OutStreamer.EmitRawText(StringRef("\tbctr")); OutStreamer.SwitchSection(LSPSection); - O << *LazyPtr << ":\n"; - O << "\t.indirect_symbol " << *RawSym << '\n'; - O << (isPPC64 ? "\t.quad" : "\t.long") << " dyld_stub_binding_helper\n"; + OutStreamer.EmitLabel(LazyPtr); + OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); + + if (isPPC64) + OutStreamer.EmitRawText(StringRef("\t.quad dyld_stub_binding_helper")); + else + OutStreamer.EmitRawText(StringRef("\t.long dyld_stub_binding_helper")); } - O << '\n'; + OutStreamer.AddBlankLine(); } @@ -858,14 +874,13 @@ bool PPCDarwinAsmPrinter::doFinalization(Module &M) { /// for a MachineFunction to the given output stream, in a format that the /// Darwin assembler can deal with. /// -static AsmPrinter *createPPCAsmPrinterPass(formatted_raw_ostream &o, - TargetMachine &tm, +static AsmPrinter *createPPCAsmPrinterPass(TargetMachine &tm, MCStreamer &Streamer) { const PPCSubtarget *Subtarget = &tm.getSubtarget<PPCSubtarget>(); if (Subtarget->isDarwin()) - return new PPCDarwinAsmPrinter(o, tm, Streamer); - return new PPCLinuxAsmPrinter(o, tm, Streamer); + return new PPCDarwinAsmPrinter(tm, Streamer); + return new PPCLinuxAsmPrinter(tm, Streamer); } // Force static initialization. diff --git a/lib/Target/PowerPC/PPC.td b/lib/Target/PowerPC/PPC.td index 08f5bb43087f..27644b2daca8 100644 --- a/lib/Target/PowerPC/PPC.td +++ b/lib/Target/PowerPC/PPC.td @@ -96,14 +96,6 @@ def : Processor<"ppc64", G5Itineraries, include "PPCCallingConv.td" def PPCInstrInfo : InstrInfo { - // Define how we want to layout our TargetSpecific information field... This - // should be kept up-to-date with the fields in the PPCInstrInfo.h file. - let TSFlagsFields = ["PPC970_First", - "PPC970_Single", - "PPC970_Cracked", - "PPC970_Unit"]; - let TSFlagsShifts = [0, 1, 2, 3]; - let isLittleEndianEncoding = 1; } diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index dda530eef434..9cd01be54e42 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -2392,7 +2392,7 @@ CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain, DebugLoc dl) { SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), MVT::i32); return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getByValAlign(), - false, NULL, 0, NULL, 0); + false, false, NULL, 0, NULL, 0); } /// LowerMemOpCallTo - Store the argument to the stack or remember it in case of diff --git a/lib/Target/PowerPC/PPCInstrFormats.td b/lib/Target/PowerPC/PPCInstrFormats.td index 54cebcdecd61..4357bdccec7b 100644 --- a/lib/Target/PowerPC/PPCInstrFormats.td +++ b/lib/Target/PowerPC/PPCInstrFormats.td @@ -23,13 +23,18 @@ class I<bits<6> opcode, dag OOL, dag IOL, string asmstr, InstrItinClass itin> let InOperandList = IOL; let AsmString = asmstr; let Itinerary = itin; - - /// These fields correspond to the fields in PPCInstrInfo.h. Any changes to - /// these must be reflected there! See comments there for what these are. + bits<1> PPC970_First = 0; bits<1> PPC970_Single = 0; bits<1> PPC970_Cracked = 0; bits<3> PPC970_Unit = 0; + + /// These fields correspond to the fields in PPCInstrInfo.h. Any changes to + /// these must be reflected there! See comments there for what these are. + let TSFlags{0} = PPC970_First; + let TSFlags{1} = PPC970_Single; + let TSFlags{2} = PPC970_Cracked; + let TSFlags{5-3} = PPC970_Unit; } class PPC970_DGroup_First { bits<1> PPC970_First = 1; } diff --git a/lib/Target/PowerPC/PPCMCAsmInfo.cpp b/lib/Target/PowerPC/PPCMCAsmInfo.cpp index b37aee804ac2..3644c79d0410 100644 --- a/lib/Target/PowerPC/PPCMCAsmInfo.cpp +++ b/lib/Target/PowerPC/PPCMCAsmInfo.cpp @@ -38,7 +38,6 @@ PPCLinuxMCAsmInfo::PPCLinuxMCAsmInfo(bool is64Bit) { UsesELFSectionDirectiveForBSS = true; // Debug Information - AbsoluteDebugSectionOffsets = true; SupportsDebugInformation = true; PCSymbol = "."; @@ -49,7 +48,6 @@ PPCLinuxMCAsmInfo::PPCLinuxMCAsmInfo(bool is64Bit) { // Exceptions handling if (!is64Bit) ExceptionsType = ExceptionHandling::Dwarf; - AbsoluteEHSectionOffsets = false; ZeroDirective = "\t.space\t"; Data64bitsDirective = is64Bit ? "\t.quad\t" : 0; diff --git a/lib/Target/PowerPC/PPCRegisterInfo.cpp b/lib/Target/PowerPC/PPCRegisterInfo.cpp index 9363aa8b7566..52d87cde803f 100644 --- a/lib/Target/PowerPC/PPCRegisterInfo.cpp +++ b/lib/Target/PowerPC/PPCRegisterInfo.cpp @@ -1280,9 +1280,9 @@ PPCRegisterInfo::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB MachineBasicBlock::iterator MBBI = MBB.begin(); MachineFrameInfo *MFI = MF.getFrameInfo(); - MachineModuleInfo *MMI = MFI->getMachineModuleInfo(); + MachineModuleInfo &MMI = MF.getMMI(); DebugLoc dl; - bool needsFrameMoves = (MMI && MMI->hasDebugInfo()) || + bool needsFrameMoves = MMI.hasDebugInfo() || !MF.getFunction()->doesNotThrow() || UnwindTablesMandatory; @@ -1442,13 +1442,13 @@ PPCRegisterInfo::emitPrologue(MachineFunction &MF) const { } } - std::vector<MachineMove> &Moves = MMI->getFrameMoves(); + std::vector<MachineMove> &Moves = MMI.getFrameMoves(); // Add the "machine moves" for the instructions we generated above, but in // reverse order. if (needsFrameMoves) { // Mark effective beginning of when frame pointer becomes valid. - FrameLabel = MMI->getContext().CreateTempSymbol(); + FrameLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(PPC::DBG_LABEL)).addSym(FrameLabel); // Show update of SP. @@ -1489,7 +1489,7 @@ PPCRegisterInfo::emitPrologue(MachineFunction &MF) const { } if (needsFrameMoves) { - ReadyLabel = MMI->getContext().CreateTempSymbol(); + ReadyLabel = MMI.getContext().CreateTempSymbol(); // Mark effective beginning of when frame pointer is ready. BuildMI(MBB, MBBI, dl, TII.get(PPC::DBG_LABEL)).addSym(ReadyLabel); diff --git a/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp b/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp index 3e40dbb17f88..ab948bb37ff2 100644 --- a/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp +++ b/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp @@ -23,39 +23,43 @@ #include "llvm/MC/MCSymbol.h" #include "llvm/Target/Mangler.h" #include "llvm/Target/TargetRegistry.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; namespace { class SparcAsmPrinter : public AsmPrinter { public: - explicit SparcAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, - MCStreamer &Streamer) - : AsmPrinter(O, TM, Streamer) {} + explicit SparcAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : AsmPrinter(TM, Streamer) {} virtual const char *getPassName() const { return "Sparc Assembly Printer"; } - void printOperand(const MachineInstr *MI, int opNum); - void printMemOperand(const MachineInstr *MI, int opNum, + void printOperand(const MachineInstr *MI, int opNum, raw_ostream &OS); + void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &OS, const char *Modifier = 0); - void printCCOperand(const MachineInstr *MI, int opNum); + void printCCOperand(const MachineInstr *MI, int opNum, raw_ostream &OS); virtual void EmitInstruction(const MachineInstr *MI) { - printInstruction(MI); - OutStreamer.AddBlankLine(); + SmallString<128> Str; + raw_svector_ostream OS(Str); + printInstruction(MI, OS); + OutStreamer.EmitRawText(OS.str()); } - void printInstruction(const MachineInstr *MI); // autogenerated. + void printInstruction(const MachineInstr *MI, raw_ostream &OS);// autogen'd. static const char *getRegisterName(unsigned RegNo); bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode); + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode); + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); - bool printGetPCX(const MachineInstr *MI, unsigned OpNo); + bool printGetPCX(const MachineInstr *MI, unsigned OpNo, raw_ostream &OS); virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const; @@ -64,7 +68,8 @@ namespace { #include "SparcGenAsmWriter.inc" -void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum) { +void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum, + raw_ostream &O) { const MachineOperand &MO = MI->getOperand (opNum); bool CloseParen = false; if (MI->getOpcode() == SP::SETHIi && !MO.isReg() && !MO.isImm()) { @@ -103,13 +108,13 @@ void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum) { } void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum, - const char *Modifier) { - printOperand(MI, opNum); + raw_ostream &O, const char *Modifier) { + printOperand(MI, opNum, O); // If this is an ADD operand, emit it like normal operands. if (Modifier && !strcmp(Modifier, "arith")) { O << ", "; - printOperand(MI, opNum+1); + printOperand(MI, opNum+1, O); return; } @@ -124,14 +129,15 @@ void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum, if (MI->getOperand(opNum+1).isGlobal() || MI->getOperand(opNum+1).isCPI()) { O << "%lo("; - printOperand(MI, opNum+1); + printOperand(MI, opNum+1, O); O << ")"; } else { - printOperand(MI, opNum+1); + printOperand(MI, opNum+1, O); } } -bool SparcAsmPrinter::printGetPCX(const MachineInstr *MI, unsigned opNum) { +bool SparcAsmPrinter::printGetPCX(const MachineInstr *MI, unsigned opNum, + raw_ostream &O) { std::string operand = ""; const MachineOperand &MO = MI->getOperand(opNum); switch (MO.getType()) { @@ -155,14 +161,15 @@ bool SparcAsmPrinter::printGetPCX(const MachineInstr *MI, unsigned opNum) { O << ".LLGETPC" << mfNum << '_' << bbNum << ":\n" ; O << "\tor\t" << operand - << ", %lo(_GLOBAL_OFFSET_TABLE_+(.-.LLGETPCH" << mfNum << '_' << bbNum << ")), " - << operand << '\n'; + << ", %lo(_GLOBAL_OFFSET_TABLE_+(.-.LLGETPCH" << mfNum << '_' << bbNum + << ")), " << operand << '\n'; O << "\tadd\t" << operand << ", %o7, " << operand << '\n'; return true; } -void SparcAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) { +void SparcAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum, + raw_ostream &O) { int CC = (int)MI->getOperand(opNum).getImm(); O << SPARCCondCodeToString((SPCC::CondCodes)CC); } @@ -171,7 +178,8 @@ void SparcAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) { /// bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, - const char *ExtraCode) { + const char *ExtraCode, + raw_ostream &O) { if (ExtraCode && ExtraCode[0]) { if (ExtraCode[1] != 0) return true; // Unknown modifier. @@ -182,20 +190,20 @@ bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, } } - printOperand(MI, OpNo); + printOperand(MI, OpNo, O); return false; } bool SparcAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, - unsigned OpNo, - unsigned AsmVariant, - const char *ExtraCode) { + unsigned OpNo, unsigned AsmVariant, + const char *ExtraCode, + raw_ostream &O) { if (ExtraCode && ExtraCode[0]) return true; // Unknown modifier O << '['; - printMemOperand(MI, OpNo); + printMemOperand(MI, OpNo, O); O << ']'; return false; diff --git a/lib/Target/Sparc/Sparc.td b/lib/Target/Sparc/Sparc.td index 53ea8f4a35f0..925d782d988b 100644 --- a/lib/Target/Sparc/Sparc.td +++ b/lib/Target/Sparc/Sparc.td @@ -38,11 +38,7 @@ include "SparcRegisterInfo.td" include "SparcCallingConv.td" include "SparcInstrInfo.td" -def SparcInstrInfo : InstrInfo { - // Define how we want to layout our target-specific information field. - let TSFlagsFields = []; - let TSFlagsShifts = []; -} +def SparcInstrInfo : InstrInfo; //===----------------------------------------------------------------------===// // SPARC processors supported. diff --git a/lib/Target/Sparc/SparcMCAsmInfo.cpp b/lib/Target/Sparc/SparcMCAsmInfo.cpp index 53a9bde92526..535c6f7c8a27 100644 --- a/lib/Target/Sparc/SparcMCAsmInfo.cpp +++ b/lib/Target/Sparc/SparcMCAsmInfo.cpp @@ -22,7 +22,6 @@ SparcELFMCAsmInfo::SparcELFMCAsmInfo(const Target &T, const StringRef &TT) { ZeroDirective = "\t.skip\t"; CommentString = "!"; HasLEB128 = true; - AbsoluteDebugSectionOffsets = true; SupportsDebugInformation = true; SunStyleELFSectionSwitchSyntax = true; diff --git a/lib/Target/SystemZ/AsmPrinter/SystemZAsmPrinter.cpp b/lib/Target/SystemZ/AsmPrinter/SystemZAsmPrinter.cpp index b29dfcdc9846..07cfb2c83e33 100644 --- a/lib/Target/SystemZ/AsmPrinter/SystemZAsmPrinter.cpp +++ b/lib/Target/SystemZ/AsmPrinter/SystemZAsmPrinter.cpp @@ -21,11 +21,9 @@ #include "llvm/Module.h" #include "llvm/Assembly/Writer.h" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/DwarfWriter.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineConstantPool.h" -#include "llvm/CodeGen/MachineInstr.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCSymbol.h" @@ -33,56 +31,52 @@ #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetRegistry.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FormattedStream.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; namespace { class SystemZAsmPrinter : public AsmPrinter { public: - SystemZAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, - MCStreamer &Streamer) - : AsmPrinter(O, TM, Streamer) {} + SystemZAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : AsmPrinter(TM, Streamer) {} virtual const char *getPassName() const { return "SystemZ Assembly Printer"; } - void printOperand(const MachineInstr *MI, int OpNum, + void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O, const char* Modifier = 0); - void printPCRelImmOperand(const MachineInstr *MI, int OpNum); - void printRIAddrOperand(const MachineInstr *MI, int OpNum, + void printPCRelImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O); + void printRIAddrOperand(const MachineInstr *MI, int OpNum, raw_ostream &O, const char* Modifier = 0); - void printRRIAddrOperand(const MachineInstr *MI, int OpNum, + void printRRIAddrOperand(const MachineInstr *MI, int OpNum, raw_ostream &O, const char* Modifier = 0); - void printS16ImmOperand(const MachineInstr *MI, int OpNum) { + void printS16ImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O) { O << (int16_t)MI->getOperand(OpNum).getImm(); } - void printS32ImmOperand(const MachineInstr *MI, int OpNum) { + void printS32ImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O) { O << (int32_t)MI->getOperand(OpNum).getImm(); } - void printInstruction(const MachineInstr *MI); // autogenerated. + void printInstruction(const MachineInstr *MI, raw_ostream &O); static const char *getRegisterName(unsigned RegNo); void EmitInstruction(const MachineInstr *MI); - - void getAnalysisUsage(AnalysisUsage &AU) const { - AsmPrinter::getAnalysisUsage(AU); - AU.setPreservesAll(); - } }; } // end of anonymous namespace #include "SystemZGenAsmWriter.inc" void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) { - // Call the autogenerated instruction printer routines. - printInstruction(MI); - OutStreamer.AddBlankLine(); + SmallString<128> Str; + raw_svector_ostream OS(Str); + printInstruction(MI, OS); + OutStreamer.EmitRawText(OS.str()); } -void SystemZAsmPrinter::printPCRelImmOperand(const MachineInstr *MI, int OpNum){ +void SystemZAsmPrinter::printPCRelImmOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O) { const MachineOperand &MO = MI->getOperand(OpNum); switch (MO.getType()) { case MachineOperand::MO_Immediate: @@ -101,7 +95,7 @@ void SystemZAsmPrinter::printPCRelImmOperand(const MachineInstr *MI, int OpNum){ !GV->hasLocalLinkage()) O << "@PLT"; - printOffset(MO.getOffset()); + printOffset(MO.getOffset(), O); return; } case MachineOperand::MO_ExternalSymbol: { @@ -121,7 +115,7 @@ void SystemZAsmPrinter::printPCRelImmOperand(const MachineInstr *MI, int OpNum){ void SystemZAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, - const char* Modifier) { + raw_ostream &O, const char *Modifier) { const MachineOperand &MO = MI->getOperand(OpNum); switch (MO.getType()) { case MachineOperand::MO_Register: { @@ -130,9 +124,9 @@ void SystemZAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, unsigned Reg = MO.getReg(); if (Modifier && strncmp(Modifier, "subreg", 6) == 0) { if (strncmp(Modifier + 7, "even", 4) == 0) - Reg = TRI->getSubReg(Reg, SystemZ::SUBREG_EVEN); + Reg = TM.getRegisterInfo()->getSubReg(Reg, SystemZ::SUBREG_EVEN); else if (strncmp(Modifier + 7, "odd", 3) == 0) - Reg = TRI->getSubReg(Reg, SystemZ::SUBREG_ODD); + Reg = TM.getRegisterInfo()->getSubReg(Reg, SystemZ::SUBREG_ODD); else assert(0 && "Invalid subreg modifier"); } @@ -155,7 +149,7 @@ void SystemZAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' << MO.getIndex(); - printOffset(MO.getOffset()); + printOffset(MO.getOffset(), O); break; case MachineOperand::MO_GlobalAddress: O << *Mang->getSymbol(MO.getGlobal()); @@ -169,47 +163,48 @@ void SystemZAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, } switch (MO.getTargetFlags()) { - default: - llvm_unreachable("Unknown target flag on GV operand"); + default: assert(0 && "Unknown target flag on GV operand"); case SystemZII::MO_NO_FLAG: break; case SystemZII::MO_GOTENT: O << "@GOTENT"; break; case SystemZII::MO_PLT: O << "@PLT"; break; } - printOffset(MO.getOffset()); + printOffset(MO.getOffset(), O); } void SystemZAsmPrinter::printRIAddrOperand(const MachineInstr *MI, int OpNum, - const char* Modifier) { + raw_ostream &O, + const char *Modifier) { const MachineOperand &Base = MI->getOperand(OpNum); // Print displacement operand. - printOperand(MI, OpNum+1); + printOperand(MI, OpNum+1, O); // Print base operand (if any) if (Base.getReg()) { O << '('; - printOperand(MI, OpNum); + printOperand(MI, OpNum, O); O << ')'; } } void SystemZAsmPrinter::printRRIAddrOperand(const MachineInstr *MI, int OpNum, - const char* Modifier) { + raw_ostream &O, + const char *Modifier) { const MachineOperand &Base = MI->getOperand(OpNum); const MachineOperand &Index = MI->getOperand(OpNum+2); // Print displacement operand. - printOperand(MI, OpNum+1); + printOperand(MI, OpNum+1, O); // Print base operand (if any) if (Base.getReg()) { O << '('; - printOperand(MI, OpNum); + printOperand(MI, OpNum, O); if (Index.getReg()) { O << ','; - printOperand(MI, OpNum+2); + printOperand(MI, OpNum+2, O); } O << ')'; } else diff --git a/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp b/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp index 734a545555f9..0b64cb4f2828 100644 --- a/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp +++ b/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp @@ -29,15 +29,18 @@ using namespace llvm; #include "X86GenAsmWriter.inc" #undef MachineInstr -void X86ATTInstPrinter::printInst(const MCInst *MI) { printInstruction(MI); } +void X86ATTInstPrinter::printInst(const MCInst *MI, raw_ostream &OS) { + printInstruction(MI, OS); +} StringRef X86ATTInstPrinter::getOpcodeName(unsigned Opcode) const { return getInstructionName(Opcode); } -void X86ATTInstPrinter::printSSECC(const MCInst *MI, unsigned Op) { +void X86ATTInstPrinter::printSSECC(const MCInst *MI, unsigned Op, + raw_ostream &O) { switch (MI->getOperand(Op).getImm()) { - default: llvm_unreachable("Invalid ssecc argument!"); + default: assert(0 && "Invalid ssecc argument!"); case 0: O << "eq"; break; case 1: O << "lt"; break; case 2: O << "le"; break; @@ -53,7 +56,8 @@ void X86ATTInstPrinter::printSSECC(const MCInst *MI, unsigned Op) { /// being encoded as a pc-relative value (e.g. for jumps and calls). These /// print slightly differently than normal immediates. For example, a $ is not /// emitted. -void X86ATTInstPrinter::print_pcrel_imm(const MCInst *MI, unsigned OpNo) { +void X86ATTInstPrinter::print_pcrel_imm(const MCInst *MI, unsigned OpNo, + raw_ostream &O) { const MCOperand &Op = MI->getOperand(OpNo); if (Op.isImm()) // Print this as a signed 32-bit value. @@ -64,8 +68,8 @@ void X86ATTInstPrinter::print_pcrel_imm(const MCInst *MI, unsigned OpNo) { } } -void X86ATTInstPrinter::printOperand(const MCInst *MI, unsigned OpNo) { - +void X86ATTInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, + raw_ostream &O) { const MCOperand &Op = MI->getOperand(OpNo); if (Op.isReg()) { O << '%' << getRegisterName(Op.getReg()); @@ -81,7 +85,8 @@ void X86ATTInstPrinter::printOperand(const MCInst *MI, unsigned OpNo) { } } -void X86ATTInstPrinter::printLeaMemReference(const MCInst *MI, unsigned Op) { +void X86ATTInstPrinter::printLeaMemReference(const MCInst *MI, unsigned Op, + raw_ostream &O) { const MCOperand &BaseReg = MI->getOperand(Op); const MCOperand &IndexReg = MI->getOperand(Op+2); const MCOperand &DispSpec = MI->getOperand(Op+3); @@ -98,11 +103,11 @@ void X86ATTInstPrinter::printLeaMemReference(const MCInst *MI, unsigned Op) { if (IndexReg.getReg() || BaseReg.getReg()) { O << '('; if (BaseReg.getReg()) - printOperand(MI, Op); + printOperand(MI, Op, O); if (IndexReg.getReg()) { O << ','; - printOperand(MI, Op+2); + printOperand(MI, Op+2, O); unsigned ScaleVal = MI->getOperand(Op+1).getImm(); if (ScaleVal != 1) O << ',' << ScaleVal; @@ -111,11 +116,12 @@ void X86ATTInstPrinter::printLeaMemReference(const MCInst *MI, unsigned Op) { } } -void X86ATTInstPrinter::printMemReference(const MCInst *MI, unsigned Op) { +void X86ATTInstPrinter::printMemReference(const MCInst *MI, unsigned Op, + raw_ostream &O) { // If this has a segment register, print it. if (MI->getOperand(Op+4).getReg()) { - printOperand(MI, Op+4); + printOperand(MI, Op+4, O); O << ':'; } - printLeaMemReference(MI, Op); + printLeaMemReference(MI, Op, O); } diff --git a/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.h b/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.h index d109a075b85c..8d5d50832d49 100644 --- a/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.h +++ b/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.h @@ -21,63 +21,62 @@ namespace llvm { class X86ATTInstPrinter : public MCInstPrinter { public: - X86ATTInstPrinter(raw_ostream &O, const MCAsmInfo &MAI) - : MCInstPrinter(O, MAI) {} + X86ATTInstPrinter(const MCAsmInfo &MAI) : MCInstPrinter(MAI) {} - virtual void printInst(const MCInst *MI); + virtual void printInst(const MCInst *MI, raw_ostream &OS); virtual StringRef getOpcodeName(unsigned Opcode) const; // Autogenerated by tblgen. - void printInstruction(const MCInst *MI); + void printInstruction(const MCInst *MI, raw_ostream &OS); static const char *getRegisterName(unsigned RegNo); static const char *getInstructionName(unsigned Opcode); - void printOperand(const MCInst *MI, unsigned OpNo); - void printMemReference(const MCInst *MI, unsigned Op); - void printLeaMemReference(const MCInst *MI, unsigned Op); - void printSSECC(const MCInst *MI, unsigned Op); - void print_pcrel_imm(const MCInst *MI, unsigned OpNo); + void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &OS); + void printMemReference(const MCInst *MI, unsigned Op, raw_ostream &OS); + void printLeaMemReference(const MCInst *MI, unsigned Op, raw_ostream &OS); + void printSSECC(const MCInst *MI, unsigned Op, raw_ostream &OS); + void print_pcrel_imm(const MCInst *MI, unsigned OpNo, raw_ostream &OS); - void printopaquemem(const MCInst *MI, unsigned OpNo) { - printMemReference(MI, OpNo); + void printopaquemem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { + printMemReference(MI, OpNo, O); } - void printi8mem(const MCInst *MI, unsigned OpNo) { - printMemReference(MI, OpNo); + void printi8mem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { + printMemReference(MI, OpNo, O); } - void printi16mem(const MCInst *MI, unsigned OpNo) { - printMemReference(MI, OpNo); + void printi16mem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { + printMemReference(MI, OpNo, O); } - void printi32mem(const MCInst *MI, unsigned OpNo) { - printMemReference(MI, OpNo); + void printi32mem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { + printMemReference(MI, OpNo, O); } - void printi64mem(const MCInst *MI, unsigned OpNo) { - printMemReference(MI, OpNo); + void printi64mem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { + printMemReference(MI, OpNo, O); } - void printi128mem(const MCInst *MI, unsigned OpNo) { - printMemReference(MI, OpNo); + void printi128mem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { + printMemReference(MI, OpNo, O); } - void printf32mem(const MCInst *MI, unsigned OpNo) { - printMemReference(MI, OpNo); + void printf32mem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { + printMemReference(MI, OpNo, O); } - void printf64mem(const MCInst *MI, unsigned OpNo) { - printMemReference(MI, OpNo); + void printf64mem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { + printMemReference(MI, OpNo, O); } - void printf80mem(const MCInst *MI, unsigned OpNo) { - printMemReference(MI, OpNo); + void printf80mem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { + printMemReference(MI, OpNo, O); } - void printf128mem(const MCInst *MI, unsigned OpNo) { - printMemReference(MI, OpNo); + void printf128mem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { + printMemReference(MI, OpNo, O); } - void printlea32mem(const MCInst *MI, unsigned OpNo) { - printLeaMemReference(MI, OpNo); + void printlea32mem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { + printLeaMemReference(MI, OpNo, O); } - void printlea64mem(const MCInst *MI, unsigned OpNo) { - printLeaMemReference(MI, OpNo); + void printlea64mem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { + printLeaMemReference(MI, OpNo, O); } - void printlea64_32mem(const MCInst *MI, unsigned OpNo) { - printLeaMemReference(MI, OpNo); + void printlea64_32mem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { + printLeaMemReference(MI, OpNo, O); } }; diff --git a/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp b/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp index 66bb914edde5..f5923969361d 100644 --- a/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp +++ b/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp @@ -36,7 +36,6 @@ #include "llvm/CodeGen/MachineModuleInfoImpls.h" #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FormattedStream.h" #include "llvm/Target/Mangler.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegistry.h" @@ -47,7 +46,7 @@ using namespace llvm; // Primitive Helper Functions. //===----------------------------------------------------------------------===// -void X86AsmPrinter::PrintPICBaseSymbol() const { +void X86AsmPrinter::PrintPICBaseSymbol(raw_ostream &O) const { const TargetLowering *TLI = TM.getTargetLowering(); O << *static_cast<const X86TargetLowering*>(TLI)->getPICBaseSymbol(MF, OutContext); @@ -60,10 +59,11 @@ bool X86AsmPrinter::runOnMachineFunction(MachineFunction &MF) { if (Subtarget->isTargetCOFF()) { const Function *F = MF.getFunction(); - O << "\t.def\t " << *CurrentFnSym << ";\t.scl\t" << - (F->hasInternalLinkage() ? COFF::C_STAT : COFF::C_EXT) - << ";\t.type\t" << (COFF::DT_FCN << COFF::N_BTSHFT) - << ";\t.endef\n"; + OutStreamer.EmitRawText("\t.def\t " + Twine(CurrentFnSym->getName()) + + ";\t.scl\t" + + Twine(F->hasInternalLinkage() ? COFF::C_STAT : COFF::C_EXT) + + ";\t.type\t" + Twine(COFF::DT_FCN << COFF::N_BTSHFT) + + ";\t.endef"); } // Have common code print out the function header with linkage info etc. @@ -79,7 +79,8 @@ bool X86AsmPrinter::runOnMachineFunction(MachineFunction &MF) { /// printSymbolOperand - Print a raw symbol reference operand. This handles /// jump tables, constant pools, global address and external symbols, all of /// which print to a label with various suffixes for relocation types etc. -void X86AsmPrinter::printSymbolOperand(const MachineOperand &MO) { +void X86AsmPrinter::printSymbolOperand(const MachineOperand &MO, + raw_ostream &O) { switch (MO.getType()) { default: llvm_unreachable("unknown symbol type!"); case MachineOperand::MO_JumpTableIndex: @@ -87,7 +88,7 @@ void X86AsmPrinter::printSymbolOperand(const MachineOperand &MO) { break; case MachineOperand::MO_ConstantPoolIndex: O << *GetCPISymbol(MO.getIndex()); - printOffset(MO.getOffset()); + printOffset(MO.getOffset(), O); break; case MachineOperand::MO_GlobalAddress: { const GlobalValue *GV = MO.getGlobal(); @@ -136,7 +137,7 @@ void X86AsmPrinter::printSymbolOperand(const MachineOperand &MO) { O << *GVSym; else O << '(' << *GVSym << ')'; - printOffset(MO.getOffset()); + printOffset(MO.getOffset(), O); break; } case MachineOperand::MO_ExternalSymbol: { @@ -182,14 +183,14 @@ void X86AsmPrinter::printSymbolOperand(const MachineOperand &MO) { break; case X86II::MO_GOT_ABSOLUTE_ADDRESS: O << " + [.-"; - PrintPICBaseSymbol(); + PrintPICBaseSymbol(O); O << ']'; break; case X86II::MO_PIC_BASE_OFFSET: case X86II::MO_DARWIN_NONLAZY_PIC_BASE: case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: O << '-'; - PrintPICBaseSymbol(); + PrintPICBaseSymbol(O); break; case X86II::MO_TLSGD: O << "@TLSGD"; break; case X86II::MO_GOTTPOFF: O << "@GOTTPOFF"; break; @@ -206,7 +207,8 @@ void X86AsmPrinter::printSymbolOperand(const MachineOperand &MO) { /// print_pcrel_imm - This is used to print an immediate value that ends up /// being encoded as a pc-relative value. These print slightly differently, for /// example, a $ is not emitted. -void X86AsmPrinter::print_pcrel_imm(const MachineInstr *MI, unsigned OpNo) { +void X86AsmPrinter::print_pcrel_imm(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { const MachineOperand &MO = MI->getOperand(OpNo); switch (MO.getType()) { default: llvm_unreachable("Unknown pcrel immediate operand"); @@ -218,14 +220,14 @@ void X86AsmPrinter::print_pcrel_imm(const MachineInstr *MI, unsigned OpNo) { return; case MachineOperand::MO_GlobalAddress: case MachineOperand::MO_ExternalSymbol: - printSymbolOperand(MO); + printSymbolOperand(MO, O); return; } } void X86AsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, - const char *Modifier) { + raw_ostream &O, const char *Modifier) { const MachineOperand &MO = MI->getOperand(OpNo); switch (MO.getType()) { default: llvm_unreachable("unknown operand type!"); @@ -251,13 +253,14 @@ void X86AsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, case MachineOperand::MO_GlobalAddress: case MachineOperand::MO_ExternalSymbol: { O << '$'; - printSymbolOperand(MO); + printSymbolOperand(MO, O); break; } } } -void X86AsmPrinter::printSSECC(const MachineInstr *MI, unsigned Op) { +void X86AsmPrinter::printSSECC(const MachineInstr *MI, unsigned Op, + raw_ostream &O) { unsigned char value = MI->getOperand(Op).getImm(); assert(value <= 7 && "Invalid ssecc argument!"); switch (value) { @@ -273,7 +276,7 @@ void X86AsmPrinter::printSSECC(const MachineInstr *MI, unsigned Op) { } void X86AsmPrinter::printLeaMemReference(const MachineInstr *MI, unsigned Op, - const char *Modifier) { + raw_ostream &O, const char *Modifier) { const MachineOperand &BaseReg = MI->getOperand(Op); const MachineOperand &IndexReg = MI->getOperand(Op+2); const MachineOperand &DispSpec = MI->getOperand(Op+3); @@ -294,7 +297,7 @@ void X86AsmPrinter::printLeaMemReference(const MachineInstr *MI, unsigned Op, } else { assert(DispSpec.isGlobal() || DispSpec.isCPI() || DispSpec.isJTI() || DispSpec.isSymbol()); - printSymbolOperand(MI->getOperand(Op+3)); + printSymbolOperand(MI->getOperand(Op+3), O); } if (HasParenPart) { @@ -303,11 +306,11 @@ void X86AsmPrinter::printLeaMemReference(const MachineInstr *MI, unsigned Op, O << '('; if (HasBaseReg) - printOperand(MI, Op, Modifier); + printOperand(MI, Op, O, Modifier); if (IndexReg.getReg()) { O << ','; - printOperand(MI, Op+2, Modifier); + printOperand(MI, Op+2, O, Modifier); unsigned ScaleVal = MI->getOperand(Op+1).getImm(); if (ScaleVal != 1) O << ',' << ScaleVal; @@ -317,24 +320,26 @@ void X86AsmPrinter::printLeaMemReference(const MachineInstr *MI, unsigned Op, } void X86AsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op, - const char *Modifier) { + raw_ostream &O, const char *Modifier) { assert(isMem(MI, Op) && "Invalid memory reference!"); const MachineOperand &Segment = MI->getOperand(Op+4); if (Segment.getReg()) { - printOperand(MI, Op+4, Modifier); + printOperand(MI, Op+4, O, Modifier); O << ':'; } - printLeaMemReference(MI, Op, Modifier); + printLeaMemReference(MI, Op, O, Modifier); } -void X86AsmPrinter::printPICLabel(const MachineInstr *MI, unsigned Op) { - PrintPICBaseSymbol(); +void X86AsmPrinter::printPICLabel(const MachineInstr *MI, unsigned Op, + raw_ostream &O) { + PrintPICBaseSymbol(O); O << '\n'; - PrintPICBaseSymbol(); + PrintPICBaseSymbol(O); O << ':'; } -bool X86AsmPrinter::printAsmMRegister(const MachineOperand &MO, char Mode) { +bool X86AsmPrinter::printAsmMRegister(const MachineOperand &MO, char Mode, + raw_ostream &O) { unsigned Reg = MO.getReg(); switch (Mode) { default: return true; // Unknown mode. @@ -363,7 +368,7 @@ bool X86AsmPrinter::printAsmMRegister(const MachineOperand &MO, char Mode) { /// bool X86AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, - const char *ExtraCode) { + const char *ExtraCode, raw_ostream &O) { // Does this asm operand have a single letter operand modifier? if (ExtraCode && ExtraCode[0]) { if (ExtraCode[1] != 0) return true; // Unknown modifier. @@ -378,12 +383,12 @@ bool X86AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, return false; } if (MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isSymbol()) { - printSymbolOperand(MO); + printSymbolOperand(MO, O); return false; } if (MO.isReg()) { O << '('; - printOperand(MI, OpNo); + printOperand(MI, OpNo, O); O << ')'; return false; } @@ -393,15 +398,15 @@ bool X86AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, if (MO.isImm()) O << MO.getImm(); else if (MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isSymbol()) - printSymbolOperand(MO); + printSymbolOperand(MO, O); else - printOperand(MI, OpNo); + printOperand(MI, OpNo, O); return false; case 'A': // Print '*' before a register (it must be a register) if (MO.isReg()) { O << '*'; - printOperand(MI, OpNo); + printOperand(MI, OpNo, O); return false; } return true; @@ -412,12 +417,12 @@ bool X86AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, case 'k': // Print SImode register case 'q': // Print DImode register if (MO.isReg()) - return printAsmMRegister(MO, ExtraCode[0]); - printOperand(MI, OpNo); + return printAsmMRegister(MO, ExtraCode[0], O); + printOperand(MI, OpNo, O); return false; case 'P': // This is the operand of a call, treat specially. - print_pcrel_imm(MI, OpNo); + print_pcrel_imm(MI, OpNo, O); return false; case 'n': // Negate the immediate or print a '-' before the operand. @@ -431,13 +436,14 @@ bool X86AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, } } - printOperand(MI, OpNo); + printOperand(MI, OpNo, O); return false; } bool X86AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, - const char *ExtraCode) { + const char *ExtraCode, + raw_ostream &O) { if (ExtraCode && ExtraCode[0]) { if (ExtraCode[1] != 0) return true; // Unknown modifier. @@ -451,11 +457,11 @@ bool X86AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, // These only apply to registers, ignore on mem. break; case 'P': // Don't print @PLT, but do print as memory. - printMemReference(MI, OpNo, "no-rip"); + printMemReference(MI, OpNo, O, "no-rip"); return false; } } - printMemReference(MI, OpNo); + printMemReference(MI, OpNo, O); return false; } @@ -570,10 +576,11 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { // Emit type information for external functions for (X86COFFMachineModuleInfo::stub_iterator I = COFFMMI.stub_begin(), E = COFFMMI.stub_end(); I != E; ++I) { - O << "\t.def\t " << I->getKeyData() - << ";\t.scl\t" << COFF::C_EXT - << ";\t.type\t" << (COFF::DT_FCN << COFF::N_BTSHFT) - << ";\t.endef\n"; + OutStreamer.EmitRawText("\t.def\t " + Twine(I->getKeyData()) + + ";\t.scl\t" + Twine(COFF::C_EXT) + + ";\t.type\t" + + Twine(COFF::DT_FCN << COFF::N_BTSHFT) + + ";\t.endef"); } if (Subtarget->isTargetCygMing()) { @@ -598,10 +605,13 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { true, SectionKind::getMetadata())); for (unsigned i = 0, e = DLLExportedGlobals.size(); i != e; ++i) - O << "\t.ascii \" -export:" << *DLLExportedGlobals[i] << ",data\"\n"; + OutStreamer.EmitRawText("\t.ascii \" -export:" + + Twine(DLLExportedGlobals[i]->getName()) + + ",data\""); for (unsigned i = 0, e = DLLExportedFns.size(); i != e; ++i) - O << "\t.ascii \" -export:" << *DLLExportedFns[i] << "\"\n"; + OutStreamer.EmitRawText("\t.ascii \" -export:" + + Twine(DLLExportedFns[i]->getName()) + "\""); } } } @@ -618,12 +628,11 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { OutStreamer.SwitchSection(TLOFELF.getDataRelSection()); const TargetData *TD = TM.getTargetData(); - for (unsigned i = 0, e = Stubs.size(); i != e; ++i) - O << *Stubs[i].first << ":\n" - << (TD->getPointerSize() == 8 ? - MAI->getData64bitsDirective() : MAI->getData32bitsDirective()) - << *Stubs[i].second.getPointer() << '\n'; - + for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { + OutStreamer.EmitLabel(Stubs[i].first); + OutStreamer.EmitSymbolValue(Stubs[i].second.getPointer(), + TD->getPointerSize(), 0); + } Stubs.clear(); } } @@ -636,12 +645,11 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { static MCInstPrinter *createX86MCInstPrinter(const Target &T, unsigned SyntaxVariant, - const MCAsmInfo &MAI, - raw_ostream &O) { + const MCAsmInfo &MAI) { if (SyntaxVariant == 0) - return new X86ATTInstPrinter(O, MAI); + return new X86ATTInstPrinter(MAI); if (SyntaxVariant == 1) - return new X86IntelInstPrinter(O, MAI); + return new X86IntelInstPrinter(MAI); return 0; } diff --git a/lib/Target/X86/AsmPrinter/X86AsmPrinter.h b/lib/Target/X86/AsmPrinter/X86AsmPrinter.h index 28c25f9b8abe..ee59289dc572 100644 --- a/lib/Target/X86/AsmPrinter/X86AsmPrinter.h +++ b/lib/Target/X86/AsmPrinter/X86AsmPrinter.h @@ -19,7 +19,6 @@ #include "../X86TargetMachine.h" #include "llvm/ADT/StringSet.h" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/DwarfWriter.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/Support/Compiler.h" @@ -35,9 +34,8 @@ class MCSymbol; class VISIBILITY_HIDDEN X86AsmPrinter : public AsmPrinter { const X86Subtarget *Subtarget; public: - explicit X86AsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, - MCStreamer &Streamer) - : AsmPrinter(O, TM, Streamer) { + explicit X86AsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : AsmPrinter(TM, Streamer) { Subtarget = &TM.getSubtarget<X86Subtarget>(); } @@ -47,85 +45,41 @@ class VISIBILITY_HIDDEN X86AsmPrinter : public AsmPrinter { const X86Subtarget &getSubtarget() const { return *Subtarget; } - void getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesAll(); - AU.addRequired<MachineModuleInfo>(); - AU.addRequired<DwarfWriter>(); - AsmPrinter::getAnalysisUsage(AU); - } - virtual void EmitStartOfAsmFile(Module &M); virtual void EmitEndOfAsmFile(Module &M); virtual void EmitInstruction(const MachineInstr *MI); - void printSymbolOperand(const MachineOperand &MO); + void printSymbolOperand(const MachineOperand &MO, raw_ostream &O); // These methods are used by the tablegen'erated instruction printer. - void printOperand(const MachineInstr *MI, unsigned OpNo, + void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O, const char *Modifier = 0); - void print_pcrel_imm(const MachineInstr *MI, unsigned OpNo); - - void printopaquemem(const MachineInstr *MI, unsigned OpNo) { - printMemReference(MI, OpNo); - } - - void printi8mem(const MachineInstr *MI, unsigned OpNo) { - printMemReference(MI, OpNo); - } - void printi16mem(const MachineInstr *MI, unsigned OpNo) { - printMemReference(MI, OpNo); - } - void printi32mem(const MachineInstr *MI, unsigned OpNo) { - printMemReference(MI, OpNo); - } - void printi64mem(const MachineInstr *MI, unsigned OpNo) { - printMemReference(MI, OpNo); - } - void printi128mem(const MachineInstr *MI, unsigned OpNo) { - printMemReference(MI, OpNo); - } - void printf32mem(const MachineInstr *MI, unsigned OpNo) { - printMemReference(MI, OpNo); - } - void printf64mem(const MachineInstr *MI, unsigned OpNo) { - printMemReference(MI, OpNo); - } - void printf80mem(const MachineInstr *MI, unsigned OpNo) { - printMemReference(MI, OpNo); - } - void printf128mem(const MachineInstr *MI, unsigned OpNo) { - printMemReference(MI, OpNo); - } - void printlea32mem(const MachineInstr *MI, unsigned OpNo) { - printLeaMemReference(MI, OpNo); - } - void printlea64mem(const MachineInstr *MI, unsigned OpNo) { - printLeaMemReference(MI, OpNo); - } - void printlea64_32mem(const MachineInstr *MI, unsigned OpNo) { - printLeaMemReference(MI, OpNo, "subreg64"); - } + void print_pcrel_imm(const MachineInstr *MI, unsigned OpNo, raw_ostream &O); - bool printAsmMRegister(const MachineOperand &MO, char Mode); + bool printAsmMRegister(const MachineOperand &MO, char Mode, raw_ostream &O); bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode); + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &OS); bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode); + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &OS); void printMachineInstruction(const MachineInstr *MI); - void printSSECC(const MachineInstr *MI, unsigned Op); - void printMemReference(const MachineInstr *MI, unsigned Op, + void printSSECC(const MachineInstr *MI, unsigned Op, raw_ostream &O); + void printMemReference(const MachineInstr *MI, unsigned Op, raw_ostream &O, const char *Modifier=NULL); - void printLeaMemReference(const MachineInstr *MI, unsigned Op, + void printLeaMemReference(const MachineInstr *MI, unsigned Op, raw_ostream &O, const char *Modifier=NULL); - void printPICLabel(const MachineInstr *MI, unsigned Op); + void printPICLabel(const MachineInstr *MI, unsigned Op, raw_ostream &O); - void PrintPICBaseSymbol() const; + void PrintPICBaseSymbol(raw_ostream &O) const; bool runOnMachineFunction(MachineFunction &F); + + void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS); }; } // end namespace llvm diff --git a/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp b/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp index 610beb550b24..7e0a9bb891fa 100644 --- a/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp +++ b/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp @@ -28,14 +28,17 @@ using namespace llvm; #include "X86GenAsmWriter1.inc" #undef MachineInstr -void X86IntelInstPrinter::printInst(const MCInst *MI) { printInstruction(MI); } +void X86IntelInstPrinter::printInst(const MCInst *MI, raw_ostream &OS) { + printInstruction(MI, OS); +} StringRef X86IntelInstPrinter::getOpcodeName(unsigned Opcode) const { return getInstructionName(Opcode); } -void X86IntelInstPrinter::printSSECC(const MCInst *MI, unsigned Op) { +void X86IntelInstPrinter::printSSECC(const MCInst *MI, unsigned Op, + raw_ostream &O) { switch (MI->getOperand(Op).getImm()) { - default: llvm_unreachable("Invalid ssecc argument!"); + default: assert(0 && "Invalid ssecc argument!"); case 0: O << "eq"; break; case 1: O << "lt"; break; case 2: O << "le"; break; @@ -49,7 +52,8 @@ void X86IntelInstPrinter::printSSECC(const MCInst *MI, unsigned Op) { /// print_pcrel_imm - This is used to print an immediate value that ends up /// being encoded as a pc-relative value. -void X86IntelInstPrinter::print_pcrel_imm(const MCInst *MI, unsigned OpNo) { +void X86IntelInstPrinter::print_pcrel_imm(const MCInst *MI, unsigned OpNo, + raw_ostream &O) { const MCOperand &Op = MI->getOperand(OpNo); if (Op.isImm()) O << Op.getImm(); @@ -65,9 +69,7 @@ static void PrintRegName(raw_ostream &O, StringRef RegName) { } void X86IntelInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, - const char *Modifier) { - assert(Modifier == 0 && "Modifiers should not be used"); - + raw_ostream &O) { const MCOperand &Op = MI->getOperand(OpNo); if (Op.isReg()) { PrintRegName(O, getRegisterName(Op.getReg())); @@ -79,7 +81,8 @@ void X86IntelInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, } } -void X86IntelInstPrinter::printLeaMemReference(const MCInst *MI, unsigned Op) { +void X86IntelInstPrinter::printLeaMemReference(const MCInst *MI, unsigned Op, + raw_ostream &O) { const MCOperand &BaseReg = MI->getOperand(Op); unsigned ScaleVal = MI->getOperand(Op+1).getImm(); const MCOperand &IndexReg = MI->getOperand(Op+2); @@ -89,7 +92,7 @@ void X86IntelInstPrinter::printLeaMemReference(const MCInst *MI, unsigned Op) { bool NeedPlus = false; if (BaseReg.getReg()) { - printOperand(MI, Op); + printOperand(MI, Op, O); NeedPlus = true; } @@ -97,7 +100,7 @@ void X86IntelInstPrinter::printLeaMemReference(const MCInst *MI, unsigned Op) { if (NeedPlus) O << " + "; if (ScaleVal != 1) O << ScaleVal << '*'; - printOperand(MI, Op+2); + printOperand(MI, Op+2, O); NeedPlus = true; } @@ -124,11 +127,12 @@ void X86IntelInstPrinter::printLeaMemReference(const MCInst *MI, unsigned Op) { O << ']'; } -void X86IntelInstPrinter::printMemReference(const MCInst *MI, unsigned Op) { +void X86IntelInstPrinter::printMemReference(const MCInst *MI, unsigned Op, + raw_ostream &O) { // If this has a segment register, print it. if (MI->getOperand(Op+4).getReg()) { - printOperand(MI, Op+4); + printOperand(MI, Op+4, O); O << ':'; } - printLeaMemReference(MI, Op); + printLeaMemReference(MI, Op, O); } diff --git a/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.h b/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.h index 545bf84b916f..a0beeb202e72 100644 --- a/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.h +++ b/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.h @@ -22,77 +22,76 @@ namespace llvm { class X86IntelInstPrinter : public MCInstPrinter { public: - X86IntelInstPrinter(raw_ostream &O, const MCAsmInfo &MAI) - : MCInstPrinter(O, MAI) {} + X86IntelInstPrinter(const MCAsmInfo &MAI) + : MCInstPrinter(MAI) {} - virtual void printInst(const MCInst *MI); + virtual void printInst(const MCInst *MI, raw_ostream &OS); virtual StringRef getOpcodeName(unsigned Opcode) const; // Autogenerated by tblgen. - void printInstruction(const MCInst *MI); + void printInstruction(const MCInst *MI, raw_ostream &O); static const char *getRegisterName(unsigned RegNo); static const char *getInstructionName(unsigned Opcode); - void printOperand(const MCInst *MI, unsigned OpNo, - const char *Modifier = 0); - void printMemReference(const MCInst *MI, unsigned Op); - void printLeaMemReference(const MCInst *MI, unsigned Op); - void printSSECC(const MCInst *MI, unsigned Op); - void print_pcrel_imm(const MCInst *MI, unsigned OpNo); + void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); + void printMemReference(const MCInst *MI, unsigned Op, raw_ostream &O); + void printLeaMemReference(const MCInst *MI, unsigned Op, raw_ostream &O); + void printSSECC(const MCInst *MI, unsigned Op, raw_ostream &O); + void print_pcrel_imm(const MCInst *MI, unsigned OpNo, raw_ostream &O); - void printopaquemem(const MCInst *MI, unsigned OpNo) { + void printopaquemem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { O << "OPAQUE PTR "; - printMemReference(MI, OpNo); + printMemReference(MI, OpNo, O); } - void printi8mem(const MCInst *MI, unsigned OpNo) { + void printi8mem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { O << "BYTE PTR "; - printMemReference(MI, OpNo); + printMemReference(MI, OpNo, O); } - void printi16mem(const MCInst *MI, unsigned OpNo) { + void printi16mem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { O << "WORD PTR "; - printMemReference(MI, OpNo); + printMemReference(MI, OpNo, O); } - void printi32mem(const MCInst *MI, unsigned OpNo) { + void printi32mem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { O << "DWORD PTR "; - printMemReference(MI, OpNo); + printMemReference(MI, OpNo, O); } - void printi64mem(const MCInst *MI, unsigned OpNo) { + void printi64mem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { O << "QWORD PTR "; - printMemReference(MI, OpNo); + printMemReference(MI, OpNo, O); } - void printi128mem(const MCInst *MI, unsigned OpNo) { + void printi128mem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { O << "XMMWORD PTR "; - printMemReference(MI, OpNo); + printMemReference(MI, OpNo, O); } - void printf32mem(const MCInst *MI, unsigned OpNo) { + void printf32mem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { O << "DWORD PTR "; - printMemReference(MI, OpNo); + printMemReference(MI, OpNo, O); } - void printf64mem(const MCInst *MI, unsigned OpNo) { + void printf64mem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { O << "QWORD PTR "; - printMemReference(MI, OpNo); + printMemReference(MI, OpNo, O); } - void printf80mem(const MCInst *MI, unsigned OpNo) { + void printf80mem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { O << "XWORD PTR "; - printMemReference(MI, OpNo); + printMemReference(MI, OpNo, O); } - void printf128mem(const MCInst *MI, unsigned OpNo) { + void printf128mem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { O << "XMMWORD PTR "; - printMemReference(MI, OpNo); + printMemReference(MI, OpNo, O); } - void printlea32mem(const MCInst *MI, unsigned OpNo) { + void printlea32mem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { O << "DWORD PTR "; - printLeaMemReference(MI, OpNo); + printLeaMemReference(MI, OpNo, O); } - void printlea64mem(const MCInst *MI, unsigned OpNo) { + void printlea64mem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { O << "QWORD PTR "; - printLeaMemReference(MI, OpNo); + printLeaMemReference(MI, OpNo, O); } - void printlea64_32mem(const MCInst *MI, unsigned OpNo) { + void printlea64_32mem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { O << "QWORD PTR "; - printLeaMemReference(MI, OpNo); + printLeaMemReference(MI, OpNo, O); } }; diff --git a/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp b/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp index c851ca3fc805..a290eb0f2a5f 100644 --- a/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp +++ b/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp @@ -326,70 +326,76 @@ void X86MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { } } +void X86AsmPrinter::PrintDebugValueComment(const MachineInstr *MI, + raw_ostream &O) { + // FIXME: if this is implemented for another target before it goes + // away completely, the common part should be moved into AsmPrinter. + O << '\t' << MAI->getCommentString() << "DEBUG_VALUE: "; + unsigned NOps = MI->getNumOperands(); + // cast away const; DIetc do not take const operands for some reason. + DIVariable V((MDNode*)(MI->getOperand(NOps-1).getMetadata())); + O << V.getName(); + O << " <- "; + if (NOps==3) { + // Register or immediate value. Register 0 means undef. + assert(MI->getOperand(0).isReg() || + MI->getOperand(0).isImm() || + MI->getOperand(0).isFPImm()); + if (MI->getOperand(0).isReg() && MI->getOperand(0).getReg() == 0) { + // Suppress offset in this case, it is not meaningful. + O << "undef"; + OutStreamer.AddBlankLine(); + return; + } + + if (MI->getOperand(0).isFPImm()) { + // This is more naturally done in printOperand, but since the only use + // of such an operand is in this comment and that is temporary (and it's + // ugly), we prefer to keep this localized. + // The include of Type.h may be removable when this code is. + if (MI->getOperand(0).getFPImm()->getType()->isFloatTy() || + MI->getOperand(0).getFPImm()->getType()->isDoubleTy()) + MI->getOperand(0).print(O, &TM); + else { + // There is no good way to print long double. Convert a copy to + // double. Ah well, it's only a comment. + bool ignored; + APFloat APF = APFloat(MI->getOperand(0).getFPImm()->getValueAPF()); + APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, + &ignored); + O << "(long double) " << APF.convertToDouble(); + } + } else + printOperand(MI, 0, O); + } else { + if (MI->getOperand(0).isReg() && MI->getOperand(0).getReg() == 0) { + // Suppress offset in this case, it is not meaningful. + O << "undef"; + OutStreamer.AddBlankLine(); + return; + } + // Frame address. Currently handles register +- offset only. + assert(MI->getOperand(0).isReg() && MI->getOperand(3).isImm()); + O << '['; printOperand(MI, 0, O); O << '+'; printOperand(MI, 3, O); + O << ']'; + } + O << "+"; + printOperand(MI, NOps-2, O); +} void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) { X86MCInstLower MCInstLowering(OutContext, Mang, *this); switch (MI->getOpcode()) { - case TargetOpcode::DBG_VALUE: { - // FIXME: if this is implemented for another target before it goes - // away completely, the common part should be moved into AsmPrinter. - if (!VerboseAsm) - return; - O << '\t' << MAI->getCommentString() << "DEBUG_VALUE: "; - unsigned NOps = MI->getNumOperands(); - // cast away const; DIetc do not take const operands for some reason. - DIVariable V((MDNode*)(MI->getOperand(NOps-1).getMetadata())); - O << V.getName(); - O << " <- "; - if (NOps==3) { - // Register or immediate value. Register 0 means undef. - assert(MI->getOperand(0).getType()==MachineOperand::MO_Register || - MI->getOperand(0).getType()==MachineOperand::MO_Immediate || - MI->getOperand(0).getType()==MachineOperand::MO_FPImmediate); - if (MI->getOperand(0).getType()==MachineOperand::MO_Register && - MI->getOperand(0).getReg()==0) { - // Suppress offset in this case, it is not meaningful. - O << "undef"; - OutStreamer.AddBlankLine(); - return; - } else if (MI->getOperand(0).getType()==MachineOperand::MO_FPImmediate) { - // This is more naturally done in printOperand, but since the only use - // of such an operand is in this comment and that is temporary (and it's - // ugly), we prefer to keep this localized. - // The include of Type.h may be removable when this code is. - if (MI->getOperand(0).getFPImm()->getType()->isFloatTy() || - MI->getOperand(0).getFPImm()->getType()->isDoubleTy()) - MI->getOperand(0).print(O, &TM); - else { - // There is no good way to print long double. Convert a copy to - // double. Ah well, it's only a comment. - bool ignored; - APFloat APF = APFloat(MI->getOperand(0).getFPImm()->getValueAPF()); - APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, - &ignored); - O << "(long double) " << APF.convertToDouble(); - } - } else - printOperand(MI, 0); - } else { - if (MI->getOperand(0).getType()==MachineOperand::MO_Register && - MI->getOperand(0).getReg()==0) { - // Suppress offset in this case, it is not meaningful. - O << "undef"; - OutStreamer.AddBlankLine(); - return; - } - // Frame address. Currently handles register +- offset only. - assert(MI->getOperand(0).getType()==MachineOperand::MO_Register); - assert(MI->getOperand(3).getType()==MachineOperand::MO_Immediate); - O << '['; printOperand(MI, 0); O << '+'; printOperand(MI, 3); O << ']'; + case TargetOpcode::DBG_VALUE: + if (isVerbose() && OutStreamer.hasRawTextSupport()) { + std::string TmpStr; + raw_string_ostream OS(TmpStr); + PrintDebugValueComment(MI, OS); + OutStreamer.EmitRawText(StringRef(OS.str())); } - O << "+"; - printOperand(MI, NOps-2); - OutStreamer.AddBlankLine(); return; - } + case X86::MOVPC32r: { MCInst TmpInst; // This is a pseudo op for a two instruction sequence with a label, which diff --git a/lib/Target/X86/SSEDomainFix.cpp b/lib/Target/X86/SSEDomainFix.cpp index 395ab5705ae2..4b546768b4f1 100644 --- a/lib/Target/X86/SSEDomainFix.cpp +++ b/lib/Target/X86/SSEDomainFix.cpp @@ -23,49 +23,11 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/Support/Allocator.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; -namespace { - -/// Allocate objects from a pool, allow objects to be recycled, and provide a -/// way of deleting everything. -template<typename T, unsigned PageSize = 64> -class PoolAllocator { - std::vector<T*> Pages, Avail; -public: - ~PoolAllocator() { Clear(); } - - T* Alloc() { - if (Avail.empty()) { - T *p = new T[PageSize]; - Pages.push_back(p); - Avail.reserve(PageSize); - for (unsigned n = 0; n != PageSize; ++n) - Avail.push_back(p+n); - } - T *p = Avail.back(); - Avail.pop_back(); - return p; - } - - // Allow object to be reallocated. It won't be reconstructed. - void Recycle(T *p) { - p->clear(); - Avail.push_back(p); - } - - // Destroy all objects, make sure there are no external pointers to them. - void Clear() { - Avail.clear(); - while (!Pages.empty()) { - delete[] Pages.back(); - Pages.pop_back(); - } - } -}; - /// A DomainValue is a bit like LiveIntervals' ValNo, but it also keeps track /// of execution domains. /// @@ -81,14 +43,15 @@ public: /// domain, but if we were forced to pay the penalty of a domain crossing, we /// keep track of the fact the the register is now available in multiple /// domains. +namespace { struct DomainValue { // Basic reference counting. unsigned Refs; - // Available domains. For an open DomainValue, it is the still possible - // domains for collapsing. For a collapsed DomainValue it is the domains where - // the register is available for free. - unsigned Mask; + // Bitmask of available domains. For an open DomainValue, it is the still + // possible domains for collapsing. For a collapsed DomainValue it is the + // domains where the register is available for free. + unsigned AvailableDomains; // Position of the last defining instruction. unsigned Dist; @@ -96,38 +59,51 @@ struct DomainValue { // Twiddleable instructions using or defining these registers. SmallVector<MachineInstr*, 8> Instrs; - // Collapsed DomainValue have no instructions to twiddle - it simply keeps + // A collapsed DomainValue has no instructions to twiddle - it simply keeps // track of the domains where the registers are already available. - bool collapsed() const { return Instrs.empty(); } + bool isCollapsed() const { return Instrs.empty(); } - // Is any domain in mask available? - bool compat(unsigned mask) const { - return Mask & mask; + // Is domain available? + bool hasDomain(unsigned domain) const { + return AvailableDomains & (1u << domain); } // Mark domain as available. - void add(unsigned domain) { - Mask |= 1u << domain; + void addDomain(unsigned domain) { + AvailableDomains |= 1u << domain; + } + + // Restrict to a single domain available. + void setSingleDomain(unsigned domain) { + AvailableDomains = 1u << domain; + } + + // Return bitmask of domains that are available and in mask. + unsigned getCommonDomains(unsigned mask) const { + return AvailableDomains & mask; } - // First domain available in mask. - unsigned firstDomain() const { - return CountTrailingZeros_32(Mask); + // First domain available. + unsigned getFirstDomain() const { + return CountTrailingZeros_32(AvailableDomains); } DomainValue() { clear(); } void clear() { - Refs = Mask = Dist = 0; + Refs = AvailableDomains = Dist = 0; Instrs.clear(); } }; +} static const unsigned NumRegs = 16; +namespace { class SSEDomainFixPass : public MachineFunctionPass { static char ID; - PoolAllocator<DomainValue> Pool; + SpecificBumpPtrAllocator<DomainValue> Allocator; + SmallVector<DomainValue*,16> Avail; MachineFunction *MF; const X86InstrInfo *TII; @@ -156,6 +132,10 @@ private: // Register mapping. int RegIndex(unsigned Reg); + // DomainValue allocation. + DomainValue *Alloc(int domain = -1); + void Recycle(DomainValue*); + // LiveRegs manipulations. void SetLiveReg(int rx, DomainValue *DV); void Kill(int rx); @@ -182,17 +162,35 @@ int SSEDomainFixPass::RegIndex(unsigned reg) { return reg < NumRegs ? reg : -1; } +DomainValue *SSEDomainFixPass::Alloc(int domain) { + DomainValue *dv = Avail.empty() ? + new(Allocator.Allocate()) DomainValue : + Avail.pop_back_val(); + dv->Dist = Distance; + if (domain >= 0) + dv->addDomain(domain); + return dv; +} + +void SSEDomainFixPass::Recycle(DomainValue *dv) { + assert(dv && "Cannot recycle NULL"); + dv->clear(); + Avail.push_back(dv); +} + /// Set LiveRegs[rx] = dv, updating reference counts. void SSEDomainFixPass::SetLiveReg(int rx, DomainValue *dv) { assert(unsigned(rx) < NumRegs && "Invalid index"); - if (!LiveRegs) - LiveRegs = (DomainValue**)calloc(sizeof(DomainValue*), NumRegs); + if (!LiveRegs) { + LiveRegs = new DomainValue*[NumRegs]; + std::fill(LiveRegs, LiveRegs+NumRegs, (DomainValue*)0); + } if (LiveRegs[rx] == dv) return; if (LiveRegs[rx]) { assert(LiveRegs[rx]->Refs && "Bad refcount"); - if (--LiveRegs[rx]->Refs == 0) Pool.Recycle(LiveRegs[rx]); + if (--LiveRegs[rx]->Refs == 0) Recycle(LiveRegs[rx]); } LiveRegs[rx] = dv; if (dv) ++dv->Refs; @@ -205,8 +203,8 @@ void SSEDomainFixPass::Kill(int rx) { // Before killing the last reference to an open DomainValue, collapse it to // the first available domain. - if (LiveRegs[rx]->Refs == 1 && !LiveRegs[rx]->collapsed()) - Collapse(LiveRegs[rx], LiveRegs[rx]->firstDomain()); + if (LiveRegs[rx]->Refs == 1 && !LiveRegs[rx]->isCollapsed()) + Collapse(LiveRegs[rx], LiveRegs[rx]->getFirstDomain()); else SetLiveReg(rx, 0); } @@ -216,54 +214,45 @@ void SSEDomainFixPass::Force(int rx, unsigned domain) { assert(unsigned(rx) < NumRegs && "Invalid index"); DomainValue *dv; if (LiveRegs && (dv = LiveRegs[rx])) { - if (dv->collapsed()) - dv->add(domain); + if (dv->isCollapsed()) + dv->addDomain(domain); else Collapse(dv, domain); } else { // Set up basic collapsed DomainValue. - dv = Pool.Alloc(); - dv->Dist = Distance; - dv->add(domain); - SetLiveReg(rx, dv); + SetLiveReg(rx, Alloc(domain)); } } /// Collapse open DomainValue into given domain. If there are multiple /// registers using dv, they each get a unique collapsed DomainValue. void SSEDomainFixPass::Collapse(DomainValue *dv, unsigned domain) { - assert(dv->compat(1u << domain) && "Cannot collapse"); + assert(dv->hasDomain(domain) && "Cannot collapse"); // Collapse all the instructions. - while (!dv->Instrs.empty()) { - MachineInstr *mi = dv->Instrs.back(); - TII->SetSSEDomain(mi, domain); - dv->Instrs.pop_back(); - } - dv->Mask = 1u << domain; + while (!dv->Instrs.empty()) + TII->SetSSEDomain(dv->Instrs.pop_back_val(), domain); + dv->setSingleDomain(domain); // If there are multiple users, give them new, unique DomainValues. - if (LiveRegs && dv->Refs > 1) { + if (LiveRegs && dv->Refs > 1) for (unsigned rx = 0; rx != NumRegs; ++rx) - if (LiveRegs[rx] == dv) { - DomainValue *dv2 = Pool.Alloc(); - dv2->Dist = Distance; - dv2->add(domain); - SetLiveReg(rx, dv2); - } - } + if (LiveRegs[rx] == dv) + SetLiveReg(rx, Alloc(domain)); } /// Merge - All instructions and registers in B are moved to A, and B is /// released. bool SSEDomainFixPass::Merge(DomainValue *A, DomainValue *B) { - assert(!A->collapsed() && "Cannot merge into collapsed"); - assert(!B->collapsed() && "Cannot merge from collapsed"); + assert(!A->isCollapsed() && "Cannot merge into collapsed"); + assert(!B->isCollapsed() && "Cannot merge from collapsed"); if (A == B) return true; - if (!A->compat(B->Mask)) + // Restrict to the domains that A and B have in common. + unsigned common = A->getCommonDomains(B->AvailableDomains); + if (!common) return false; - A->Mask &= B->Mask; + A->AvailableDomains = common; A->Dist = std::max(A->Dist, B->Dist); A->Instrs.append(B->Instrs.begin(), B->Instrs.end()); for (unsigned rx = 0; rx != NumRegs; ++rx) @@ -290,18 +279,18 @@ void SSEDomainFixPass::enterBasicBlock() { } // We have a live DomainValue from more than one predecessor. - if (LiveRegs[rx]->collapsed()) { + if (LiveRegs[rx]->isCollapsed()) { // We are already collapsed, but predecessor is not. Force him. - if (!pdv->collapsed()) - Collapse(pdv, LiveRegs[rx]->firstDomain()); + if (!pdv->isCollapsed()) + Collapse(pdv, LiveRegs[rx]->getFirstDomain()); continue; } - + // Currently open, merge in predecessor. - if (!pdv->collapsed()) + if (!pdv->isCollapsed()) Merge(LiveRegs[rx], pdv); else - Collapse(LiveRegs[rx], pdv->firstDomain()); + Collapse(LiveRegs[rx], pdv->getFirstDomain()); } } } @@ -332,8 +321,11 @@ void SSEDomainFixPass::visitHardInstr(MachineInstr *mi, unsigned domain) { // A soft instruction can be changed to work in other domains given by mask. void SSEDomainFixPass::visitSoftInstr(MachineInstr *mi, unsigned mask) { + // Bitmask of available domains for this instruction after taking collapsed + // operands into account. + unsigned available = mask; + // Scan the explicit use operands for incoming domains. - unsigned collmask = mask; SmallVector<int, 4> used; if (LiveRegs) for (unsigned i = mi->getDesc().getNumDefs(), @@ -343,33 +335,40 @@ void SSEDomainFixPass::visitSoftInstr(MachineInstr *mi, unsigned mask) { int rx = RegIndex(mo.getReg()); if (rx < 0) continue; if (DomainValue *dv = LiveRegs[rx]) { + // Bitmask of domains that dv and available have in common. + unsigned common = dv->getCommonDomains(available); // Is it possible to use this collapsed register for free? - if (dv->collapsed()) { - if (unsigned m = collmask & dv->Mask) - collmask = m; - } else if (dv->compat(collmask)) + if (dv->isCollapsed()) { + // Restrict available domains to the ones in common with the operand. + // If there are no common domains, we must pay the cross-domain + // penalty for this operand. + if (common) available = common; + } else if (common) + // Open DomainValue is compatible, save it for merging. used.push_back(rx); else + // Open DomainValue is not compatible with instruction. It is useless + // now. Kill(rx); } } // If the collapsed operands force a single domain, propagate the collapse. - if (isPowerOf2_32(collmask)) { - unsigned domain = CountTrailingZeros_32(collmask); + if (isPowerOf2_32(available)) { + unsigned domain = CountTrailingZeros_32(available); TII->SetSSEDomain(mi, domain); visitHardInstr(mi, domain); return; } - // Kill off any remaining uses that don't match collmask, and build a list of - // incoming DomainValue that we want to merge. + // Kill off any remaining uses that don't match available, and build a list of + // incoming DomainValues that we want to merge. SmallVector<DomainValue*,4> doms; for (SmallVector<int, 4>::iterator i=used.begin(), e=used.end(); i!=e; ++i) { int rx = *i; DomainValue *dv = LiveRegs[rx]; // This useless DomainValue could have been missed above. - if (!dv->compat(collmask)) { + if (!dv->getCommonDomains(available)) { Kill(*i); continue; } @@ -388,28 +387,29 @@ void SSEDomainFixPass::visitSoftInstr(MachineInstr *mi, unsigned mask) { doms.push_back(dv); } - // doms are now sorted in order of appearance. Try to merge them all, giving - // priority to the latest ones. + // doms are now sorted in order of appearance. Try to merge them all, giving + // priority to the latest ones. DomainValue *dv = 0; while (!doms.empty()) { if (!dv) { dv = doms.pop_back_val(); continue; } - - DomainValue *ThisDV = doms.pop_back_val(); - if (Merge(dv, ThisDV)) continue; - + + DomainValue *latest = doms.pop_back_val(); + if (Merge(dv, latest)) continue; + + // If latest didn't merge, it is useless now. Kill all registers using it. for (SmallVector<int,4>::iterator i=used.begin(), e=used.end(); i != e; ++i) - if (LiveRegs[*i] == ThisDV) + if (LiveRegs[*i] == latest) Kill(*i); } // dv is the DomainValue we are going to use for this instruction. if (!dv) - dv = Pool.Alloc(); + dv = Alloc(); dv->Dist = Distance; - dv->Mask = collmask; + dv->AvailableDomains = available; dv->Instrs.push_back(mi); // Finally set all defs and non-collapsed uses to dv. @@ -487,9 +487,10 @@ bool SSEDomainFixPass::runOnMachineFunction(MachineFunction &mf) { // DomainValues? for (LiveOutMap::const_iterator i = LiveOuts.begin(), e = LiveOuts.end(); i != e; ++i) - free(i->second); + delete[] i->second; LiveOuts.clear(); - Pool.Clear(); + Avail.clear(); + Allocator.DestroyAll(); return false; } diff --git a/lib/Target/X86/X86.td b/lib/Target/X86/X86.td index 89cc84ffb3c6..ec86fc248e3d 100644 --- a/lib/Target/X86/X86.td +++ b/lib/Target/X86/X86.td @@ -164,33 +164,7 @@ include "X86RegisterInfo.td" include "X86InstrInfo.td" -def X86InstrInfo : InstrInfo { - - // Define how we want to layout our TargetSpecific information field... This - // should be kept up-to-date with the fields in the X86InstrInfo.h file. - let TSFlagsFields = ["FormBits", - "hasOpSizePrefix", - "hasAdSizePrefix", - "Prefix", - "hasREX_WPrefix", - "ImmT.Value", - "FPForm.Value", - "hasLockPrefix", - "SegOvrBits", - "ExeDomain.Value", - "Opcode"]; - let TSFlagsShifts = [0, - 6, - 7, - 8, - 12, - 13, - 16, - 19, - 20, - 22, - 24]; -} +def X86InstrInfo : InstrInfo; //===----------------------------------------------------------------------===// // Calling Conventions diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp index c69eeb3e9006..7849b51accc4 100644 --- a/lib/Target/X86/X86FastISel.cpp +++ b/lib/Target/X86/X86FastISel.cpp @@ -54,8 +54,6 @@ class X86FastISel : public FastISel { public: explicit X86FastISel(MachineFunction &mf, - MachineModuleInfo *mmi, - DwarfWriter *dw, DenseMap<const Value *, unsigned> &vm, DenseMap<const BasicBlock *, MachineBasicBlock *> &bm, DenseMap<const AllocaInst *, int> &am @@ -63,7 +61,7 @@ public: , SmallSet<Instruction*, 8> &cil #endif ) - : FastISel(mf, mmi, dw, vm, bm, am + : FastISel(mf, vm, bm, am #ifndef NDEBUG , cil #endif @@ -1753,8 +1751,6 @@ unsigned X86FastISel::TargetMaterializeAlloca(AllocaInst *C) { namespace llvm { llvm::FastISel *X86::createFastISel(MachineFunction &mf, - MachineModuleInfo *mmi, - DwarfWriter *dw, DenseMap<const Value *, unsigned> &vm, DenseMap<const BasicBlock *, MachineBasicBlock *> &bm, DenseMap<const AllocaInst *, int> &am @@ -1762,7 +1758,7 @@ namespace llvm { , SmallSet<Instruction*, 8> &cil #endif ) { - return new X86FastISel(mf, mmi, dw, vm, bm, am + return new X86FastISel(mf, vm, bm, am #ifndef NDEBUG , cil #endif diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 527e19b60882..64702f1d5c9f 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -1434,7 +1434,8 @@ CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain, DebugLoc dl) { SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), MVT::i32); return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getByValAlign(), - /*AlwaysInline=*/true, NULL, 0, NULL, 0); + /*isVolatile*/false, /*AlwaysInline=*/true, + NULL, 0, NULL, 0); } /// IsTailCallConvention - Return true if the calling convention is one that @@ -2397,8 +2398,7 @@ X86TargetLowering::IsEligibleForTailCallOptimization(SDValue Callee, } FastISel * -X86TargetLowering::createFastISel(MachineFunction &mf, MachineModuleInfo *mmo, - DwarfWriter *dw, +X86TargetLowering::createFastISel(MachineFunction &mf, DenseMap<const Value *, unsigned> &vm, DenseMap<const BasicBlock*, MachineBasicBlock*> &bm, DenseMap<const AllocaInst *, int> &am @@ -2406,7 +2406,7 @@ X86TargetLowering::createFastISel(MachineFunction &mf, MachineModuleInfo *mmo, , SmallSet<Instruction*, 8> &cil #endif ) { - return X86::createFastISel(mf, mmo, dw, vm, bm, am + return X86::createFastISel(mf, vm, bm, am #ifndef NDEBUG , cil #endif @@ -6548,6 +6548,7 @@ X86TargetLowering::EmitTargetCodeForMemset(SelectionDAG &DAG, DebugLoc dl, SDValue Chain, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, + bool isVolatile, const Value *DstSV, uint64_t DstSVOff) { ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size); @@ -6676,7 +6677,7 @@ X86TargetLowering::EmitTargetCodeForMemset(SelectionDAG &DAG, DebugLoc dl, DAG.getConstant(Offset, AddrVT)), Src, DAG.getConstant(BytesLeft, SizeVT), - Align, DstSV, DstSVOff + Offset); + Align, isVolatile, DstSV, DstSVOff + Offset); } // TODO: Use a Tokenfactor, as in memcpy, instead of a single chain. @@ -6687,7 +6688,7 @@ SDValue X86TargetLowering::EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, SDValue Chain, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, - bool AlwaysInline, + bool isVolatile, bool AlwaysInline, const Value *DstSV, uint64_t DstSVOff, const Value *SrcSV, uint64_t SrcSVOff) { // This requires the copy size to be a constant, preferrably @@ -6746,7 +6747,7 @@ X86TargetLowering::EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, DAG.getNode(ISD::ADD, dl, SrcVT, Src, DAG.getConstant(Offset, SrcVT)), DAG.getConstant(BytesLeft, SizeVT), - Align, AlwaysInline, + Align, isVolatile, AlwaysInline, DstSV, DstSVOff + Offset, SrcSV, SrcSVOff + Offset)); } @@ -6829,8 +6830,8 @@ SDValue X86TargetLowering::LowerVACOPY(SDValue Op, SelectionDAG &DAG) { DebugLoc dl = Op.getDebugLoc(); return DAG.getMemcpy(Chain, dl, DstPtr, SrcPtr, - DAG.getIntPtrConstant(24), 8, false, - DstSV, 0, SrcSV, 0); + DAG.getIntPtrConstant(24), 8, /*isVolatile*/false, + false, DstSV, 0, SrcSV, 0); } SDValue diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index 2c2a5fbb8032..1026480ef0a6 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -575,7 +575,6 @@ namespace llvm { /// or null if the target does not support "fast" ISel. virtual FastISel * createFastISel(MachineFunction &mf, - MachineModuleInfo *mmi, DwarfWriter *dw, DenseMap<const Value *, unsigned> &, DenseMap<const BasicBlock *, MachineBasicBlock *> &, DenseMap<const AllocaInst *, int> & @@ -741,12 +740,13 @@ namespace llvm { SDValue Chain, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, + bool isVolatile, const Value *DstSV, uint64_t DstSVOff); SDValue EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, SDValue Chain, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, - bool AlwaysInline, + bool isVolatile, bool AlwaysInline, const Value *DstSV, uint64_t DstSVOff, const Value *SrcSV, uint64_t SrcSVOff); @@ -756,7 +756,7 @@ namespace llvm { /// block, the number of args, and whether or not the second arg is /// in memory or not. MachineBasicBlock *EmitPCMP(MachineInstr *BInstr, MachineBasicBlock *BB, - unsigned argNum, bool inMem) const; + unsigned argNum, bool inMem) const; /// Utility function to emit atomic bitwise operations (and, or, xor). /// It takes the bitwise instruction to expand, the associated machine basic @@ -815,7 +815,6 @@ namespace llvm { namespace X86 { FastISel *createFastISel(MachineFunction &mf, - MachineModuleInfo *mmi, DwarfWriter *dw, DenseMap<const Value *, unsigned> &, DenseMap<const BasicBlock *, MachineBasicBlock *> &, DenseMap<const AllocaInst *, int> & diff --git a/lib/Target/X86/X86InstrFormats.td b/lib/Target/X86/X86InstrFormats.td index cbe4c8256299..c4522f3fd9e8 100644 --- a/lib/Target/X86/X86InstrFormats.td +++ b/lib/Target/X86/X86InstrFormats.td @@ -128,6 +128,19 @@ class X86Inst<bits<8> opcod, Format f, ImmType i, dag outs, dag ins, bit hasLockPrefix = 0; // Does this inst have a 0xF0 prefix? bits<2> SegOvrBits = 0; // Segment override prefix. Domain ExeDomain = d; + + // TSFlags layout should be kept in sync with X86InstrInfo.h. + let TSFlags{5-0} = FormBits; + let TSFlags{6} = hasOpSizePrefix; + let TSFlags{7} = hasAdSizePrefix; + let TSFlags{11-8} = Prefix; + let TSFlags{12} = hasREX_WPrefix; + let TSFlags{15-13} = ImmT.Value; + let TSFlags{18-16} = FPForm.Value; + let TSFlags{19} = hasLockPrefix; + let TSFlags{21-20} = SegOvrBits; + let TSFlags{23-22} = ExeDomain.Value; + let TSFlags{31-24} = Opcode; } class I<bits<8> o, Format f, dag outs, dag ins, string asm, @@ -314,8 +327,7 @@ class SS42AI<bits<8> o, Format F, dag outs, dag ins, string asm, // AES Instruction Templates: // // AES8I -// FIXME: Verify these, they appear to use the same encoding as the SSE4.2 T8 -// and TA encodings. +// These use the same encoding as the SSE4.2 T8 and TA encodings. class AES8I<bits<8> o, Format F, dag outs, dag ins, string asm, list<dag>pattern> : I<o, F, outs, ins, asm, pattern, SSEPackedInt>, T8, diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp index fcb9947423de..ccb7b055b079 100644 --- a/lib/Target/X86/X86InstrInfo.cpp +++ b/lib/Target/X86/X86InstrInfo.cpp @@ -2961,10 +2961,6 @@ X86InstrInfo::areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2, Load1->getOperand(2) == Load2->getOperand(2)) { if (cast<ConstantSDNode>(Load1->getOperand(1))->getZExtValue() != 1) return false; - SDValue Op2 = Load1->getOperand(2); - if (!isa<RegisterSDNode>(Op2) || - cast<RegisterSDNode>(Op2)->getReg() != 0) - return 0; // Now let's examine the displacements. if (isa<ConstantSDNode>(Load1->getOperand(3)) && diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index 65b7ec023d81..940b439d22a9 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -2707,7 +2707,7 @@ let isCodeGenOnly = 1 in { "add{b}\t{$src2, $dst|$dst, $src2}", []>; def ADD16rr_alt: I<0x03, MRMSrcReg,(outs GR16:$dst),(ins GR16:$src1, GR16:$src2), "add{w}\t{$src2, $dst|$dst, $src2}", []>, OpSize; - def ADD32rr_alt: I<0x03, MRMSrcReg,(outs GR16:$dst),(ins GR16:$src1, GR16:$src2), + def ADD32rr_alt: I<0x03, MRMSrcReg,(outs GR32:$dst),(ins GR32:$src1, GR32:$src2), "add{l}\t{$src2, $dst|$dst, $src2}", []>; } diff --git a/lib/Target/X86/X86MCAsmInfo.cpp b/lib/Target/X86/X86MCAsmInfo.cpp index 1afabc9d9c15..d257ee38c5c7 100644 --- a/lib/Target/X86/X86MCAsmInfo.cpp +++ b/lib/Target/X86/X86MCAsmInfo.cpp @@ -84,7 +84,6 @@ X86ELFMCAsmInfo::X86ELFMCAsmInfo(const Triple &T) { HasLEB128 = true; // Target asm supports leb128 directives (little-endian) // Debug Information - AbsoluteDebugSectionOffsets = true; SupportsDebugInformation = true; // Exceptions handling diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index 3238ccebb99f..32f28a520074 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -297,9 +297,7 @@ X86RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { bool ghcCall = false; if (MF) { - const MachineFrameInfo *MFI = MF->getFrameInfo(); - const MachineModuleInfo *MMI = MFI->getMachineModuleInfo(); - callsEHReturn = (MMI ? MMI->callsEHReturn() : false); + callsEHReturn = MF->getMMI().callsEHReturn(); const Function *F = MF->getFunction(); ghcCall = (F ? F->getCallingConv() == CallingConv::GHC : false); } @@ -348,12 +346,8 @@ X86RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { const TargetRegisterClass* const* X86RegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const { bool callsEHReturn = false; - - if (MF) { - const MachineFrameInfo *MFI = MF->getFrameInfo(); - const MachineModuleInfo *MMI = MFI->getMachineModuleInfo(); - callsEHReturn = (MMI ? MMI->callsEHReturn() : false); - } + if (MF) + callsEHReturn = MF->getMMI().callsEHReturn(); static const TargetRegisterClass * const CalleeSavedRegClasses32Bit[] = { &X86::GR32RegClass, &X86::GR32RegClass, @@ -443,14 +437,14 @@ BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const { /// or if frame pointer elimination is disabled. bool X86RegisterInfo::hasFP(const MachineFunction &MF) const { const MachineFrameInfo *MFI = MF.getFrameInfo(); - const MachineModuleInfo *MMI = MFI->getMachineModuleInfo(); + const MachineModuleInfo &MMI = MF.getMMI(); return (NoFramePointerElim || needsStackRealignment(MF) || MFI->hasVarSizedObjects() || MFI->isFrameAddressTaken() || MF.getInfo<X86MachineFunctionInfo>()->getForceFramePointer() || - (MMI && MMI->callsUnwindInit())); + MMI.callsUnwindInit()); } bool X86RegisterInfo::canRealignStack(const MachineFunction &MF) const { @@ -800,14 +794,13 @@ void X86RegisterInfo::emitCalleeSavedFrameMoves(MachineFunction &MF, MCSymbol *Label, unsigned FramePtr) const { MachineFrameInfo *MFI = MF.getFrameInfo(); - MachineModuleInfo *MMI = MFI->getMachineModuleInfo(); - if (!MMI) return; + MachineModuleInfo &MMI = MF.getMMI(); // Add callee saved registers to move list. const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); if (CSI.empty()) return; - std::vector<MachineMove> &Moves = MMI->getFrameMoves(); + std::vector<MachineMove> &Moves = MMI.getFrameMoves(); const TargetData *TD = MF.getTarget().getTargetData(); bool HasFP = hasFP(MF); @@ -874,9 +867,9 @@ void X86RegisterInfo::emitPrologue(MachineFunction &MF) const { MachineFrameInfo *MFI = MF.getFrameInfo(); const Function *Fn = MF.getFunction(); const X86Subtarget *Subtarget = &MF.getTarget().getSubtarget<X86Subtarget>(); - MachineModuleInfo *MMI = MFI->getMachineModuleInfo(); + MachineModuleInfo &MMI = MF.getMMI(); X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>(); - bool needsFrameMoves = (MMI && MMI->hasDebugInfo()) || + bool needsFrameMoves = MMI.hasDebugInfo() || !Fn->doesNotThrow() || UnwindTablesMandatory; uint64_t MaxAlign = MFI->getMaxAlignment(); // Desired stack alignment. uint64_t StackSize = MFI->getStackSize(); // Number of bytes to allocate. @@ -935,7 +928,7 @@ void X86RegisterInfo::emitPrologue(MachineFunction &MF) const { // REG < 64 => DW_CFA_offset + Reg // ELSE => DW_CFA_offset_extended - std::vector<MachineMove> &Moves = MMI->getFrameMoves(); + std::vector<MachineMove> &Moves = MMI.getFrameMoves(); const TargetData *TD = MF.getTarget().getTargetData(); uint64_t NumBytes = 0; int stackGrowth = -TD->getPointerSize(); @@ -959,7 +952,7 @@ void X86RegisterInfo::emitPrologue(MachineFunction &MF) const { if (needsFrameMoves) { // Mark the place where EBP/RBP was saved. - MCSymbol *FrameLabel = MMI->getContext().CreateTempSymbol(); + MCSymbol *FrameLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, DL, TII.get(X86::DBG_LABEL)).addSym(FrameLabel); // Define the current CFA rule to use the provided offset. @@ -987,7 +980,7 @@ void X86RegisterInfo::emitPrologue(MachineFunction &MF) const { if (needsFrameMoves) { // Mark effective beginning of when frame pointer becomes valid. - MCSymbol *FrameLabel = MMI->getContext().CreateTempSymbol(); + MCSymbol *FrameLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, DL, TII.get(X86::DBG_LABEL)).addSym(FrameLabel); // Define the current CFA to use the EBP/RBP register. @@ -1027,7 +1020,7 @@ void X86RegisterInfo::emitPrologue(MachineFunction &MF) const { if (!HasFP && needsFrameMoves) { // Mark callee-saved push instruction. - MCSymbol *Label = MMI->getContext().CreateTempSymbol(); + MCSymbol *Label = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, DL, TII.get(X86::DBG_LABEL)).addSym(Label); // Define the current CFA rule to use the provided offset. @@ -1099,7 +1092,7 @@ void X86RegisterInfo::emitPrologue(MachineFunction &MF) const { if ((NumBytes || PushedRegs) && needsFrameMoves) { // Mark end of stack pointer adjustment. - MCSymbol *Label = MMI->getContext().CreateTempSymbol(); + MCSymbol *Label = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, DL, TII.get(X86::DBG_LABEL)).addSym(Label); if (!HasFP && NumBytes) { diff --git a/lib/Target/XCore/AsmPrinter/XCoreAsmPrinter.cpp b/lib/Target/XCore/AsmPrinter/XCoreAsmPrinter.cpp index c88233877903..5801b40b7e90 100644 --- a/lib/Target/XCore/AsmPrinter/XCoreAsmPrinter.cpp +++ b/lib/Target/XCore/AsmPrinter/XCoreAsmPrinter.cpp @@ -22,7 +22,6 @@ #include "llvm/DerivedTypes.h" #include "llvm/Module.h" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/DwarfWriter.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineConstantPool.h" @@ -34,11 +33,11 @@ #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetRegistry.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cctype> using namespace llvm; @@ -53,68 +52,53 @@ namespace { class XCoreAsmPrinter : public AsmPrinter { const XCoreSubtarget &Subtarget; public: - explicit XCoreAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, - MCStreamer &Streamer) - : AsmPrinter(O, TM, Streamer), - Subtarget(TM.getSubtarget<XCoreSubtarget>()) {} + explicit XCoreAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : AsmPrinter(TM, Streamer), Subtarget(TM.getSubtarget<XCoreSubtarget>()){} virtual const char *getPassName() const { return "XCore Assembly Printer"; } - void printMemOperand(const MachineInstr *MI, int opNum); - void printInlineJT(const MachineInstr *MI, int opNum, + void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O); + void printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O, const std::string &directive = ".jmptable"); - void printInlineJT32(const MachineInstr *MI, int opNum) { - printInlineJT(MI, opNum, ".jmptable32"); + void printInlineJT32(const MachineInstr *MI, int opNum, raw_ostream &O) { + printInlineJT(MI, opNum, O, ".jmptable32"); } - void printOperand(const MachineInstr *MI, int opNum); + void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode); + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); - void emitGlobalDirective(const MCSymbol *Sym); - - void emitArrayBound(const MCSymbol *Sym, const GlobalVariable *GV); + void emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV); virtual void EmitGlobalVariable(const GlobalVariable *GV); - void emitFunctionStart(MachineFunction &MF); - - void printInstruction(const MachineInstr *MI); // autogenerated. + void printInstruction(const MachineInstr *MI, raw_ostream &O); // autogen'd. static const char *getRegisterName(unsigned RegNo); - bool runOnMachineFunction(MachineFunction &MF); + void EmitFunctionEntryLabel(); void EmitInstruction(const MachineInstr *MI); void EmitFunctionBodyEnd(); - - void getAnalysisUsage(AnalysisUsage &AU) const { - AsmPrinter::getAnalysisUsage(AU); - AU.setPreservesAll(); - AU.addRequired<MachineModuleInfo>(); - AU.addRequired<DwarfWriter>(); - } }; } // end of anonymous namespace #include "XCoreGenAsmWriter.inc" -void XCoreAsmPrinter::emitGlobalDirective(const MCSymbol *Sym) { - O << MAI->getGlobalDirective() << *Sym << "\n"; -} - -void XCoreAsmPrinter::emitArrayBound(const MCSymbol *Sym, - const GlobalVariable *GV) { +void XCoreAsmPrinter::emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV) { assert(((GV->hasExternalLinkage() || GV->hasWeakLinkage()) || GV->hasLinkOnceLinkage()) && "Unexpected linkage"); if (const ArrayType *ATy = dyn_cast<ArrayType>( cast<PointerType>(GV->getType())->getElementType())) { - O << MAI->getGlobalDirective() << *Sym; - O << ".globound" << "\n"; - O << "\t.set\t" << *Sym; - O << ".globound" << "," << ATy->getNumElements() << "\n"; + OutStreamer.EmitSymbolAttribute(Sym, MCSA_Global); + // FIXME: MCStreamerize. + OutStreamer.EmitRawText(StringRef(".globound")); + OutStreamer.EmitRawText("\t.set\t" + Twine(Sym->getName())); + OutStreamer.EmitRawText(".globound," + Twine(ATy->getNumElements())); if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) { // TODO Use COMDAT groups for LinkOnceLinkage - O << MAI->getWeakDefDirective() << *Sym << ".globound" << "\n"; + OutStreamer.EmitRawText(MAI->getWeakDefDirective() +Twine(Sym->getName())+ + ".globound"); } } } @@ -134,7 +118,8 @@ void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { unsigned Align = (unsigned)TD->getPreferredTypeAlignmentShift(C->getType()); // Mark the start of the global - O << "\t.cc_top " << *GVSym << ".data," << *GVSym << "\n"; + OutStreamer.EmitRawText("\t.cc_top " + Twine(GVSym->getName()) + ".data," + + GVSym->getName()); switch (GV->getLinkage()) { case GlobalValue::AppendingLinkage: @@ -145,10 +130,11 @@ void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { case GlobalValue::WeakODRLinkage: case GlobalValue::ExternalLinkage: emitArrayBound(GVSym, GV); - emitGlobalDirective(GVSym); + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); + // TODO Use COMDAT groups for LinkOnceLinkage if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) - O << MAI->getWeakDefDirective() << *GVSym << "\n"; + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak); // FALL THROUGH case GlobalValue::InternalLinkage: case GlobalValue::PrivateLinkage: @@ -169,10 +155,11 @@ void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { Size *= MaxThreads; } if (MAI->hasDotTypeDotSizeDirective()) { - O << "\t.type " << *GVSym << ",@object\n"; - O << "\t.size " << *GVSym << "," << Size << "\n"; + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject); + OutStreamer.EmitRawText("\t.size " + Twine(GVSym->getName()) + "," + + Twine(Size)); } - O << *GVSym << ":\n"; + OutStreamer.EmitLabel(GVSym); EmitGlobalConstant(C); if (GV->isThreadLocal()) { @@ -185,87 +172,38 @@ void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { OutStreamer.EmitZeros(4 - Size, 0); // Mark the end of the global - O << "\t.cc_bottom " << *GVSym << ".data\n"; + OutStreamer.EmitRawText("\t.cc_bottom " + Twine(GVSym->getName()) + ".data"); } -/// Emit the directives on the start of functions -void XCoreAsmPrinter::emitFunctionStart(MachineFunction &MF) { - // Print out the label for the function. - const Function *F = MF.getFunction(); - - OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM)); - - // Mark the start of the function - O << "\t.cc_top " << *CurrentFnSym << ".function," << *CurrentFnSym << "\n"; - - switch (F->getLinkage()) { - default: llvm_unreachable("Unknown linkage type!"); - case Function::InternalLinkage: // Symbols default to internal. - case Function::PrivateLinkage: - case Function::LinkerPrivateLinkage: - break; - case Function::ExternalLinkage: - emitGlobalDirective(CurrentFnSym); - break; - case Function::LinkOnceAnyLinkage: - case Function::LinkOnceODRLinkage: - case Function::WeakAnyLinkage: - case Function::WeakODRLinkage: - // TODO Use COMDAT groups for LinkOnceLinkage - O << MAI->getGlobalDirective() << *CurrentFnSym << "\n"; - O << MAI->getWeakDefDirective() << *CurrentFnSym << "\n"; - break; - } - // (1 << 1) byte aligned - EmitAlignment(MF.getAlignment(), F, 1); - if (MAI->hasDotTypeDotSizeDirective()) - O << "\t.type " << *CurrentFnSym << ",@function\n"; - - O << *CurrentFnSym << ":\n"; -} - - /// EmitFunctionBodyEnd - Targets can override this to emit stuff after /// the last basic block in the function. void XCoreAsmPrinter::EmitFunctionBodyEnd() { // Emit function end directives - O << "\t.cc_bottom " << *CurrentFnSym << ".function\n"; + OutStreamer.EmitRawText("\t.cc_bottom " + Twine(CurrentFnSym->getName()) + + ".function"); } -/// runOnMachineFunction - This uses the printMachineInstruction() -/// method to print assembly for each instruction. -/// -bool XCoreAsmPrinter::runOnMachineFunction(MachineFunction &MF) { - SetupMachineFunction(MF); - - // Print out constants referenced by the function - EmitConstantPool(); - - // Emit the function start directives - emitFunctionStart(MF); - - // Emit pre-function debug information. - DW->BeginFunction(&MF); - - EmitFunctionBody(); - return false; +void XCoreAsmPrinter::EmitFunctionEntryLabel() { + // Mark the start of the function + OutStreamer.EmitRawText("\t.cc_top " + Twine(CurrentFnSym->getName()) + + ".function," + CurrentFnSym->getName()); + OutStreamer.EmitLabel(CurrentFnSym); } -void XCoreAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum) -{ - printOperand(MI, opNum); +void XCoreAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum, + raw_ostream &O) { + printOperand(MI, opNum, O); - if (MI->getOperand(opNum+1).isImm() - && MI->getOperand(opNum+1).getImm() == 0) + if (MI->getOperand(opNum+1).isImm() && MI->getOperand(opNum+1).getImm() == 0) return; O << "+"; - printOperand(MI, opNum+1); + printOperand(MI, opNum+1, O); } void XCoreAsmPrinter:: -printInlineJT(const MachineInstr *MI, int opNum, const std::string &directive) -{ +printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O, + const std::string &directive) { unsigned JTI = MI->getOperand(opNum).getIndex(); const MachineFunction *MF = MI->getParent()->getParent(); const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); @@ -280,7 +218,8 @@ printInlineJT(const MachineInstr *MI, int opNum, const std::string &directive) } } -void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum) { +void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum, + raw_ostream &O) { const MachineOperand &MO = MI->getOperand(opNum); switch (MO.getType()) { case MachineOperand::MO_Register: @@ -317,23 +256,25 @@ void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum) { /// PrintAsmOperand - Print out an operand for an inline asm expression. /// bool XCoreAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, - const char *ExtraCode) { - printOperand(MI, OpNo); + unsigned AsmVariant,const char *ExtraCode, + raw_ostream &O) { + printOperand(MI, OpNo, O); return false; } void XCoreAsmPrinter::EmitInstruction(const MachineInstr *MI) { + SmallString<128> Str; + raw_svector_ostream O(Str); + // Check for mov mnemonic unsigned src, dst, srcSR, dstSR; if (TM.getInstrInfo()->isMoveInstr(*MI, src, dst, srcSR, dstSR)) { O << "\tmov " << getRegisterName(dst) << ", "; O << getRegisterName(src); - OutStreamer.AddBlankLine(); - return; + } else { + printInstruction(MI, O); } - printInstruction(MI); - OutStreamer.AddBlankLine(); + OutStreamer.EmitRawText(O.str()); } // Force static initialization. diff --git a/lib/Target/XCore/XCore.td b/lib/Target/XCore/XCore.td index b07445dd386f..38401895e634 100644 --- a/lib/Target/XCore/XCore.td +++ b/lib/Target/XCore/XCore.td @@ -24,10 +24,7 @@ include "XCoreRegisterInfo.td" include "XCoreInstrInfo.td" include "XCoreCallingConv.td" -def XCoreInstrInfo : InstrInfo { - let TSFlagsFields = []; - let TSFlagsShifts = []; -} +def XCoreInstrInfo : InstrInfo; //===----------------------------------------------------------------------===// // XCore processors supported. diff --git a/lib/Target/XCore/XCoreISelLowering.cpp b/lib/Target/XCore/XCoreISelLowering.cpp index bf1a45762795..27e523324664 100644 --- a/lib/Target/XCore/XCoreISelLowering.cpp +++ b/lib/Target/XCore/XCoreISelLowering.cpp @@ -1443,7 +1443,7 @@ SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N, return DAG.getMemmove(Chain, dl, ST->getBasePtr(), LD->getBasePtr(), DAG.getConstant(StoreBits/8, MVT::i32), - Alignment, ST->getSrcValue(), + Alignment, false, ST->getSrcValue(), ST->getSrcValueOffset(), LD->getSrcValue(), LD->getSrcValueOffset()); } diff --git a/lib/Target/XCore/XCoreInstrInfo.cpp b/lib/Target/XCore/XCoreInstrInfo.cpp index ae3f16c2dfe4..c9831128ba22 100644 --- a/lib/Target/XCore/XCoreInstrInfo.cpp +++ b/lib/Target/XCore/XCoreInstrInfo.cpp @@ -14,12 +14,12 @@ #include "XCoreMachineFunctionInfo.h" #include "XCoreInstrInfo.h" #include "XCore.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/MC/MCContext.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineLocation.h" -#include "llvm/CodeGen/MachineModuleInfo.h" #include "XCoreGenInstrInfo.inc" +#include "llvm/ADT/STLExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -419,14 +419,11 @@ void XCoreInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, bool XCoreInstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, - const std::vector<CalleeSavedInfo> &CSI) const -{ + const std::vector<CalleeSavedInfo> &CSI) const { if (CSI.empty()) { return true; } MachineFunction *MF = MBB.getParent(); - const MachineFrameInfo *MFI = MF->getFrameInfo(); - MachineModuleInfo *MMI = MFI->getMachineModuleInfo(); XCoreFunctionInfo *XFI = MF->getInfo<XCoreFunctionInfo>(); bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(*MF); @@ -442,7 +439,7 @@ bool XCoreInstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB, storeRegToStackSlot(MBB, MI, it->getReg(), true, it->getFrameIdx(), it->getRegClass()); if (emitFrameMoves) { - MCSymbol *SaveLabel = MMI->getContext().CreateTempSymbol(); + MCSymbol *SaveLabel = MF->getContext().CreateTempSymbol(); BuildMI(MBB, MI, DL, get(XCore::DBG_LABEL)).addSym(SaveLabel); XFI->getSpillLabels().push_back(std::make_pair(SaveLabel, *it)); } diff --git a/lib/Target/XCore/XCoreMCAsmInfo.cpp b/lib/Target/XCore/XCoreMCAsmInfo.cpp index bf785755db4e..5f6feae37235 100644 --- a/lib/Target/XCore/XCoreMCAsmInfo.cpp +++ b/lib/Target/XCore/XCoreMCAsmInfo.cpp @@ -25,6 +25,5 @@ XCoreMCAsmInfo::XCoreMCAsmInfo(const Target &T, const StringRef &TT) { // Debug HasLEB128 = true; - AbsoluteDebugSectionOffsets = true; } diff --git a/lib/Target/XCore/XCoreRegisterInfo.cpp b/lib/Target/XCore/XCoreRegisterInfo.cpp index 1631e7399922..ab71d0535444 100644 --- a/lib/Target/XCore/XCoreRegisterInfo.cpp +++ b/lib/Target/XCore/XCoreRegisterInfo.cpp @@ -67,12 +67,8 @@ unsigned XCoreRegisterInfo::getNumArgRegs(const MachineFunction *MF) return array_lengthof(XCore_ArgRegs); } -bool XCoreRegisterInfo::needsFrameMoves(const MachineFunction &MF) -{ - const MachineFrameInfo *MFI = MF.getFrameInfo(); - MachineModuleInfo *MMI = MFI->getMachineModuleInfo(); - return (MMI && MMI->hasDebugInfo()) || - !MF.getFunction()->doesNotThrow() || +bool XCoreRegisterInfo::needsFrameMoves(const MachineFunction &MF) { + return MF.getMMI().hasDebugInfo() || !MF.getFunction()->doesNotThrow() || UnwindTablesMandatory; } @@ -412,7 +408,7 @@ void XCoreRegisterInfo::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB MachineBasicBlock::iterator MBBI = MBB.begin(); MachineFrameInfo *MFI = MF.getFrameInfo(); - MachineModuleInfo *MMI = MFI->getMachineModuleInfo(); + MachineModuleInfo *MMI = &MF.getMMI(); XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp index 76c815da8628..e025b053765b 100644 --- a/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -136,8 +136,14 @@ Instruction *InstCombiner::SimplifyMemTransfer(MemIntrinsic *MI) { return 0; // If not 1/2/4/8 bytes, exit. // Use an integer load+store unless we can find something better. - Type *NewPtrTy = - PointerType::getUnqual(IntegerType::get(MI->getContext(), Size<<3)); + unsigned SrcAddrSp = + cast<PointerType>(MI->getOperand(2)->getType())->getAddressSpace(); + unsigned DstAddrSp = + cast<PointerType>(MI->getOperand(1)->getType())->getAddressSpace(); + + const IntegerType* IntType = IntegerType::get(MI->getContext(), Size<<3); + Type *NewSrcPtrTy = PointerType::get(IntType, SrcAddrSp); + Type *NewDstPtrTy = PointerType::get(IntType, DstAddrSp); // Memcpy forces the use of i8* for the source and destination. That means // that if you're using memcpy to move one double around, you'll get a cast @@ -167,8 +173,10 @@ Instruction *InstCombiner::SimplifyMemTransfer(MemIntrinsic *MI) { break; } - if (SrcETy->isSingleValueType()) - NewPtrTy = PointerType::getUnqual(SrcETy); + if (SrcETy->isSingleValueType()) { + NewSrcPtrTy = PointerType::get(SrcETy, SrcAddrSp); + NewDstPtrTy = PointerType::get(SrcETy, DstAddrSp); + } } } @@ -178,11 +186,12 @@ Instruction *InstCombiner::SimplifyMemTransfer(MemIntrinsic *MI) { SrcAlign = std::max(SrcAlign, CopyAlign); DstAlign = std::max(DstAlign, CopyAlign); - Value *Src = Builder->CreateBitCast(MI->getOperand(2), NewPtrTy); - Value *Dest = Builder->CreateBitCast(MI->getOperand(1), NewPtrTy); - Instruction *L = new LoadInst(Src, "tmp", false, SrcAlign); + Value *Src = Builder->CreateBitCast(MI->getOperand(2), NewSrcPtrTy); + Value *Dest = Builder->CreateBitCast(MI->getOperand(1), NewDstPtrTy); + Instruction *L = new LoadInst(Src, "tmp", MI->isVolatile(), SrcAlign); InsertNewInstBefore(L, *MI); - InsertNewInstBefore(new StoreInst(L, Dest, false, DstAlign), *MI); + InsertNewInstBefore(new StoreInst(L, Dest, MI->isVolatile(), DstAlign), + *MI); // Set the size of the copy to 0, it will be deleted on the next iteration. MI->setOperand(3, Constant::getNullValue(MemOpLength->getType())); @@ -275,10 +284,11 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { if (GVSrc->isConstant()) { Module *M = CI.getParent()->getParent()->getParent(); Intrinsic::ID MemCpyID = Intrinsic::memcpy; - const Type *Tys[1]; - Tys[0] = CI.getOperand(3)->getType(); + const Type *Tys[3] = { CI.getOperand(1)->getType(), + CI.getOperand(2)->getType(), + CI.getOperand(3)->getType() }; CI.setOperand(0, - Intrinsic::getDeclaration(M, MemCpyID, Tys, 1)); + Intrinsic::getDeclaration(M, MemCpyID, Tys, 3)); Changed = true; } } diff --git a/lib/Transforms/Scalar/LoopUnswitch.cpp b/lib/Transforms/Scalar/LoopUnswitch.cpp index 27fd2ef5a686..3918738cc8be 100644 --- a/lib/Transforms/Scalar/LoopUnswitch.cpp +++ b/lib/Transforms/Scalar/LoopUnswitch.cpp @@ -231,8 +231,7 @@ bool LoopUnswitch::processCurrentLoop() { // block that is branching on a loop-invariant condition, we can unswitch this // loop. for (Loop::block_iterator I = currentLoop->block_begin(), - E = currentLoop->block_end(); - I != E; ++I) { + E = currentLoop->block_end(); I != E; ++I) { TerminatorInst *TI = (*I)->getTerminator(); if (BranchInst *BI = dyn_cast<BranchInst>(TI)) { // If this isn't branching on an invariant condition, we can't unswitch @@ -474,7 +473,6 @@ static inline void RemapInstruction(Instruction *I, static Loop *CloneLoop(Loop *L, Loop *PL, DenseMap<const Value*, Value*> &VM, LoopInfo *LI, LPPassManager *LPM) { Loop *New = new Loop(); - LPM->insertLoop(New, PL); // Add all of the blocks in L to the new loop. @@ -565,8 +563,7 @@ void LoopUnswitch::UnswitchTrivialCondition(Loop *L, Value *Cond, /// SplitExitEdges - Split all of the edges from inside the loop to their exit /// blocks. Update the appropriate Phi nodes as we do so. void LoopUnswitch::SplitExitEdges(Loop *L, - const SmallVector<BasicBlock *, 8> &ExitBlocks) -{ + const SmallVector<BasicBlock *, 8> &ExitBlocks){ for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) { BasicBlock *ExitBlock = ExitBlocks[i]; @@ -619,15 +616,15 @@ void LoopUnswitch::UnswitchNontrivialCondition(Value *LIC, Constant *Val, NewBlocks.reserve(LoopBlocks.size()); DenseMap<const Value*, Value*> ValueMap; for (unsigned i = 0, e = LoopBlocks.size(); i != e; ++i) { - BasicBlock *New = CloneBasicBlock(LoopBlocks[i], ValueMap, ".us", F); - NewBlocks.push_back(New); - ValueMap[LoopBlocks[i]] = New; // Keep the BB mapping. - LPM->cloneBasicBlockSimpleAnalysis(LoopBlocks[i], New, L); + BasicBlock *NewBB = CloneBasicBlock(LoopBlocks[i], ValueMap, ".us", F); + NewBlocks.push_back(NewBB); + ValueMap[LoopBlocks[i]] = NewBB; // Keep the BB mapping. + LPM->cloneBasicBlockSimpleAnalysis(LoopBlocks[i], NewBB, L); } // Splice the newly inserted blocks into the function right before the // original preheader. - F->getBasicBlockList().splice(LoopBlocks[0], F->getBasicBlockList(), + F->getBasicBlockList().splice(NewPreheader, F->getBasicBlockList(), NewBlocks[0], F->end()); // Now we create the new Loop object for the versioned loop. @@ -652,8 +649,8 @@ void LoopUnswitch::UnswitchNontrivialCondition(Value *LIC, Constant *Val, // If the successor of the exit block had PHI nodes, add an entry for // NewExit. PHINode *PN; - for (BasicBlock::iterator I = ExitSucc->begin(); - (PN = dyn_cast<PHINode>(I)); ++I) { + for (BasicBlock::iterator I = ExitSucc->begin(); isa<PHINode>(I); ++I) { + PN = cast<PHINode>(I); Value *V = PN->getIncomingValueForBlock(ExitBlocks[i]); DenseMap<const Value *, Value*>::iterator It = ValueMap.find(V); if (It != ValueMap.end()) V = It->second; @@ -682,7 +679,7 @@ void LoopUnswitch::UnswitchNontrivialCondition(Value *LIC, Constant *Val, // Now we rewrite the original code to know that the condition is true and the // new code to know that the condition is false. - RewriteLoopBodyWithConditionConstant(L , LIC, Val, false); + RewriteLoopBodyWithConditionConstant(L, LIC, Val, false); // It's possible that simplifying one loop could cause the other to be // deleted. If so, don't simplify it. @@ -884,65 +881,66 @@ void LoopUnswitch::RewriteLoopBodyWithConditionConstant(Loop *L, Value *LIC, U->replaceUsesOfWith(LIC, Replacement); Worklist.push_back(U); } - } else { - // Otherwise, we don't know the precise value of LIC, but we do know that it - // is certainly NOT "Val". As such, simplify any uses in the loop that we - // can. This case occurs when we unswitch switch statements. - for (unsigned i = 0, e = Users.size(); i != e; ++i) - if (Instruction *U = cast<Instruction>(Users[i])) { - if (!L->contains(U)) - continue; + SimplifyCode(Worklist, L); + return; + } + + // Otherwise, we don't know the precise value of LIC, but we do know that it + // is certainly NOT "Val". As such, simplify any uses in the loop that we + // can. This case occurs when we unswitch switch statements. + for (unsigned i = 0, e = Users.size(); i != e; ++i) { + Instruction *U = cast<Instruction>(Users[i]); + if (!L->contains(U)) + continue; - Worklist.push_back(U); + Worklist.push_back(U); - // If we know that LIC is not Val, use this info to simplify code. - if (SwitchInst *SI = dyn_cast<SwitchInst>(U)) { - for (unsigned i = 1, e = SI->getNumCases(); i != e; ++i) { - if (SI->getCaseValue(i) == Val) { - // Found a dead case value. Don't remove PHI nodes in the - // successor if they become single-entry, those PHI nodes may - // be in the Users list. - - // FIXME: This is a hack. We need to keep the successor around - // and hooked up so as to preserve the loop structure, because - // trying to update it is complicated. So instead we preserve the - // loop structure and put the block on a dead code path. - BasicBlock *Switch = SI->getParent(); - SplitEdge(Switch, SI->getSuccessor(i), this); - // Compute the successors instead of relying on the return value - // of SplitEdge, since it may have split the switch successor - // after PHI nodes. - BasicBlock *NewSISucc = SI->getSuccessor(i); - BasicBlock *OldSISucc = *succ_begin(NewSISucc); - // Create an "unreachable" destination. - BasicBlock *Abort = BasicBlock::Create(Context, "us-unreachable", - Switch->getParent(), - OldSISucc); - new UnreachableInst(Context, Abort); - // Force the new case destination to branch to the "unreachable" - // block while maintaining a (dead) CFG edge to the old block. - NewSISucc->getTerminator()->eraseFromParent(); - BranchInst::Create(Abort, OldSISucc, - ConstantInt::getTrue(Context), NewSISucc); - // Release the PHI operands for this edge. - for (BasicBlock::iterator II = NewSISucc->begin(); - PHINode *PN = dyn_cast<PHINode>(II); ++II) - PN->setIncomingValue(PN->getBasicBlockIndex(Switch), - UndefValue::get(PN->getType())); - // Tell the domtree about the new block. We don't fully update the - // domtree here -- instead we force it to do a full recomputation - // after the pass is complete -- but we do need to inform it of - // new blocks. - if (DT) - DT->addNewBlock(Abort, NewSISucc); - break; - } - } - } + // TODO: We could do other simplifications, for example, turning + // 'icmp eq LIC, Val' -> false. + + // If we know that LIC is not Val, use this info to simplify code. + SwitchInst *SI = dyn_cast<SwitchInst>(U); + if (SI == 0 || !isa<ConstantInt>(Val)) continue; + + unsigned DeadCase = SI->findCaseValue(cast<ConstantInt>(Val)); + if (DeadCase == 0) continue; // Default case is live for multiple values. + + // Found a dead case value. Don't remove PHI nodes in the + // successor if they become single-entry, those PHI nodes may + // be in the Users list. - // TODO: We could do other simplifications, for example, turning - // LIC == Val -> false. - } + // FIXME: This is a hack. We need to keep the successor around + // and hooked up so as to preserve the loop structure, because + // trying to update it is complicated. So instead we preserve the + // loop structure and put the block on a dead code path. + BasicBlock *Switch = SI->getParent(); + SplitEdge(Switch, SI->getSuccessor(DeadCase), this); + // Compute the successors instead of relying on the return value + // of SplitEdge, since it may have split the switch successor + // after PHI nodes. + BasicBlock *NewSISucc = SI->getSuccessor(DeadCase); + BasicBlock *OldSISucc = *succ_begin(NewSISucc); + // Create an "unreachable" destination. + BasicBlock *Abort = BasicBlock::Create(Context, "us-unreachable", + Switch->getParent(), + OldSISucc); + new UnreachableInst(Context, Abort); + // Force the new case destination to branch to the "unreachable" + // block while maintaining a (dead) CFG edge to the old block. + NewSISucc->getTerminator()->eraseFromParent(); + BranchInst::Create(Abort, OldSISucc, + ConstantInt::getTrue(Context), NewSISucc); + // Release the PHI operands for this edge. + for (BasicBlock::iterator II = NewSISucc->begin(); + PHINode *PN = dyn_cast<PHINode>(II); ++II) + PN->setIncomingValue(PN->getBasicBlockIndex(Switch), + UndefValue::get(PN->getType())); + // Tell the domtree about the new block. We don't fully update the + // domtree here -- instead we force it to do a full recomputation + // after the pass is complete -- but we do need to inform it of + // new blocks. + if (DT) + DT->addNewBlock(Abort, NewSISucc); } SimplifyCode(Worklist, L); @@ -1054,7 +1052,10 @@ void LoopUnswitch::SimplifyCode(std::vector<Instruction*> &Worklist, Loop *L) { LPM->deleteSimpleAnalysisValue(Succ, L); Succ->eraseFromParent(); ++NumSimplify; - } else if (ConstantInt *CB = dyn_cast<ConstantInt>(BI->getCondition())){ + break; + } + + if (ConstantInt *CB = dyn_cast<ConstantInt>(BI->getCondition())){ // Conditional branch. Turn it into an unconditional branch, then // remove dead blocks. break; // FIXME: Enable. diff --git a/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/lib/Transforms/Scalar/MemCpyOptimizer.cpp index 62e29770588e..3b305ae766e8 100644 --- a/lib/Transforms/Scalar/MemCpyOptimizer.cpp +++ b/lib/Transforms/Scalar/MemCpyOptimizer.cpp @@ -413,7 +413,6 @@ bool MemCpyOpt::processStore(StoreInst *SI, BasicBlock::iterator &BBI) { // interesting as a small compile-time optimization. Ranges.addStore(0, SI); - Function *MemSetF = 0; // Now that we have full information about ranges, loop over the ranges and // emit memset's for anything big enough to be worthwhile. @@ -433,29 +432,40 @@ bool MemCpyOpt::processStore(StoreInst *SI, BasicBlock::iterator &BBI) { // memset block. This ensure that the memset is dominated by any addressing // instruction needed by the start of the block. BasicBlock::iterator InsertPt = BI; - - if (MemSetF == 0) { - const Type *Ty = Type::getInt64Ty(Context); - MemSetF = Intrinsic::getDeclaration(M, Intrinsic::memset, &Ty, 1); - } - + // Get the starting pointer of the block. StartPtr = Range.StartPtr; - + + // Determine alignment + unsigned Alignment = Range.Alignment; + if (Alignment == 0) { + const Type *EltType = + cast<PointerType>(StartPtr->getType())->getElementType(); + Alignment = TD->getABITypeAlignment(EltType); + } + // Cast the start ptr to be i8* as memset requires. - const Type *i8Ptr = Type::getInt8PtrTy(Context); - if (StartPtr->getType() != i8Ptr) + const PointerType* StartPTy = cast<PointerType>(StartPtr->getType()); + const PointerType *i8Ptr = Type::getInt8PtrTy(Context, + StartPTy->getAddressSpace()); + if (StartPTy!= i8Ptr) StartPtr = new BitCastInst(StartPtr, i8Ptr, StartPtr->getName(), InsertPt); - + Value *Ops[] = { StartPtr, ByteVal, // Start, value // size ConstantInt::get(Type::getInt64Ty(Context), Range.End-Range.Start), // align - ConstantInt::get(Type::getInt32Ty(Context), Range.Alignment) + ConstantInt::get(Type::getInt32Ty(Context), Alignment), + // volatile + ConstantInt::get(Type::getInt1Ty(Context), 0), }; - Value *C = CallInst::Create(MemSetF, Ops, Ops+4, "", InsertPt); + const Type *Tys[] = { Ops[0]->getType(), Ops[2]->getType() }; + + Function *MemSetF = Intrinsic::getDeclaration(M, Intrinsic::memset, Tys, 2); + + Value *C = CallInst::Create(MemSetF, Ops, Ops+5, "", InsertPt); DEBUG(dbgs() << "Replace stores:\n"; for (unsigned i = 0, e = Range.TheStores.size(); i != e; ++i) dbgs() << *Range.TheStores[i]; @@ -680,16 +690,19 @@ bool MemCpyOpt::processMemCpy(MemCpyInst *M) { return false; // If all checks passed, then we can transform these memcpy's - const Type *Ty = M->getLength()->getType(); + const Type *ArgTys[3] = { M->getRawDest()->getType(), + MDep->getRawSource()->getType(), + M->getLength()->getType() }; Function *MemCpyFun = Intrinsic::getDeclaration( M->getParent()->getParent()->getParent(), - M->getIntrinsicID(), &Ty, 1); + M->getIntrinsicID(), ArgTys, 3); - Value *Args[4] = { - M->getRawDest(), MDep->getRawSource(), M->getLength(), M->getAlignmentCst() + Value *Args[5] = { + M->getRawDest(), MDep->getRawSource(), M->getLength(), + M->getAlignmentCst(), M->getVolatileCst() }; - CallInst *C = CallInst::Create(MemCpyFun, Args, Args+4, "", M); + CallInst *C = CallInst::Create(MemCpyFun, Args, Args+5, "", M); // If C and M don't interfere, then this is a valid transformation. If they @@ -728,8 +741,10 @@ bool MemCpyOpt::processMemMove(MemMoveInst *M) { // If not, then we know we can transform this. Module *Mod = M->getParent()->getParent()->getParent(); - const Type *Ty = M->getLength()->getType(); - M->setOperand(0, Intrinsic::getDeclaration(Mod, Intrinsic::memcpy, &Ty, 1)); + const Type *ArgTys[3] = { M->getRawDest()->getType(), + M->getRawSource()->getType(), + M->getLength()->getType() }; + M->setOperand(0,Intrinsic::getDeclaration(Mod, Intrinsic::memcpy, ArgTys, 3)); // MemDep may have over conservative information about this instruction, just // conservatively flush it from the cache. diff --git a/lib/Transforms/Scalar/SCCP.cpp b/lib/Transforms/Scalar/SCCP.cpp index 546b7b6cc292..4f09bee53a81 100644 --- a/lib/Transforms/Scalar/SCCP.cpp +++ b/lib/Transforms/Scalar/SCCP.cpp @@ -1521,45 +1521,48 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) { } } + // Check to see if we have a branch or switch on an undefined value. If so + // we force the branch to go one way or the other to make the successor + // values live. It doesn't really matter which way we force it. TerminatorInst *TI = BB->getTerminator(); if (BranchInst *BI = dyn_cast<BranchInst>(TI)) { if (!BI->isConditional()) continue; if (!getValueState(BI->getCondition()).isUndefined()) continue; - } else if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) { + + // If the input to SCCP is actually branch on undef, fix the undef to + // false. + if (isa<UndefValue>(BI->getCondition())) { + BI->setCondition(ConstantInt::getFalse(BI->getContext())); + markEdgeExecutable(BB, TI->getSuccessor(1)); + return true; + } + + // Otherwise, it is a branch on a symbolic value which is currently + // considered to be undef. Handle this by forcing the input value to the + // branch to false. + markForcedConstant(BI->getCondition(), + ConstantInt::getFalse(TI->getContext())); + return true; + } + + if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) { if (SI->getNumSuccessors() < 2) // no cases continue; if (!getValueState(SI->getCondition()).isUndefined()) continue; - } else { - continue; - } - - // If the edge to the second successor isn't thought to be feasible yet, - // mark it so now. We pick the second one so that this goes to some - // enumerated value in a switch instead of going to the default destination. - if (KnownFeasibleEdges.count(Edge(BB, TI->getSuccessor(1)))) - continue; - - // Otherwise, it isn't already thought to be feasible. Mark it as such now - // and return. This will make other blocks reachable, which will allow new - // values to be discovered and existing ones to be moved in the lattice. - markEdgeExecutable(BB, TI->getSuccessor(1)); - - // This must be a conditional branch of switch on undef. At this point, - // force the old terminator to branch to the first successor. This is - // required because we are now influencing the dataflow of the function with - // the assumption that this edge is taken. If we leave the branch condition - // as undef, then further analysis could think the undef went another way - // leading to an inconsistent set of conclusions. - if (BranchInst *BI = dyn_cast<BranchInst>(TI)) { - BI->setCondition(ConstantInt::getFalse(BI->getContext())); - } else { - SwitchInst *SI = cast<SwitchInst>(TI); - SI->setCondition(SI->getCaseValue(1)); + + // If the input to SCCP is actually switch on undef, fix the undef to + // the first constant. + if (isa<UndefValue>(SI->getCondition())) { + SI->setCondition(SI->getCaseValue(1)); + markEdgeExecutable(BB, TI->getSuccessor(1)); + return true; + } + + markForcedConstant(SI->getCondition(), SI->getCaseValue(1)); + return true; } - - return true; } return false; diff --git a/lib/Transforms/Scalar/ScalarReplAggregates.cpp b/lib/Transforms/Scalar/ScalarReplAggregates.cpp index bbe627065584..6211beb70ba2 100644 --- a/lib/Transforms/Scalar/ScalarReplAggregates.cpp +++ b/lib/Transforms/Scalar/ScalarReplAggregates.cpp @@ -858,8 +858,17 @@ void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst, EltPtr = new BitCastInst(EltPtr, BytePtrTy, EltPtr->getName(), MI); // Cast the other pointer (if we have one) to BytePtrTy. - if (OtherElt && OtherElt->getType() != BytePtrTy) - OtherElt = new BitCastInst(OtherElt, BytePtrTy, OtherElt->getName(), MI); + if (OtherElt && OtherElt->getType() != BytePtrTy) { + // Preserve address space of OtherElt + const PointerType* OtherPTy = cast<PointerType>(OtherElt->getType()); + const PointerType* PTy = cast<PointerType>(BytePtrTy); + if (OtherPTy->getElementType() != PTy->getElementType()) { + Type *NewOtherPTy = PointerType::get(PTy->getElementType(), + OtherPTy->getAddressSpace()); + OtherElt = new BitCastInst(OtherElt, NewOtherPTy, + OtherElt->getNameStr(), MI); + } + } unsigned EltSize = TD->getTypeAllocSize(EltTy); @@ -870,17 +879,28 @@ void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst, SROADest ? OtherElt : EltPtr, // Src ptr ConstantInt::get(MI->getOperand(3)->getType(), EltSize), // Size // Align - ConstantInt::get(Type::getInt32Ty(MI->getContext()), OtherEltAlign) + ConstantInt::get(Type::getInt32Ty(MI->getContext()), OtherEltAlign), + MI->getVolatileCst() }; - CallInst::Create(TheFn, Ops, Ops + 4, "", MI); + // In case we fold the address space overloaded memcpy of A to B + // with memcpy of B to C, change the function to be a memcpy of A to C. + const Type *Tys[] = { Ops[0]->getType(), Ops[1]->getType(), + Ops[2]->getType() }; + Module *M = MI->getParent()->getParent()->getParent(); + TheFn = Intrinsic::getDeclaration(M, MI->getIntrinsicID(), Tys, 3); + CallInst::Create(TheFn, Ops, Ops + 5, "", MI); } else { assert(isa<MemSetInst>(MI)); Value *Ops[] = { EltPtr, MI->getOperand(2), // Dest, Value, ConstantInt::get(MI->getOperand(3)->getType(), EltSize), // Size - Zero // Align + Zero, // Align + ConstantInt::get(Type::getInt1Ty(MI->getContext()), 0) // isVolatile }; - CallInst::Create(TheFn, Ops, Ops + 4, "", MI); + const Type *Tys[] = { Ops[0]->getType(), Ops[2]->getType() }; + Module *M = MI->getParent()->getParent()->getParent(); + TheFn = Intrinsic::getDeclaration(M, Intrinsic::memset, Tys, 2); + CallInst::Create(TheFn, Ops, Ops + 5, "", MI); } } DeadInsts.push_back(MI); diff --git a/lib/Transforms/Scalar/SimplifyLibCalls.cpp b/lib/Transforms/Scalar/SimplifyLibCalls.cpp index 5941ea6571b7..b053cfc3b46d 100644 --- a/lib/Transforms/Scalar/SimplifyLibCalls.cpp +++ b/lib/Transforms/Scalar/SimplifyLibCalls.cpp @@ -142,7 +142,8 @@ struct StrCatOpt : public LibCallOptimization { // We have enough information to now generate the memcpy call to do the // concatenation for us. Make a memcpy to copy the nul byte with align = 1. EmitMemCpy(CpyDst, Src, - ConstantInt::get(TD->getIntPtrType(*Context), Len+1), 1, B, TD); + ConstantInt::get(TD->getIntPtrType(*Context), Len+1), + 1, false, B, TD); } }; @@ -383,7 +384,8 @@ struct StrCpyOpt : public LibCallOptimization { CI->getOperand(3), B, TD); else EmitMemCpy(Dst, Src, - ConstantInt::get(TD->getIntPtrType(*Context), Len), 1, B, TD); + ConstantInt::get(TD->getIntPtrType(*Context), Len), + 1, false, B, TD); return Dst; } }; @@ -411,8 +413,8 @@ struct StrNCpyOpt : public LibCallOptimization { if (SrcLen == 0) { // strncpy(x, "", y) -> memset(x, '\0', y, 1) - EmitMemSet(Dst, ConstantInt::get(Type::getInt8Ty(*Context), '\0'), LenOp, - B, TD); + EmitMemSet(Dst, ConstantInt::get(Type::getInt8Ty(*Context), '\0'), + LenOp, false, B, TD); return Dst; } @@ -432,7 +434,8 @@ struct StrNCpyOpt : public LibCallOptimization { // strncpy(x, s, c) -> memcpy(x, s, c, 1) [s and c are constant] EmitMemCpy(Dst, Src, - ConstantInt::get(TD->getIntPtrType(*Context), Len), 1, B, TD); + ConstantInt::get(TD->getIntPtrType(*Context), Len), + 1, false, B, TD); return Dst; } @@ -593,7 +596,7 @@ struct MemCpyOpt : public LibCallOptimization { // memcpy(x, y, n) -> llvm.memcpy(x, y, n, 1) EmitMemCpy(CI->getOperand(1), CI->getOperand(2), - CI->getOperand(3), 1, B, TD); + CI->getOperand(3), 1, false, B, TD); return CI->getOperand(1); } }; @@ -615,7 +618,7 @@ struct MemMoveOpt : public LibCallOptimization { // memmove(x, y, n) -> llvm.memmove(x, y, n, 1) EmitMemMove(CI->getOperand(1), CI->getOperand(2), - CI->getOperand(3), 1, B, TD); + CI->getOperand(3), 1, false, B, TD); return CI->getOperand(1); } }; @@ -637,8 +640,8 @@ struct MemSetOpt : public LibCallOptimization { // memset(p, v, n) -> llvm.memset(p, v, n, 1) Value *Val = B.CreateIntCast(CI->getOperand(2), Type::getInt8Ty(*Context), - false); - EmitMemSet(CI->getOperand(1), Val, CI->getOperand(3), B, TD); + false); + EmitMemSet(CI->getOperand(1), Val, CI->getOperand(3), false, B, TD); return CI->getOperand(1); } }; @@ -999,7 +1002,7 @@ struct SPrintFOpt : public LibCallOptimization { // sprintf(str, fmt) -> llvm.memcpy(str, fmt, strlen(fmt)+1, 1) EmitMemCpy(CI->getOperand(1), CI->getOperand(2), // Copy the nul byte. ConstantInt::get(TD->getIntPtrType(*Context), - FormatStr.size()+1), 1, B, TD); + FormatStr.size()+1), 1, false, B, TD); return ConstantInt::get(CI->getType(), FormatStr.size()); } @@ -1013,11 +1016,11 @@ struct SPrintFOpt : public LibCallOptimization { // sprintf(dst, "%c", chr) --> *(i8*)dst = chr; *((i8*)dst+1) = 0 if (!CI->getOperand(3)->getType()->isIntegerTy()) return 0; Value *V = B.CreateTrunc(CI->getOperand(3), - Type::getInt8Ty(*Context), "char"); + Type::getInt8Ty(*Context), "char"); Value *Ptr = CastToCStr(CI->getOperand(1), B); B.CreateStore(V, Ptr); Ptr = B.CreateGEP(Ptr, ConstantInt::get(Type::getInt32Ty(*Context), 1), - "nul"); + "nul"); B.CreateStore(Constant::getNullValue(Type::getInt8Ty(*Context)), Ptr); return ConstantInt::get(CI->getType(), 1); @@ -1034,7 +1037,7 @@ struct SPrintFOpt : public LibCallOptimization { Value *IncLen = B.CreateAdd(Len, ConstantInt::get(Len->getType(), 1), "leninc"); - EmitMemCpy(CI->getOperand(1), CI->getOperand(3), IncLen, 1, B, TD); + EmitMemCpy(CI->getOperand(1), CI->getOperand(3), IncLen, 1, false, B, TD); // The sprintf result is the unincremented number of bytes in the string. return B.CreateIntCast(Len, CI->getType(), false); diff --git a/lib/Transforms/Utils/BasicBlockUtils.cpp b/lib/Transforms/Utils/BasicBlockUtils.cpp index 1f62dabb2014..2f1ae005a4fd 100644 --- a/lib/Transforms/Utils/BasicBlockUtils.cpp +++ b/lib/Transforms/Utils/BasicBlockUtils.cpp @@ -336,21 +336,19 @@ BasicBlock *llvm::SplitBlock(BasicBlock *Old, Instruction *SplitPt, Pass *P) { if (Loop *L = LI->getLoopFor(Old)) L->addBasicBlockToLoop(New, LI->getBase()); - if (DominatorTree *DT = P->getAnalysisIfAvailable<DominatorTree>()) - { - // Old dominates New. New node domiantes all other nodes dominated by Old. - DomTreeNode *OldNode = DT->getNode(Old); - std::vector<DomTreeNode *> Children; - for (DomTreeNode::iterator I = OldNode->begin(), E = OldNode->end(); - I != E; ++I) - Children.push_back(*I); - - DomTreeNode *NewNode = DT->addNewBlock(New,Old); - + if (DominatorTree *DT = P->getAnalysisIfAvailable<DominatorTree>()) { + // Old dominates New. New node domiantes all other nodes dominated by Old. + DomTreeNode *OldNode = DT->getNode(Old); + std::vector<DomTreeNode *> Children; + for (DomTreeNode::iterator I = OldNode->begin(), E = OldNode->end(); + I != E; ++I) + Children.push_back(*I); + + DomTreeNode *NewNode = DT->addNewBlock(New,Old); for (std::vector<DomTreeNode *>::iterator I = Children.begin(), E = Children.end(); I != E; ++I) DT->changeImmediateDominator(*I, NewNode); - } + } if (DominanceFrontier *DF = P->getAnalysisIfAvailable<DominanceFrontier>()) DF->splitBlock(Old); diff --git a/lib/Transforms/Utils/BuildLibCalls.cpp b/lib/Transforms/Utils/BuildLibCalls.cpp index 0afccf42f637..fff817928f34 100644 --- a/lib/Transforms/Utils/BuildLibCalls.cpp +++ b/lib/Transforms/Utils/BuildLibCalls.cpp @@ -109,15 +109,16 @@ Value *llvm::EmitStrNCpy(Value *Dst, Value *Src, Value *Len, /// EmitMemCpy - Emit a call to the memcpy function to the builder. This always /// expects that Len has type 'intptr_t' and Dst/Src are pointers. -Value *llvm::EmitMemCpy(Value *Dst, Value *Src, Value *Len, - unsigned Align, IRBuilder<> &B, const TargetData *TD) { +Value *llvm::EmitMemCpy(Value *Dst, Value *Src, Value *Len, unsigned Align, + bool isVolatile, IRBuilder<> &B, const TargetData *TD) { Module *M = B.GetInsertBlock()->getParent()->getParent(); - const Type *Ty = Len->getType(); - Value *MemCpy = Intrinsic::getDeclaration(M, Intrinsic::memcpy, &Ty, 1); + const Type *ArgTys[3] = { Dst->getType(), Src->getType(), Len->getType() }; + Value *MemCpy = Intrinsic::getDeclaration(M, Intrinsic::memcpy, ArgTys, 3); Dst = CastToCStr(Dst, B); Src = CastToCStr(Src, B); - return B.CreateCall4(MemCpy, Dst, Src, Len, - ConstantInt::get(B.getInt32Ty(), Align)); + return B.CreateCall5(MemCpy, Dst, Src, Len, + ConstantInt::get(B.getInt32Ty(), Align), + ConstantInt::get(B.getInt1Ty(), isVolatile)); } /// EmitMemCpyChk - Emit a call to the __memcpy_chk function to the builder. @@ -146,16 +147,18 @@ Value *llvm::EmitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize, /// EmitMemMove - Emit a call to the memmove function to the builder. This /// always expects that the size has type 'intptr_t' and Dst/Src are pointers. -Value *llvm::EmitMemMove(Value *Dst, Value *Src, Value *Len, - unsigned Align, IRBuilder<> &B, const TargetData *TD) { +Value *llvm::EmitMemMove(Value *Dst, Value *Src, Value *Len, unsigned Align, + bool isVolatile, IRBuilder<> &B, const TargetData *TD) { Module *M = B.GetInsertBlock()->getParent()->getParent(); LLVMContext &Context = B.GetInsertBlock()->getContext(); - const Type *Ty = TD->getIntPtrType(Context); - Value *MemMove = Intrinsic::getDeclaration(M, Intrinsic::memmove, &Ty, 1); + const Type *ArgTys[3] = { Dst->getType(), Src->getType(), + TD->getIntPtrType(Context) }; + Value *MemMove = Intrinsic::getDeclaration(M, Intrinsic::memmove, ArgTys, 3); Dst = CastToCStr(Dst, B); Src = CastToCStr(Src, B); Value *A = ConstantInt::get(B.getInt32Ty(), Align); - return B.CreateCall4(MemMove, Dst, Src, Len, A); + Value *Vol = ConstantInt::get(B.getInt1Ty(), isVolatile); + return B.CreateCall5(MemMove, Dst, Src, Len, A, Vol); } /// EmitMemChr - Emit a call to the memchr function. This assumes that Ptr is @@ -206,15 +209,15 @@ Value *llvm::EmitMemCmp(Value *Ptr1, Value *Ptr2, } /// EmitMemSet - Emit a call to the memset function -Value *llvm::EmitMemSet(Value *Dst, Value *Val, - Value *Len, IRBuilder<> &B, const TargetData *TD) { +Value *llvm::EmitMemSet(Value *Dst, Value *Val, Value *Len, bool isVolatile, + IRBuilder<> &B, const TargetData *TD) { Module *M = B.GetInsertBlock()->getParent()->getParent(); Intrinsic::ID IID = Intrinsic::memset; - const Type *Tys[1]; - Tys[0] = Len->getType(); - Value *MemSet = Intrinsic::getDeclaration(M, IID, Tys, 1); + const Type *Tys[2] = { Dst->getType(), Len->getType() }; + Value *MemSet = Intrinsic::getDeclaration(M, IID, Tys, 2); Value *Align = ConstantInt::get(B.getInt32Ty(), 1); - return B.CreateCall4(MemSet, CastToCStr(Dst, B), Val, Len, Align); + Value *Vol = ConstantInt::get(B.getInt1Ty(), isVolatile); + return B.CreateCall5(MemSet, CastToCStr(Dst, B), Val, Len, Align, Vol); } /// EmitUnaryFloatFnCall - Emit a call to the unary function named 'Name' (e.g. @@ -381,7 +384,7 @@ bool SimplifyFortifiedLibCalls::fold(CallInst *CI, const TargetData *TD) { if (Name == "__memcpy_chk") { if (isFoldable(4, 3, false)) { EmitMemCpy(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), - 1, B, TD); + 1, false, B, TD); replaceCall(CI->getOperand(1)); return true; } @@ -396,7 +399,7 @@ bool SimplifyFortifiedLibCalls::fold(CallInst *CI, const TargetData *TD) { if (Name == "__memmove_chk") { if (isFoldable(4, 3, false)) { EmitMemMove(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), - 1, B, TD); + 1, false, B, TD); replaceCall(CI->getOperand(1)); return true; } @@ -407,7 +410,7 @@ bool SimplifyFortifiedLibCalls::fold(CallInst *CI, const TargetData *TD) { if (isFoldable(4, 3, false)) { Value *Val = B.CreateIntCast(CI->getOperand(2), B.getInt8Ty(), false); - EmitMemSet(CI->getOperand(1), Val, CI->getOperand(3), B, TD); + EmitMemSet(CI->getOperand(1), Val, CI->getOperand(3), false, B, TD); replaceCall(CI->getOperand(1)); return true; } diff --git a/lib/Transforms/Utils/InlineFunction.cpp b/lib/Transforms/Utils/InlineFunction.cpp index 17f8827fd5c0..75c9ccdd7a93 100644 --- a/lib/Transforms/Utils/InlineFunction.cpp +++ b/lib/Transforms/Utils/InlineFunction.cpp @@ -297,10 +297,10 @@ bool llvm::InlineFunction(CallSite CS, CallGraph *CG, const TargetData *TD, I->getName(), &*Caller->begin()->begin()); // Emit a memcpy. - const Type *Tys[] = { Type::getInt64Ty(Context) }; + const Type *Tys[3] = {VoidPtrTy, VoidPtrTy, Type::getInt64Ty(Context)}; Function *MemCpyFn = Intrinsic::getDeclaration(Caller->getParent(), Intrinsic::memcpy, - Tys, 1); + Tys, 3); Value *DestCast = new BitCastInst(NewAlloca, VoidPtrTy, "tmp", TheCall); Value *SrcCast = new BitCastInst(*AI, VoidPtrTy, "tmp", TheCall); @@ -309,17 +309,18 @@ bool llvm::InlineFunction(CallSite CS, CallGraph *CG, const TargetData *TD, Size = ConstantExpr::getSizeOf(AggTy); else Size = ConstantInt::get(Type::getInt64Ty(Context), - TD->getTypeStoreSize(AggTy)); + TD->getTypeStoreSize(AggTy)); // Always generate a memcpy of alignment 1 here because we don't know // the alignment of the src pointer. Other optimizations can infer // better alignment. Value *CallArgs[] = { DestCast, SrcCast, Size, - ConstantInt::get(Type::getInt32Ty(Context), 1) + ConstantInt::get(Type::getInt32Ty(Context), 1), + ConstantInt::get(Type::getInt1Ty(Context), 0) }; CallInst *TheMemCpy = - CallInst::Create(MemCpyFn, CallArgs, CallArgs+4, "", TheCall); + CallInst::Create(MemCpyFn, CallArgs, CallArgs+5, "", TheCall); // If we have a call graph, update it. if (CG) { diff --git a/lib/VMCore/AutoUpgrade.cpp b/lib/VMCore/AutoUpgrade.cpp index b9aa5c34675b..4d06b6668169 100644 --- a/lib/VMCore/AutoUpgrade.cpp +++ b/lib/VMCore/AutoUpgrade.cpp @@ -145,6 +145,54 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) { } break; + case 'm': { + // This upgrades the llvm.memcpy, llvm.memmove, and llvm.memset to the + // new format that allows overloading the pointer for different address + // space (e.g., llvm.memcpy.i16 => llvm.memcpy.p0i8.p0i8.i16) + const char* NewFnName = NULL; + if (Name.compare(5,8,"memcpy.i",8) == 0) { + if (Name[13] == '8') + NewFnName = "llvm.memcpy.p0i8.p0i8.i8"; + else if (Name.compare(13,2,"16") == 0) + NewFnName = "llvm.memcpy.p0i8.p0i8.i16"; + else if (Name.compare(13,2,"32") == 0) + NewFnName = "llvm.memcpy.p0i8.p0i8.i32"; + else if (Name.compare(13,2,"64") == 0) + NewFnName = "llvm.memcpy.p0i8.p0i8.i64"; + } else if (Name.compare(5,9,"memmove.i",9) == 0) { + if (Name[14] == '8') + NewFnName = "llvm.memmove.p0i8.p0i8.i8"; + else if (Name.compare(14,2,"16") == 0) + NewFnName = "llvm.memmove.p0i8.p0i8.i16"; + else if (Name.compare(14,2,"32") == 0) + NewFnName = "llvm.memmove.p0i8.p0i8.i32"; + else if (Name.compare(14,2,"64") == 0) + NewFnName = "llvm.memmove.p0i8.p0i8.i64"; + } + else if (Name.compare(5,8,"memset.i",8) == 0) { + if (Name[13] == '8') + NewFnName = "llvm.memset.p0i8.i8"; + else if (Name.compare(13,2,"16") == 0) + NewFnName = "llvm.memset.p0i8.i16"; + else if (Name.compare(13,2,"32") == 0) + NewFnName = "llvm.memset.p0i8.i32"; + else if (Name.compare(13,2,"64") == 0) + NewFnName = "llvm.memset.p0i8.i64"; + } + if (NewFnName) { + const FunctionType *FTy = F->getFunctionType(); + NewFn = cast<Function>(M->getOrInsertFunction(NewFnName, + FTy->getReturnType(), + FTy->getParamType(0), + FTy->getParamType(1), + FTy->getParamType(2), + FTy->getParamType(3), + Type::getInt1Ty(F->getContext()), + (Type *)0)); + return true; + } + break; + } case 'p': // This upgrades the llvm.part.select overloaded intrinsic names to only // use one type specifier in the name. We only care about the old format @@ -472,6 +520,28 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { CI->eraseFromParent(); } break; + case Intrinsic::memcpy: + case Intrinsic::memmove: + case Intrinsic::memset: { + // Add isVolatile + const llvm::Type *I1Ty = llvm::Type::getInt1Ty(CI->getContext()); + Value *Operands[5] = { CI->getOperand(1), CI->getOperand(2), + CI->getOperand(3), CI->getOperand(4), + llvm::ConstantInt::get(I1Ty, 0) }; + CallInst *NewCI = CallInst::Create(NewFn, Operands, Operands+5, + CI->getName(), CI); + NewCI->setTailCall(CI->isTailCall()); + NewCI->setCallingConv(CI->getCallingConv()); + // Handle any uses of the old CallInst. + if (!CI->use_empty()) + // Replace all uses of the old call with the new cast which has the + // correct type. + CI->replaceAllUsesWith(NewCI); + + // Clean up the old call now that it has been completely upgraded. + CI->eraseFromParent(); + break; + } } } diff --git a/lib/VMCore/LLVMContext.cpp b/lib/VMCore/LLVMContext.cpp index 2a870ec6cfd9..3244f2842c4f 100644 --- a/lib/VMCore/LLVMContext.cpp +++ b/lib/VMCore/LLVMContext.cpp @@ -33,6 +33,23 @@ LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) { } LLVMContext::~LLVMContext() { delete pImpl; } +void LLVMContext::setInlineAsmDiagnosticHandler(void *DiagHandler, + void *DiagContext) { + pImpl->InlineAsmDiagHandler = DiagHandler; + pImpl->InlineAsmDiagContext = DiagContext; +} + +/// getInlineAsmDiagnosticHandler - Return the diagnostic handler set by +/// setInlineAsmDiagnosticHandler. +void *LLVMContext::getInlineAsmDiagnosticHandler() const { + return pImpl->InlineAsmDiagHandler; +} + +/// getInlineAsmDiagnosticContext - Return the diagnostic context set by +/// setInlineAsmDiagnosticHandler. +void *LLVMContext::getInlineAsmDiagnosticContext() const { + return pImpl->InlineAsmDiagContext; +} #ifndef NDEBUG /// isValidName - Return true if Name is a valid custom metadata handler name. @@ -73,5 +90,3 @@ void LLVMContext::getMDKindNames(SmallVectorImpl<StringRef> &Names) const { // MD Handlers are numbered from 1. Names[I->second] = I->first(); } - - diff --git a/lib/VMCore/LLVMContextImpl.cpp b/lib/VMCore/LLVMContextImpl.cpp index b4553ddc1b9f..e71157f44020 100644 --- a/lib/VMCore/LLVMContextImpl.cpp +++ b/lib/VMCore/LLVMContextImpl.cpp @@ -30,6 +30,9 @@ LLVMContextImpl::LLVMContextImpl(LLVMContext &C) Int32Ty(C, 32), Int64Ty(C, 64), AlwaysOpaqueTy(new OpaqueType(C)) { + InlineAsmDiagHandler = 0; + InlineAsmDiagContext = 0; + // Make sure the AlwaysOpaqueTy stays alive as long as the Context. AlwaysOpaqueTy->addRef(); OpaqueTypes.insert(AlwaysOpaqueTy); diff --git a/lib/VMCore/LLVMContextImpl.h b/lib/VMCore/LLVMContextImpl.h index d4ebf8044d8b..4876f5d5075a 100644 --- a/lib/VMCore/LLVMContextImpl.h +++ b/lib/VMCore/LLVMContextImpl.h @@ -115,6 +115,8 @@ public: class LLVMContextImpl { public: + void *InlineAsmDiagHandler, *InlineAsmDiagContext; + typedef DenseMap<DenseMapAPIntKeyInfo::KeyTy, ConstantInt*, DenseMapAPIntKeyInfo> IntMapTy; IntMapTy IntConstants; diff --git a/lib/VMCore/Pass.cpp b/lib/VMCore/Pass.cpp index 609375012480..6b941f34996e 100644 --- a/lib/VMCore/Pass.cpp +++ b/lib/VMCore/Pass.cpp @@ -294,13 +294,8 @@ public: static std::vector<PassRegistrationListener*> *Listeners = 0; static sys::SmartMutex<true> ListenersLock; -// FIXME: This should use ManagedStatic to manage the pass registrar. -// Unfortunately, we can't do this, because passes are registered with static -// ctors, and having llvm_shutdown clear this map prevents successful -// ressurection after llvm_shutdown is run. +static PassRegistrar *PassRegistrarObj = 0; static PassRegistrar *getPassRegistrar() { - static PassRegistrar *PassRegistrarObj = 0; - // Use double-checked locking to safely initialize the registrar when // we're running in multithreaded mode. PassRegistrar* tmp = PassRegistrarObj; @@ -323,6 +318,19 @@ static PassRegistrar *getPassRegistrar() { return PassRegistrarObj; } +// FIXME: We use ManagedCleanup to erase the pass registrar on shutdown. +// Unfortunately, passes are registered with static ctors, and having +// llvm_shutdown clear this map prevents successful ressurection after +// llvm_shutdown is run. Ideally we should find a solution so that we don't +// leak the map, AND can still resurrect after shutdown. +void cleanupPassRegistrar(void*) { + if (PassRegistrarObj) { + delete PassRegistrarObj; + PassRegistrarObj = 0; + } +} +ManagedCleanup<&cleanupPassRegistrar> registrarCleanup; + // getPassInfo - Return the PassInfo data structure that corresponds to this // pass... const PassInfo *Pass::getPassInfo() const { diff --git a/test/Analysis/BasicAA/modref.ll b/test/Analysis/BasicAA/modref.ll index 4a616364b00b..a2aabf135f6f 100644 --- a/test/Analysis/BasicAA/modref.ll +++ b/test/Analysis/BasicAA/modref.ll @@ -103,7 +103,7 @@ define i32 @test4(i8* %P) { ret i32 %sub ; CHECK: @test4 ; CHECK: load i32* @G -; CHECK: memset.i32 +; CHECK: memset.p0i8.i32 ; CHECK-NOT: load ; CHECK: sub i32 %tmp, %tmp } @@ -118,7 +118,7 @@ define i32 @test5(i8* %P, i32 %Len) { ret i32 %sub ; CHECK: @test5 ; CHECK: load i32* @G -; CHECK: memcpy.i32 +; CHECK: memcpy.p0i8.p0i8.i32 ; CHECK-NOT: load ; CHECK: sub i32 %tmp, %tmp } diff --git a/test/Bitcode/memcpy.ll b/test/Bitcode/memcpy.ll index 85b95fe57263..b6573b5f6216 100644 --- a/test/Bitcode/memcpy.ll +++ b/test/Bitcode/memcpy.ll @@ -8,6 +8,7 @@ entry: tail call void @llvm.memcpy.i64( i8* %tmp.1, i8* %tmp.3, i64 100000, i32 1 ) tail call void @llvm.memset.i32( i8* %tmp.3, i8 14, i32 10000, i32 0 ) tail call void @llvm.memmove.i32( i8* %tmp.1, i8* %tmp.3, i32 123124, i32 1 ) + tail call void @llvm.memmove.i64( i8* %tmp.1, i8* %tmp.3, i64 123124, i32 1 ) ret void } @@ -19,3 +20,4 @@ declare void @llvm.memset.i32(i8*, i8, i32, i32) declare void @llvm.memmove.i32(i8*, i8*, i32, i32) +declare void @llvm.memmove.i64(i8*, i8*, i32, i32) diff --git a/test/CodeGen/X86/memcpy.ll b/test/CodeGen/X86/memcpy.ll index 24530cd27e4b..5a3ae77caae1 100644 --- a/test/CodeGen/X86/memcpy.ll +++ b/test/CodeGen/X86/memcpy.ll @@ -2,13 +2,13 @@ declare void @llvm.memcpy.i64(i8*, i8*, i64, i32) -define i8* @my_memcpy(i8* %a, i8* %b, i64 %n) { +define i8* @my_memcpy(i8* %a, i8* %b, i64 %n) nounwind { entry: tail call void @llvm.memcpy.i64( i8* %a, i8* %b, i64 %n, i32 1 ) ret i8* %a } -define i8* @my_memcpy2(i64* %a, i64* %b, i64 %n) { +define i8* @my_memcpy2(i64* %a, i64* %b, i64 %n) nounwind { entry: %tmp14 = bitcast i64* %a to i8* %tmp25 = bitcast i64* %b to i8* diff --git a/test/CodeGen/X86/personality.ll b/test/CodeGen/X86/personality.ll index 5acf04cc06c1..6789bb0c0fbe 100644 --- a/test/CodeGen/X86/personality.ll +++ b/test/CodeGen/X86/personality.ll @@ -38,10 +38,10 @@ declare void @__gxx_personality_v0() declare void @__cxa_end_catch() -; X64: Leh_frame_common_begin: +; X64: Leh_frame_common_begin0: ; X64: .long ___gxx_personality_v0@GOTPCREL+4 -; X32: Leh_frame_common_begin: +; X32: Leh_frame_common_begin0: ; X32: .long L___gxx_personality_v0$non_lazy_ptr- ; .... diff --git a/test/CodeGen/X86/unreachable-loop-sinking.ll b/test/CodeGen/X86/unreachable-loop-sinking.ll new file mode 100644 index 000000000000..35f69175a86a --- /dev/null +++ b/test/CodeGen/X86/unreachable-loop-sinking.ll @@ -0,0 +1,30 @@ +; RUN: llc < %s +; PR6777 + +; MachineSink shouldn't try to sink code in unreachable blocks, as it's +; not worthwhile, and there are corner cases which it doesn't handle. + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" +target triple = "x86_64-unknown-linux-gnu" + +define double @fn1(i8* %arg, i64 %arg1) { +Entry: + br i1 undef, label %Body, label %Exit + +Exit: ; preds = %Brancher7, %Entry + ret double undef + +Body: ; preds = %Entry + br i1 false, label %Brancher7, label %Body3 + +Body3: ; preds = %Body6, %Body3, %Body + br label %Body3 + +Body6: ; preds = %Brancher7 + %tmp = fcmp oeq double 0xC04FBB2E40000000, undef ; <i1> [#uses=1] + br i1 %tmp, label %Body3, label %Brancher7 + +Brancher7: ; preds = %Body6, %Body + %tmp2 = icmp ult i32 undef, 10 ; <i1> [#uses=1] + br i1 %tmp2, label %Body6, label %Exit +} diff --git a/test/MC/Disassembler/arm-tests.txt b/test/MC/Disassembler/arm-tests.txt index 094a2d737246..81261c59028d 100644 --- a/test/MC/Disassembler/arm-tests.txt +++ b/test/MC/Disassembler/arm-tests.txt @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 | FileCheck %s +# XFAIL: * # CHECK: b #0 0xfe 0xff 0xff 0xea diff --git a/test/MC/Disassembler/neon-tests.txt b/test/MC/Disassembler/neon-tests.txt index 5d37b8c6416d..25099c0a39b8 100644 --- a/test/MC/Disassembler/neon-tests.txt +++ b/test/MC/Disassembler/neon-tests.txt @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 | FileCheck %s +# XFAIL: * # CHECK: vbif q15, q7, q0 0x50 0xe1 0x7e 0xf3 diff --git a/test/MC/Disassembler/thumb-tests.txt b/test/MC/Disassembler/thumb-tests.txt index e7e6385818ef..343e6c94b19f 100644 --- a/test/MC/Disassembler/thumb-tests.txt +++ b/test/MC/Disassembler/thumb-tests.txt @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 | FileCheck %s +# XFAIL: * # CHECK: add r5, sp, #68 0x11 0xad diff --git a/test/Transforms/InstCombine/memset_chk.ll b/test/Transforms/InstCombine/memset_chk.ll index 5a4e6d9e84f1..58ecda582fd1 100644 --- a/test/Transforms/InstCombine/memset_chk.ll +++ b/test/Transforms/InstCombine/memset_chk.ll @@ -7,7 +7,7 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3 define i32 @t() nounwind ssp { ; CHECK: @t -; CHECK: @llvm.memset.i64 +; CHECK: @llvm.memset.p0i8.i64 entry: %0 = alloca %struct.data, align 8 ; <%struct.data*> [#uses=1] %1 = bitcast %struct.data* %0 to i8* ; <i8*> [#uses=1] diff --git a/test/Transforms/InstCombine/objsize.ll b/test/Transforms/InstCombine/objsize.ll index f8b2ffca01ed..d74312d2e7e9 100644 --- a/test/Transforms/InstCombine/objsize.ll +++ b/test/Transforms/InstCombine/objsize.ll @@ -113,7 +113,7 @@ entry: %1 = bitcast %struct.data* %0 to i8* %2 = call i64 @llvm.objectsize.i64(i8* %1, i1 false) nounwind ; CHECK-NOT: @llvm.objectsize -; CHECK: @llvm.memset.i64(i8* %1, i8 0, i64 1824, i32 8) +; CHECK: @llvm.memset.p0i8.i64(i8* %1, i8 0, i64 1824, i32 8, i1 false) %3 = call i8* @__memset_chk(i8* %1, i32 0, i64 1824, i64 %2) nounwind ret i32 0 } @@ -128,7 +128,7 @@ entry: %1 = tail call i32 @llvm.objectsize.i32(i8* %0, i1 false) %2 = load i8** @s, align 8 ; CHECK-NOT: @llvm.objectsize -; CHECK: @llvm.memcpy.i32(i8* %0, i8* %1, i32 10, i32 1) +; CHECK: @llvm.memcpy.p0i8.p0i8.i32(i8* %0, i8* %1, i32 10, i32 1, i1 false) %3 = tail call i8* @__memcpy_chk(i8* %0, i8* %2, i32 10, i32 %1) nounwind ret void } diff --git a/test/Transforms/MemCpyOpt/align.ll b/test/Transforms/MemCpyOpt/align.ll index 47df380b2da7..b0ae5f413a5d 100644 --- a/test/Transforms/MemCpyOpt/align.ll +++ b/test/Transforms/MemCpyOpt/align.ll @@ -4,7 +4,7 @@ target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f3 ; The resulting memset is only 4-byte aligned, despite containing ; a 16-byte alignmed store in the middle. -; CHECK: call void @llvm.memset.i64(i8* %a01, i8 0, i64 16, i32 4) +; CHECK: call void @llvm.memset.p0i8.i64(i8* %a01, i8 0, i64 16, i32 4, i1 false) define void @foo(i32* %p) { %a0 = getelementptr i32* %p, i64 0 diff --git a/test/Transforms/SimplifyLibCalls/StrCpy.ll b/test/Transforms/SimplifyLibCalls/StrCpy.ll index c3cc58ce3806..83406ff8f868 100644 --- a/test/Transforms/SimplifyLibCalls/StrCpy.ll +++ b/test/Transforms/SimplifyLibCalls/StrCpy.ll @@ -21,7 +21,7 @@ define i32 @t1() { %arg1 = getelementptr [1024 x i8]* %target, i32 0, i32 0 %arg2 = getelementptr [6 x i8]* @hello, i32 0, i32 0 %rslt1 = call i8* @strcpy( i8* %arg1, i8* %arg2 ) -; CHECK: @llvm.memcpy.i32 +; CHECK: @llvm.memcpy.p0i8.p0i8.i32 ret i32 0 } diff --git a/test/Verifier/2006-12-12-IntrinsicDefine.ll b/test/Verifier/2006-12-12-IntrinsicDefine.ll index b63ae65aa2e7..8d09b512066e 100644 --- a/test/Verifier/2006-12-12-IntrinsicDefine.ll +++ b/test/Verifier/2006-12-12-IntrinsicDefine.ll @@ -1,7 +1,7 @@ ; RUN: not llvm-as < %s |& grep {llvm intrinsics cannot be defined} ; PR1047 -define void @llvm.memcpy.i32(i8*, i8*, i32, i32) { +define void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i32, i1) { entry: ret void } diff --git a/tools/edis/EDDisassembler.cpp b/tools/edis/EDDisassembler.cpp index f2b2f9157754..8729b4998fda 100644 --- a/tools/edis/EDDisassembler.cpp +++ b/tools/edis/EDDisassembler.cpp @@ -195,10 +195,7 @@ EDDisassembler::EDDisassembler(CPUKey &key) : InstString.reset(new std::string); InstStream.reset(new raw_string_ostream(*InstString)); - - InstPrinter.reset(Tgt->createMCInstPrinter(syntaxVariant, - *AsmInfo, - *InstStream)); + InstPrinter.reset(Tgt->createMCInstPrinter(syntaxVariant, *AsmInfo)); if (!InstPrinter) return; @@ -314,11 +311,10 @@ bool EDDisassembler::registerIsProgramCounter(unsigned registerID) { return (programCounters.find(registerID) != programCounters.end()); } -int EDDisassembler::printInst(std::string& str, - MCInst& inst) { +int EDDisassembler::printInst(std::string &str, MCInst &inst) { PrinterMutex.acquire(); - InstPrinter->printInst(&inst); + InstPrinter->printInst(&inst, *InstStream); InstStream->flush(); str = *InstString; InstString->clear(); diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index aa977a7032c4..dccfb26e7455 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -214,6 +214,7 @@ int main(int argc, char **argv) { // Initialize targets first, so that --version shows registered targets. InitializeAllTargets(); InitializeAllAsmPrinters(); + InitializeAllAsmParsers(); cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n"); diff --git a/tools/llvm-mc/Disassembler.cpp b/tools/llvm-mc/Disassembler.cpp index 0caf539ac959..9fe07909284c 100644 --- a/tools/llvm-mc/Disassembler.cpp +++ b/tools/llvm-mc/Disassembler.cpp @@ -48,8 +48,8 @@ public: } static bool PrintInsts(const MCDisassembler &DisAsm, - MCInstPrinter &Printer, const ByteArrayTy &Bytes, - SourceMgr &SM) { + MCInstPrinter &Printer, const ByteArrayTy &Bytes, + SourceMgr &SM) { // Wrap the vector in a MemoryObject. VectorMemoryObject memoryObject(Bytes); @@ -62,7 +62,7 @@ static bool PrintInsts(const MCDisassembler &DisAsm, if (DisAsm.getInstruction(Inst, Size, memoryObject, Index, /*REMOVE*/ nulls())) { - Printer.printInst(&Inst); + Printer.printInst(&Inst, outs()); outs() << "\n"; } else { @@ -92,7 +92,7 @@ int Disassembler::disassemble(const Target &T, const std::string &Triple, return -1; } - OwningPtr<MCInstPrinter> IP(T.createMCInstPrinter(0, *AsmInfo, outs())); + OwningPtr<MCInstPrinter> IP(T.createMCInstPrinter(0, *AsmInfo)); if (!IP) { errs() << "error: no instruction printer for target " << Triple << '\n'; return -1; diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp index 6dce5cc96c74..c6657f5d3e74 100644 --- a/tools/llvm-mc/llvm-mc.cpp +++ b/tools/llvm-mc/llvm-mc.cpp @@ -18,6 +18,13 @@ #include "llvm/MC/MCInstPrinter.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCParser/AsmParser.h" +#include "llvm/Target/TargetAsmBackend.h" +#include "llvm/Target/TargetAsmParser.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Target/TargetMachine.h" // FIXME. +#include "llvm/Target/TargetSelect.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FormattedStream.h" @@ -28,13 +35,6 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/System/Host.h" #include "llvm/System/Signals.h" -#include "llvm/Target/TargetAsmBackend.h" -#include "llvm/Target/TargetAsmParser.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetRegistry.h" -#include "llvm/Target/TargetMachine.h" // FIXME. -#include "llvm/Target/TargetSelect.h" -#include "llvm/MC/MCParser/AsmParser.h" #include "Disassembler.h" using namespace llvm; @@ -158,7 +158,7 @@ static int AsLexInput(const char *ProgName) { if (!TheTarget) return 1; - llvm::OwningPtr<MCAsmInfo> MAI((MCAsmInfo*) TheTarget->createAsmInfo(TripleName)); + llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createAsmInfo(TripleName)); assert(MAI && "Unable to create target asm info!"); AsmLexer Lexer(*MAI); @@ -266,7 +266,7 @@ static int AssembleInput(const char *ProgName) { SrcMgr.setIncludeDirs(IncludeDirs); - llvm::OwningPtr<MCAsmInfo> MAI((MCAsmInfo*) TheTarget->createAsmInfo(TripleName)); + llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createAsmInfo(TripleName)); assert(MAI && "Unable to create target asm info!"); MCContext Ctx(*MAI); @@ -290,7 +290,7 @@ static int AssembleInput(const char *ProgName) { if (FileType == OFT_AssemblyFile) { MCInstPrinter *IP = - TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI, *Out); + TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI); if (ShowEncoding) CE.reset(TheTarget->createCodeEmitter(*TM, Ctx)); Str.reset(createAsmStreamer(Ctx, *Out,TM->getTargetData()->isLittleEndian(), diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp index 08576abac456..b269e7823758 100644 --- a/tools/lto/LTOModule.cpp +++ b/tools/lto/LTOModule.cpp @@ -101,13 +101,13 @@ LTOModule* LTOModule::makeLTOModule(const char* path, /// Also if next byte is on a different page, don't assume it is readable. MemoryBuffer* LTOModule::makeBuffer(const void* mem, size_t length) { - const char* startPtr = (char*)mem; - const char* endPtr = startPtr+length; - if ((((uintptr_t)endPtr & (sys::Process::GetPageSize()-1)) == 0) - || (*endPtr != 0)) - return MemoryBuffer::getMemBufferCopy(startPtr, endPtr); - else - return MemoryBuffer::getMemBuffer(startPtr, endPtr); + const char *startPtr = (char*)mem; + const char *endPtr = startPtr+length; + if (((uintptr_t)endPtr & (sys::Process::GetPageSize()-1)) == 0 || + *endPtr != 0) + return MemoryBuffer::getMemBufferCopy(StringRef(startPtr, length)); + + return MemoryBuffer::getMemBuffer(StringRef(startPtr, length)); } diff --git a/unittests/ExecutionEngine/JIT/JITTest.cpp b/unittests/ExecutionEngine/JIT/JITTest.cpp index b85f724353c3..8f0582d3e8de 100644 --- a/unittests/ExecutionEngine/JIT/JITTest.cpp +++ b/unittests/ExecutionEngine/JIT/JITTest.cpp @@ -701,9 +701,7 @@ ExecutionEngine *getJITFromBitcode( LLVMContext &Context, const std::string &Bitcode, Module *&M) { // c_str() is null-terminated like MemoryBuffer::getMemBuffer requires. MemoryBuffer *BitcodeBuffer = - MemoryBuffer::getMemBuffer(Bitcode.c_str(), - Bitcode.c_str() + Bitcode.size(), - "Bitcode for test"); + MemoryBuffer::getMemBuffer(Bitcode, "Bitcode for test"); std::string errMsg; M = getLazyBitcodeModule(BitcodeBuffer, Context, &errMsg); if (M == NULL) { diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp index c6a139275899..e7cd713ce601 100644 --- a/utils/FileCheck/FileCheck.cpp +++ b/utils/FileCheck/FileCheck.cpp @@ -441,7 +441,7 @@ struct CheckString { /// CanonicalizeInputFile - Remove duplicate horizontal space from the specified /// memory buffer, free it, and return a new one. static MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB) { - SmallVector<char, 16> NewFile; + SmallString<128> NewFile; NewFile.reserve(MB->getBufferSize()); for (const char *Ptr = MB->getBufferStart(), *End = MB->getBufferEnd(); @@ -461,9 +461,7 @@ static MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB) { // Free the old buffer and return a new one. MemoryBuffer *MB2 = - MemoryBuffer::getMemBufferCopy(NewFile.data(), - NewFile.data() + NewFile.size(), - MB->getBufferIdentifier()); + MemoryBuffer::getMemBufferCopy(NewFile.str(), MB->getBufferIdentifier()); delete MB; return MB2; diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index ab1e239a95f2..1e95467a3b2c 100644 --- a/utils/TableGen/AsmWriterEmitter.cpp +++ b/utils/TableGen/AsmWriterEmitter.cpp @@ -248,7 +248,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { "/// printInstruction - This method is automatically generated by tablegen\n" "/// from the instruction set description.\n" "void " << Target.getName() << ClassName - << "::printInstruction(const MachineInstr *MI) {\n"; + << "::printInstruction(const MachineInstr *MI, raw_ostream &O) {\n"; std::vector<AsmWriterInst> Instructions; diff --git a/utils/TableGen/AsmWriterInst.cpp b/utils/TableGen/AsmWriterInst.cpp index 508e4530d09c..b2228b037ddd 100644 --- a/utils/TableGen/AsmWriterInst.cpp +++ b/utils/TableGen/AsmWriterInst.cpp @@ -38,6 +38,7 @@ std::string AsmWriterOperand::getCode() const { std::string Result = Str + "(MI"; if (MIOpNo != ~0U) Result += ", " + utostr(MIOpNo); + Result += ", O"; if (!MiModifier.empty()) Result += ", \"" + MiModifier + '"'; return Result + "); "; diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index 9bc545928d9b..006a2a1b0933 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -288,19 +288,19 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, if (Inst.isAsCheapAsAMove) OS << "|(1<<TID::CheapAsAMove)"; if (Inst.hasExtraSrcRegAllocReq) OS << "|(1<<TID::ExtraSrcRegAllocReq)"; if (Inst.hasExtraDefRegAllocReq) OS << "|(1<<TID::ExtraDefRegAllocReq)"; - OS << ", 0"; // Emit all of the target-specific flags... - ListInit *LI = InstrInfo->getValueAsListInit("TSFlagsFields"); - ListInit *Shift = InstrInfo->getValueAsListInit("TSFlagsShifts"); - if (LI->getSize() != Shift->getSize()) - throw "Lengths of " + InstrInfo->getName() + - ":(TargetInfoFields, TargetInfoPositions) must be equal!"; - - for (unsigned i = 0, e = LI->getSize(); i != e; ++i) - emitShiftedValue(Inst.TheDef, dynamic_cast<StringInit*>(LI->getElement(i)), - dynamic_cast<IntInit*>(Shift->getElement(i)), OS); - + BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags"); + if (!TSF) throw "no TSFlags?"; + uint64_t Value = 0; + for (unsigned i = 0, e = TSF->getNumBits(); i != e; ++i) { + if (BitInit *Bit = dynamic_cast<BitInit*>(TSF->getBit(i))) + Value |= uint64_t(Bit->getValue()) << i; + else + throw "Invalid TSFlags bit in " + Inst.TheDef->getName(); + } + OS << ", 0x"; + OS.write_hex(Value); OS << ", "; // Emit the implicit uses and defs lists... @@ -328,66 +328,6 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, OS << "0"; else OS << "OperandInfo" << OpInfo.find(OperandInfo)->second; - - OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n"; -} - - -void InstrInfoEmitter::emitShiftedValue(Record *R, StringInit *Val, - IntInit *ShiftInt, raw_ostream &OS) { - if (Val == 0 || ShiftInt == 0) - throw std::string("Illegal value or shift amount in TargetInfo*!"); - RecordVal *RV = R->getDottedValue(Val->getValue()); - int Shift = ShiftInt->getValue(); - - if (RV == 0 || RV->getValue() == 0) { - // This isn't an error if this is a builtin instruction. - if (R->getName() != "PHI" && - R->getName() != "INLINEASM" && - R->getName() != "DBG_LABEL" && - R->getName() != "EH_LABEL" && - R->getName() != "GC_LABEL" && - R->getName() != "KILL" && - R->getName() != "EXTRACT_SUBREG" && - R->getName() != "INSERT_SUBREG" && - R->getName() != "IMPLICIT_DEF" && - R->getName() != "SUBREG_TO_REG" && - R->getName() != "COPY_TO_REGCLASS" && - R->getName() != "DBG_VALUE") - throw R->getName() + " doesn't have a field named '" + - Val->getValue() + "'!"; - return; - } - Init *Value = RV->getValue(); - if (BitInit *BI = dynamic_cast<BitInit*>(Value)) { - if (BI->getValue()) OS << "|(1<<" << Shift << ")"; - return; - } else if (BitsInit *BI = dynamic_cast<BitsInit*>(Value)) { - // Convert the Bits to an integer to print... - Init *I = BI->convertInitializerTo(new IntRecTy()); - if (I) - if (IntInit *II = dynamic_cast<IntInit*>(I)) { - if (II->getValue()) { - if (Shift) - OS << "|(" << II->getValue() << "<<" << Shift << ")"; - else - OS << "|" << II->getValue(); - } - return; - } - - } else if (IntInit *II = dynamic_cast<IntInit*>(Value)) { - if (II->getValue()) { - if (Shift) - OS << "|(" << II->getValue() << "<<" << Shift << ")"; - else - OS << II->getValue(); - } - return; - } - - errs() << "Unhandled initializer: " << *Val << "\n"; - throw "In record '" + R->getName() + "' for TSFlag emission."; + OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n"; } - diff --git a/utils/TableGen/InstrInfoEmitter.h b/utils/TableGen/InstrInfoEmitter.h index 657939e46388..abb1c6bc188c 100644 --- a/utils/TableGen/InstrInfoEmitter.h +++ b/utils/TableGen/InstrInfoEmitter.h @@ -47,8 +47,6 @@ private: std::map<Record*, unsigned> &BM, const OperandInfoMapTy &OpInfo, raw_ostream &OS); - void emitShiftedValue(Record *R, StringInit *Val, IntInit *Shift, - raw_ostream &OS); // Itinerary information. void GatherItinClasses(); diff --git a/utils/TableGen/Record.cpp b/utils/TableGen/Record.cpp index 55c998926c0a..4f9f6045c14c 100644 --- a/utils/TableGen/Record.cpp +++ b/utils/TableGen/Record.cpp @@ -1307,17 +1307,6 @@ void Record::resolveReferencesTo(const RecordVal *RV) { } } -RecordVal *Record::getDottedValue(StringRef Name) { - size_t pos = Name.find('.'); - if (pos == StringRef::npos) - return getValue(Name); - RecordVal *RV = getValue(Name.substr(0, pos)); - if (!RV) return 0; - DefInit *DI = dynamic_cast<DefInit*>(RV->getValue()); - if (!DI) return 0; - return DI->getDef()->getDottedValue(Name.substr(pos+1)); -} - void Record::dump() const { errs() << *this; } raw_ostream &llvm::operator<<(raw_ostream &OS, const Record &R) { diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h index 41373c799a0d..55c1a80f9b6a 100644 --- a/utils/TableGen/Record.h +++ b/utils/TableGen/Record.h @@ -1262,9 +1262,6 @@ public: return 0; } - // Like getValue, but allow dotting into members: X.Y - RecordVal *getDottedValue(StringRef Name); - void addTemplateArg(StringRef Name) { assert(!isTemplateArg(Name) && "Template arg already defined!"); TemplateArgs.push_back(Name); |