--- /dev/null
+//===-- 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);
+}