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