First cut at assembly output
authorChris Lattner <sabre@nondot.org>
Wed, 19 Sep 2001 13:47:27 +0000 (13:47 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 19 Sep 2001 13:47:27 +0000 (13:47 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@636 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/SparcV9/SparcV9AsmPrinter.cpp [new file with mode: 0644]

diff --git a/lib/Target/SparcV9/SparcV9AsmPrinter.cpp b/lib/Target/SparcV9/SparcV9AsmPrinter.cpp
new file mode 100644 (file)
index 0000000..9014d21
--- /dev/null
@@ -0,0 +1,213 @@
+//===-- EmitAssembly.cpp - Emit Sparc Specific .s File ---------------------==//
+//
+// This file implements all of the stuff neccesary to output a .s file from
+// LLVM.  The code in this file assumes that the specified module has already
+// been compiled into the internal data structures of the Module.
+//
+// The entry point of this file is the UltraSparc::emitAssembly method.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SparcInternals.h"
+#include "llvm/Analysis/SlotCalculator.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/BasicBlock.h"
+#include "llvm/Method.h"
+#include "llvm/Module.h"
+#include "llvm/Support/StringExtras.h"
+
+namespace {
+
+class SparcAsmPrinter {
+  ostream &Out;
+  SlotCalculator Table;
+  UltraSparc &Target;
+
+  enum Sections {
+    Unknown,
+    Text,
+    Data,
+    ReadOnly,
+  } CurSection;
+public:
+  inline SparcAsmPrinter(ostream &o, const Module *M, UltraSparc &t)
+    : Out(o), Table(SlotCalculator(M, true)), Target(t), CurSection(Unknown) {
+    emitModule(M);
+  }
+
+private :
+  void emitModule(const Module *M);
+  /*
+  void processSymbolTable(const SymbolTable &ST);
+  void processConstant(const ConstPoolVal *CPV);
+  void processGlobal(const GlobalVariable *GV);
+  */
+  void emitMethod(const Method *M);
+  //void processMethodArgument(const MethodArgument *MA);
+  void emitBasicBlock(const BasicBlock *BB);
+  void emitMachineInst(const MachineInstr *MI);
+
+  
+  //void writeOperand(const Value *Op, bool PrintType, bool PrintName = true);
+
+
+  // enterSection - Use this method to enter a different section of the output
+  // executable.  This is used to only output neccesary section transitions.
+  //
+  void enterSection(enum Sections S) {
+    if (S == CurSection) return;        // Only switch section if neccesary
+    CurSection = S;
+
+    Out << ".section \".";
+    switch (S) {
+    default: assert(0 && "Bad section name!");
+    case Text:     Out << "text"; break;
+    case Data:     Out << "data"; break;
+    case ReadOnly: Out << "rodata"; break;
+    }
+    Out << "\"\n";
+  }
+
+  // getID - Return a valid identifier for the specified value.  Base it on
+  // the name of the identifier if possible, use a numbered value based on
+  // prefix otherwise.  FPrefix is always prepended to the output identifier.
+  //
+  string getID(const Value *V, const char *Prefix, const char *FPrefix = 0) {
+    string FP(FPrefix ? FPrefix : "");  // "Forced prefix"
+    if (V->hasName()) {
+      return FP + V->getName();  // TODO: Escape name if needed
+    } else {
+      assert(Table.getValSlot(V) != -1 && "Value not in value table!");
+      return FP + string(Prefix) + itostr(Table.getValSlot(V));
+    }
+  }
+
+  // getID Wrappers - Ensure consistent usage...
+  string getID(const Method *M) { return getID(M, "anon_method$"); }
+  string getID(const BasicBlock *BB) {
+    return getID(BB, "LL", (".L$"+getID(BB->getParent())).c_str());
+  }
+
+  unsigned getOperandMask(unsigned Opcode) {
+    switch (Opcode) {
+    case SUBcc:   return 1 << 3;  // Remove CC argument
+    case BA:      return 1 << 0;  // Remove Arg #0, which is always null
+    default:      return 0;       // By default, don't hack operands...
+    }
+  }
+};
+
+
+void SparcAsmPrinter::emitMachineInst(const MachineInstr *MI) {
+  unsigned Opcode = MI->getOpCode();
+
+  if (TargetInstrDescriptors[Opcode].iclass & M_DUMMY_PHI_FLAG)
+    return;  // IGNORE PHI NODES
+
+  Out << "\t" << TargetInstrDescriptors[Opcode].opCodeString << "\t";
+
+  unsigned Mask = getOperandMask(Opcode);
+
+  bool NeedComma = false;
+  for(unsigned OpNum = 0; OpNum < MI->getNumOperands(); ++OpNum) {
+    if ((1 << OpNum) & Mask) continue;  // Ignore this operand?
+    
+    const MachineOperand &Op = MI->getOperand(OpNum);
+    if (NeedComma) Out << ", ";    // Handle comma outputing
+    NeedComma = true;
+
+    switch (Op.getOperandType()) {
+    case MachineOperand::MO_VirtualRegister:
+    case MachineOperand::MO_CCRegister:
+    case MachineOperand::MO_MachineRegister: {
+      int RegNum = (int)Op.getAllocatedRegNum();
+      
+      // ****this code is temporary till NULL Values are fixed
+      if (RegNum == 10000) {
+        Out << "<NULL VALUE>";
+        continue;
+      }
+      
+      Out << "%" << Target.getRegInfo().getUnifiedRegName(RegNum);
+      break;
+    }
+      
+    case MachineOperand::MO_PCRelativeDisp: {
+      const Value *Val = Op.getVRegValue();
+      if (!Val) {
+        Out << "\t<*NULL Value*>";
+      } else if (Val->isBasicBlock()) {
+        Out << getID(Val->castBasicBlockAsserting());
+      } else {
+        Out << "<unknown value=" << Val << ">";
+      }
+      break;
+    }
+
+    default:
+      Out << Op;      // use dump field
+      break;
+    }
+  }
+  Out << endl;
+}
+
+void SparcAsmPrinter::emitBasicBlock(const BasicBlock *BB) {
+  // Emit a label for the basic block
+  Out << getID(BB) << ":\n";
+
+  // Get the vector of machine instructions corresponding to this bb.
+  const MachineCodeForBasicBlock &MIs = BB->getMachineInstrVec();
+  MachineCodeForBasicBlock::const_iterator MII = MIs.begin(), MIE = MIs.end();
+
+  // Loop over all of the instructions in the basic block...
+  for (; MII != MIE; ++MII)
+    emitMachineInst(*MII);
+  Out << "\n";  // Seperate BB's with newlines
+}
+
+void SparcAsmPrinter::emitMethod(const Method *M) {
+  if (M->isExternal()) return;
+
+  // Make sure the slot table has information about this method...
+  Table.incorporateMethod(M);
+
+  string MethName = getID(M);
+  Out << "!****** Outputing Method: " << MethName << " ******\n";
+  enterSection(Text);
+  Out << "\t.align 4\n\t.global\t" << MethName << "\n";
+  Out << "\t.type\t" << MethName << ",#function\n";
+  Out << MethName << ":\n";
+
+  // Output code for all of the basic blocks in the method...
+  for (Method::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
+    emitBasicBlock(*I);
+
+  // Output a .size directive so the debugger knows the extents of the function
+  Out << ".EndOf$" << MethName << ":\n\t.size " << MethName << ", .EndOf$"
+      << MethName << "-" << MethName << endl;
+
+  // Put some spaces between the methods
+  Out << "\n\n";
+
+  // Forget all about M.
+  Table.purgeMethod();
+}
+
+
+void SparcAsmPrinter::emitModule(const Module *M) {
+  // TODO: Look for a filename annotation on M to emit a .file directive
+  for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
+    emitMethod(*I);
+}
+
+}  // End anonymous namespace
+
+//
+// emitAssembly - Output assembly language code (a .s file) for the specified
+// method. The specified method must have been compiled before this may be
+// used.
+//
+void UltraSparc::emitAssembly(const Module *M, ostream &Out) {
+  SparcAsmPrinter Print(Out, M, *this);
+}