Make the symbol prologue/epilogue stuff redundant with MappingInfo, in
[oota-llvm.git] / lib / Target / SparcV9 / EmitBytecodeToAssembly.cpp
1 //===-- EmitBytecodeToAssembly.cpp - Emit bytecode to Sparc .s File --------==//
2 //
3 // This file implements the pass that writes LLVM bytecode as data to a sparc
4 // assembly file.  The bytecode gets assembled into a special bytecode section
5 // of the executable for use at runtime later.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "SparcInternals.h"
10 #include "llvm/Pass.h"
11 #include "llvm/Bytecode/Writer.h"
12 #include <iostream>
13
14 using std::ostream;
15
16 namespace {
17
18   // sparcasmbuf - stream buf for encoding output bytes as .byte directives for
19   // the sparc assembler.
20   //
21   class sparcasmbuf : public std::streambuf {
22     std::ostream &BaseStr;
23   public:
24     typedef char           char_type;
25     typedef int            int_type;
26     typedef std::streampos pos_type;
27     typedef std::streamoff off_type;
28     
29     sparcasmbuf(std::ostream &On) : BaseStr(On) {}
30
31     virtual int_type overflow(int_type C) {
32       if (C != EOF)
33         BaseStr << "\t.byte " << C << "\n"; // Output C;
34       return C;
35     }
36   };
37
38
39   // osparcasmstream - Define an ostream implementation that uses a sparcasmbuf
40   // as the underlying streambuf to write the data to.  This streambuf formats
41   // the output as .byte directives for sparc output.
42   //
43   class osparcasmstream : public std::ostream {
44     sparcasmbuf sb;
45   public:
46     typedef char           char_type;
47     typedef int            int_type;
48     typedef std::streampos pos_type;
49     typedef std::streamoff off_type;
50
51     explicit osparcasmstream(std::ostream &On) : std::ostream(&sb), sb(On) { }
52
53     sparcasmbuf *rdbuf() const {
54       return const_cast<sparcasmbuf*>(&sb);
55     }
56   };
57
58   static void writePrologue (std::ostream &Out, const std::string &comment,
59                              const std::string &symName) {
60     // Prologue:
61     // Output a comment describing the object.
62     Out << "!" << comment << "\n";   
63     // Switch the current section to .rodata in the assembly output:
64     Out << "\t.section \".rodata\"\n\t.align 8\n";  
65     // Output a global symbol naming the object:
66     Out << "\t.global " << symName << "\n";    
67     Out << "\t.type " << symName << ",#object\n"; 
68     Out << symName << ":\n"; 
69   }
70
71   static void writeEpilogue (std::ostream &Out, const std::string &symName) {
72     // Epilogue:
73     // Output a local symbol marking the end of the object:
74     Out << ".end_" << symName << ":\n";    
75     // Output size directive giving the size of the object:
76     Out << "\t.size " << symName << ", .end_" << symName << "-" << symName
77         << "\n";
78   }
79
80   // SparcBytecodeWriter - Write bytecode out to a stream that is sparc'ified
81   class SparcBytecodeWriter : public Pass {
82     std::ostream &Out;
83   public:
84     SparcBytecodeWriter(std::ostream &out) : Out(out) {}
85
86     const char *getPassName() const { return "Emit Bytecode to Sparc Assembly";}
87     
88     virtual bool run(Module &M) {
89       // Write an object containing the bytecode to the SPARC assembly stream
90       writePrologue (Out, "LLVM BYTECODE OUTPUT", "LLVMBytecode");
91       osparcasmstream OS(Out);
92       WriteBytecodeToFile(&M, OS);
93       writeEpilogue (Out, "LLVMBytecode");
94
95       // Write an object containing its length as an integer to the
96       // SPARC assembly stream
97       writePrologue (Out, "LLVM BYTECODE LENGTH", "llvm_length");
98       Out <<"\t.word\t.end_LLVMBytecode-LLVMBytecode\n"; 
99       writeEpilogue (Out, "llvm_length");
100
101       return false;
102     }
103   };
104 }  // end anonymous namespace
105
106 Pass *UltraSparc::getBytecodeAsmPrinterPass(std::ostream &Out) {
107   return new SparcBytecodeWriter(Out);
108 }