Allow target intrinsics that return multiple values, i.e., struct types,
[oota-llvm.git] / lib / CodeGen / AsmPrinter / AsmPrinter.cpp
index 7b7a9a5a97ad3bee28ee96a8491f31f42436483c..e19631fb4251da8184c00f99cb8593938bc8086f 100644 (file)
 #include "llvm/CodeGen/MachineModuleInfo.h"
 #include "llvm/CodeGen/DwarfWriter.h"
 #include "llvm/Analysis/DebugInfo.h"
+#include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCStreamer.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/FormattedStream.h"
 #include "llvm/Support/Mangler.h"
-#include "llvm/Support/FormattedStream.h"
 #include "llvm/Target/TargetAsmInfo.h"
 #include "llvm/Target/TargetData.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"
@@ -48,6 +51,10 @@ AsmPrinter::AsmPrinter(formatted_raw_ostream &o, TargetMachine &tm,
                        const TargetAsmInfo *T, bool VDef)
   : MachineFunctionPass(&ID), FunctionNumber(0), O(o),
     TM(tm), TAI(T), TRI(tm.getRegisterInfo()),
+
+    OutContext(*new MCContext()),
+    OutStreamer(*createAsmStreamer(OutContext, O)),
+
     IsInTextSection(false), LastMI(0), LastFn(0), Counter(~0U),
     PrevDLT(0, ~0U, ~0U) {
   DW = 0; MMI = 0;
@@ -62,8 +69,16 @@ AsmPrinter::~AsmPrinter() {
   for (gcp_iterator I = GCMetadataPrinters.begin(),
                     E = GCMetadataPrinters.end(); I != E; ++I)
     delete I->second;
+  
+  delete &OutStreamer;
+  delete &OutContext;
+}
+
+const TargetLoweringObjectFile &AsmPrinter::getObjFileLowering() const {
+  return TM.getTargetLowering()->getObjFileLowering();
 }
 
+
 /// SwitchToTextSection - Switch to the specified text section of the executable
 /// if we are not already in it!
 ///
@@ -118,8 +133,8 @@ void AsmPrinter::SwitchToDataSection(const char *NewSection,
 
 /// SwitchToSection - Switch to the specified section of the executable if we
 /// are not already in it!
-void AsmPrinter::SwitchToSection(const Section* NS) {
-  const std::stringNewSection = NS->getName();
+void AsmPrinter::SwitchToSection(const MCSection *NS) {
+  const std::string &NewSection = NS->getName();
 
   // If we're already in this section, we're done.
   if (CurrentSection == NewSection) return;
@@ -136,16 +151,21 @@ void AsmPrinter::SwitchToSection(const Section* NS) {
     // If section is named we need to switch into it via special '.section'
     // directive and also append funky flags. Otherwise - section name is just
     // some magic assembler directive.
-    if (NS->isNamed())
+    if (NS->getKind().hasExplicitSection()) {
+      SmallString<32> FlagsStr;
+      
+      getObjFileLowering().getSectionFlagsAsString(NS->getKind(), FlagsStr);
+
       O << TAI->getSwitchToSectionDirective()
         << CurrentSection
-        << TAI->getSectionFlags(NS->getFlags());
-    else
+        << FlagsStr.c_str();
+    } else {
       O << CurrentSection;
+    }
     O << TAI->getDataSectionStartSuffix() << '\n';
   }
 
-  IsInTextSection = (NS->getFlags() & SectionFlags::Code);
+  IsInTextSection = NS->getKind().isText();
 }
 
 void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
@@ -154,6 +174,10 @@ void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
 }
 
 bool AsmPrinter::doInitialization(Module &M) {
+  // Initialize TargetLoweringObjectFile.
+  const_cast<TargetLoweringObjectFile&>(getObjFileLowering())
+    .Initialize(OutContext, TM);
+  
   Mang = new Mangler(M, TAI->getGlobalPrefix(), TAI->getPrivateGlobalPrefix(),
                      TAI->getLinkerPrivateGlobalPrefix());
   
@@ -228,9 +252,6 @@ bool AsmPrinter::doFinalization(Module &M) {
   }
 
   if (TAI->getSetDirective()) {
-    if (!M.alias_empty())
-      SwitchToSection(TAI->getTextSection());
-
     O << '\n';
     for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end();
          I != E; ++I) {
@@ -267,6 +288,8 @@ bool AsmPrinter::doFinalization(Module &M) {
 
   delete Mang; Mang = 0;
   DW = 0; MMI = 0;
+  
+  OutStreamer.Finish();
   return false;
 }
 
@@ -286,10 +309,10 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) {
 namespace {
   // SectionCPs - Keep track the alignment, constpool entries per Section.
   struct SectionCPs {
-    const Section *S;
+    const MCSection *S;
     unsigned Alignment;
     SmallVector<unsigned, 4> CPEs;
-    SectionCPs(const Section *s, unsigned a) : S(s), Alignment(a) {};
+    SectionCPs(const MCSection *s, unsigned a) : S(s), Alignment(a) {};
   };
 }
 
@@ -306,9 +329,28 @@ void AsmPrinter::EmitConstantPool(MachineConstantPool *MCP) {
   // the same section together to reduce amount of section switch statements.
   SmallVector<SectionCPs, 4> CPSections;
   for (unsigned i = 0, e = CP.size(); i != e; ++i) {
-    MachineConstantPoolEntry CPE = CP[i];
+    const MachineConstantPoolEntry &CPE = CP[i];
     unsigned Align = CPE.getAlignment();
-    const Section* S = TAI->SelectSectionForMachineConst(CPE.getType());
+    
+    SectionKind Kind;
+    switch (CPE.getRelocationInfo()) {
+    default: llvm_unreachable("Unknown section kind");
+    case 2: Kind = SectionKind::get(SectionKind::ReadOnlyWithRel, false); break;
+    case 1:
+      Kind = SectionKind::get(SectionKind::ReadOnlyWithRelLocal,false);
+      break;
+    case 0:
+    switch (TM.getTargetData()->getTypeAllocSize(CPE.getType())) {
+    case 4:  Kind = SectionKind::get(SectionKind::MergeableConst4,false); break;
+    case 8:  Kind = SectionKind::get(SectionKind::MergeableConst8,false); break;
+    case 16: Kind = SectionKind::get(SectionKind::MergeableConst16,false);break;
+    default: Kind = SectionKind::get(SectionKind::MergeableConst,false); break;
+    }
+    }
+
+    const MCSection *S =
+      getObjFileLowering().getSectionForMergeableConstant(Kind);
+    
     // The number of sections are small, just do a linear search from the
     // last section to the first.
     bool Found = false;
@@ -376,18 +418,21 @@ void AsmPrinter::EmitJumpTableInfo(MachineJumpTableInfo *MJTI,
   // the appropriate section.
   TargetLowering *LoweringInfo = TM.getTargetLowering();
 
-  const charJumpTableDataSection = TAI->getJumpTableDataSection();
+  const char *JumpTableDataSection = TAI->getJumpTableDataSection();
   const Function *F = MF.getFunction();
-  unsigned SectionFlags = TAI->SectionFlagsForGlobal(F);
+  
+  const MCSection *FuncSection =
+    getObjFileLowering().SectionForGlobal(F, Mang, TM);
+
   bool JTInDiffSection = false;
   if ((IsPic && !(LoweringInfo && LoweringInfo->usesGlobalOffsetTable())) ||
       !JumpTableDataSection ||
-      SectionFlags & SectionFlags::Linkonce) {
+      FuncSection->getKind().isWeak()) {
     // In PIC mode, we need to emit the jump table to the same section as the
     // function body itself, otherwise the label differences won't make sense.
     // We should also do if the section name is NULL or function is declared in
     // discardable section.
-    SwitchToSection(TAI->SectionForGlobal(F));
+    SwitchToSection(FuncSection);
   } else {
     SwitchToDataSection(JumpTableDataSection);
     JTInDiffSection = true;
@@ -472,7 +517,7 @@ void AsmPrinter::printPICJumpTableEntry(const MachineJumpTableInfo *MJTI,
 /// special global used by LLVM.  If so, emit it and return true, otherwise
 /// do nothing and return false.
 bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) {
-  if (GV->isName("llvm.used")) {
+  if (GV->getName() == "llvm.used") {
     if (TAI->getUsedDirective() != 0)    // No need to emit this at all.
       EmitLLVMUsedList(GV->getInitializer());
     return true;
@@ -519,7 +564,7 @@ void AsmPrinter::EmitLLVMUsedList(Constant *List) {
   for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
     const GlobalValue *GV =
       dyn_cast<GlobalValue>(InitList->getOperand(i)->stripPointerCasts());
-    if (GV && TAI->emitUsedDirectiveFor(GV, Mang)) {
+    if (GV && getObjFileLowering().shouldEmitUsedDirectiveFor(GV, Mang)) {
       O << Directive;
       EmitConstantValueOnly(InitList->getOperand(i));
       O << '\n';
@@ -802,8 +847,28 @@ void AsmPrinter::EmitAlignment(unsigned NumBits, const GlobalValue *GV,
   }
   O << '\n';
 }
-
     
+/// PadToColumn - This gets called every time a tab is emitted.  If
+/// column padding is turned on, we replace the tab with the
+/// appropriate amount of padding.  If not, we replace the tab with a
+/// space, except for the first operand so that initial operands are
+/// always lined up by tabs.
+void AsmPrinter::PadToColumn(unsigned Operand) const {
+  if (TAI->getOperandColumn(Operand) > 0) {
+    O.PadToColumn(TAI->getOperandColumn(Operand), 1);
+  }
+  else {
+    if (Operand == 1) {
+      // Emit the tab after the mnemonic.
+      O << '\t';
+    }
+    else {
+      // Replace the tab with a space.
+      O << ' ';
+    }
+  }
+}
+
 /// EmitZeros - Emit a block of zeros.
 ///
 void AsmPrinter::EmitZeros(uint64_t NumZeros, unsigned AddrSpace) const {
@@ -1589,7 +1654,7 @@ void AsmPrinter::printBasicBlockLabel(const MachineBasicBlock *MBB,
     O << ':';
   if (printComment && MBB->getBasicBlock())
     O << '\t' << TAI->getCommentString() << ' '
-      << MBB->getBasicBlock()->getNameStart();
+      << MBB->getBasicBlock()->getNameStr();
 }
 
 /// printPICJumpTableSetLabel - This method prints a set label for the
@@ -1707,23 +1772,47 @@ GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy *S) {
 /// EmitComments - Pretty-print comments for instructions
 void AsmPrinter::EmitComments(const MachineInstr &MI) const
 {
-  if (!MI.getDebugLoc().isUnknown()) {
-    DebugLocTuple DLT = MF->getDebugLocTuple(MI.getDebugLoc());
-
-    // Print source line info
-    O.PadToColumn(TAI->getCommentColumn(), 1);
-    O << TAI->getCommentString() << " SrcLine " << DLT.Line << ":" << DLT.Col;
+  if (VerboseAsm) {
+    if (!MI.getDebugLoc().isUnknown()) {
+      DebugLocTuple DLT = MF->getDebugLocTuple(MI.getDebugLoc());
+
+      // Print source line info
+      O.PadToColumn(TAI->getCommentColumn(), 1);
+      O << TAI->getCommentString() << " SrcLine ";
+      if (DLT.CompileUnit->hasInitializer()) {
+        Constant *Name = DLT.CompileUnit->getInitializer();
+        if (ConstantArray *NameString = dyn_cast<ConstantArray>(Name))
+          if (NameString->isString()) {
+            O << NameString->getAsString() << " ";
+          }
+      }
+      O << DLT.Line;
+      if (DLT.Col != 0) 
+        O << ":" << DLT.Col;
+    }
   }
 }
 
 /// EmitComments - Pretty-print comments for instructions
 void AsmPrinter::EmitComments(const MCInst &MI) const
 {
-  if (!MI.getDebugLoc().isUnknown()) {
-    DebugLocTuple DLT = MF->getDebugLocTuple(MI.getDebugLoc());
-
-    // Print source line info
-    O.PadToColumn(TAI->getCommentColumn(), 1);
-    O << TAI->getCommentString() << " SrcLine " << DLT.Line << ":" << DLT.Col;
+  if (VerboseAsm) {
+    if (!MI.getDebugLoc().isUnknown()) {
+      DebugLocTuple DLT = MF->getDebugLocTuple(MI.getDebugLoc());
+
+      // Print source line info
+      O.PadToColumn(TAI->getCommentColumn(), 1);
+      O << TAI->getCommentString() << " SrcLine ";
+      if (DLT.CompileUnit->hasInitializer()) {
+        Constant *Name = DLT.CompileUnit->getInitializer();
+        if (ConstantArray *NameString = dyn_cast<ConstantArray>(Name))
+          if (NameString->isString()) {
+            O << NameString->getAsString() << " ";
+          }
+      }
+      O << DLT.Line;
+      if (DLT.Col != 0) 
+        O << ":" << DLT.Col;
+    }
   }
 }