blob: 40facf3fd99b8d7fd054b9660b669fbc308192d8 [file] [log] [blame]
Chris Lattner9530a6f2002-02-11 22:35:46 +00001//===-- EmitBytecodeToAssembly.cpp - Emit bytecode to Sparc .s File --------==//
John Criswellb576c942003-10-20 19:43:21 +00002//
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//===----------------------------------------------------------------------===//
Chris Lattner9530a6f2002-02-11 22:35:46 +00009//
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 "SparcInternals.h"
Chris Lattnerd50b6712002-04-28 20:40:59 +000017#include "llvm/Pass.h"
Chris Lattner9530a6f2002-02-11 22:35:46 +000018#include "llvm/Bytecode/Writer.h"
Vikram S. Adve9ee9d712002-03-03 20:46:32 +000019#include <iostream>
Mehwish Nagda0009c2e2002-07-25 17:22:48 +000020
Brian Gaeked0fde302003-11-11 22:41:34 +000021namespace llvm {
22
Anand Shukla3ee2ea82002-07-21 09:35:01 +000023using std::ostream;
Chris Lattner9530a6f2002-02-11 22:35:46 +000024
25namespace {
26
27 // sparcasmbuf - stream buf for encoding output bytes as .byte directives for
28 // the sparc assembler.
29 //
Anand Shukla3ee2ea82002-07-21 09:35:01 +000030 class sparcasmbuf : public std::streambuf {
Chris Lattner9530a6f2002-02-11 22:35:46 +000031 std::ostream &BaseStr;
32 public:
Chris Lattner49b8a9c2002-02-24 23:02:40 +000033 typedef char char_type;
34 typedef int int_type;
35 typedef std::streampos pos_type;
36 typedef std::streamoff off_type;
Chris Lattner9530a6f2002-02-11 22:35:46 +000037
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 //
Mehwish Nagda0009c2e2002-07-25 17:22:48 +000052 class osparcasmstream : public std::ostream {
Chris Lattner9530a6f2002-02-11 22:35:46 +000053 sparcasmbuf sb;
54 public:
Chris Lattner49b8a9c2002-02-24 23:02:40 +000055 typedef char char_type;
56 typedef int int_type;
57 typedef std::streampos pos_type;
58 typedef std::streamoff off_type;
Chris Lattner9530a6f2002-02-11 22:35:46 +000059
Mehwish Nagda0009c2e2002-07-25 17:22:48 +000060 explicit osparcasmstream(std::ostream &On) : std::ostream(&sb), sb(On) { }
Chris Lattner9530a6f2002-02-11 22:35:46 +000061
62 sparcasmbuf *rdbuf() const {
63 return const_cast<sparcasmbuf*>(&sb);
64 }
65 };
66
Brian Gaekebb7cd972003-09-18 17:37:14 +000067 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
Chris Lattner9530a6f2002-02-11 22:35:46 +000089 // SparcBytecodeWriter - Write bytecode out to a stream that is sparc'ified
90 class SparcBytecodeWriter : public Pass {
91 std::ostream &Out;
92 public:
93 SparcBytecodeWriter(std::ostream &out) : Out(out) {}
94
Chris Lattner96c466b2002-04-29 14:57:45 +000095 const char *getPassName() const { return "Emit Bytecode to Sparc Assembly";}
Mehwish Nagda0009c2e2002-07-25 17:22:48 +000096
Chris Lattner0b12b5f2002-06-25 16:13:21 +000097 virtual bool run(Module &M) {
Brian Gaekebb7cd972003-09-18 17:37:14 +000098 // Write an object containing the bytecode to the SPARC assembly stream
99 writePrologue (Out, "LLVM BYTECODE OUTPUT", "LLVMBytecode");
Mehwish Nagda0009c2e2002-07-25 17:22:48 +0000100 osparcasmstream OS(Out);
Chris Lattner0b12b5f2002-06-25 16:13:21 +0000101 WriteBytecodeToFile(&M, OS);
Brian Gaekebb7cd972003-09-18 17:37:14 +0000102 writeEpilogue (Out, "LLVMBytecode");
Chris Lattner9530a6f2002-02-11 22:35:46 +0000103
Brian Gaekebb7cd972003-09-18 17:37:14 +0000104 // Write an object containing its length as an integer to the
105 // SPARC assembly stream
106 writePrologue (Out, "LLVM BYTECODE LENGTH", "llvm_length");
Mehwish Nagda0009c2e2002-07-25 17:22:48 +0000107 Out <<"\t.word\t.end_LLVMBytecode-LLVMBytecode\n";
Brian Gaekebb7cd972003-09-18 17:37:14 +0000108 writeEpilogue (Out, "llvm_length");
109
Chris Lattner9530a6f2002-02-11 22:35:46 +0000110 return false;
111 }
112 };
113} // end anonymous namespace
114
Misha Brukman661a5712003-11-13 00:19:02 +0000115Pass *createBytecodeAsmPrinterPass(std::ostream &Out) {
Chris Lattner9530a6f2002-02-11 22:35:46 +0000116 return new SparcBytecodeWriter(Out);
117}
Brian Gaeked0fde302003-11-11 22:41:34 +0000118
119} // End llvm namespace