blob: 2c45021f007b32bde71ba79d51c1a5216f3ae401 [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
Anand Shukla3ee2ea82002-07-21 09:35:01 +000021using std::ostream;
Chris Lattner9530a6f2002-02-11 22:35:46 +000022
23namespace {
24
25 // sparcasmbuf - stream buf for encoding output bytes as .byte directives for
26 // the sparc assembler.
27 //
Anand Shukla3ee2ea82002-07-21 09:35:01 +000028 class sparcasmbuf : public std::streambuf {
Chris Lattner9530a6f2002-02-11 22:35:46 +000029 std::ostream &BaseStr;
30 public:
Chris Lattner49b8a9c2002-02-24 23:02:40 +000031 typedef char char_type;
32 typedef int int_type;
33 typedef std::streampos pos_type;
34 typedef std::streamoff off_type;
Chris Lattner9530a6f2002-02-11 22:35:46 +000035
36 sparcasmbuf(std::ostream &On) : BaseStr(On) {}
37
38 virtual int_type overflow(int_type C) {
39 if (C != EOF)
40 BaseStr << "\t.byte " << C << "\n"; // Output C;
41 return C;
42 }
43 };
44
45
46 // osparcasmstream - Define an ostream implementation that uses a sparcasmbuf
47 // as the underlying streambuf to write the data to. This streambuf formats
48 // the output as .byte directives for sparc output.
49 //
Mehwish Nagda0009c2e2002-07-25 17:22:48 +000050 class osparcasmstream : public std::ostream {
Chris Lattner9530a6f2002-02-11 22:35:46 +000051 sparcasmbuf sb;
52 public:
Chris Lattner49b8a9c2002-02-24 23:02:40 +000053 typedef char char_type;
54 typedef int int_type;
55 typedef std::streampos pos_type;
56 typedef std::streamoff off_type;
Chris Lattner9530a6f2002-02-11 22:35:46 +000057
Mehwish Nagda0009c2e2002-07-25 17:22:48 +000058 explicit osparcasmstream(std::ostream &On) : std::ostream(&sb), sb(On) { }
Chris Lattner9530a6f2002-02-11 22:35:46 +000059
60 sparcasmbuf *rdbuf() const {
61 return const_cast<sparcasmbuf*>(&sb);
62 }
63 };
64
Brian Gaekebb7cd972003-09-18 17:37:14 +000065 static void writePrologue (std::ostream &Out, const std::string &comment,
66 const std::string &symName) {
67 // Prologue:
68 // Output a comment describing the object.
69 Out << "!" << comment << "\n";
70 // Switch the current section to .rodata in the assembly output:
71 Out << "\t.section \".rodata\"\n\t.align 8\n";
72 // Output a global symbol naming the object:
73 Out << "\t.global " << symName << "\n";
74 Out << "\t.type " << symName << ",#object\n";
75 Out << symName << ":\n";
76 }
77
78 static void writeEpilogue (std::ostream &Out, const std::string &symName) {
79 // Epilogue:
80 // Output a local symbol marking the end of the object:
81 Out << ".end_" << symName << ":\n";
82 // Output size directive giving the size of the object:
83 Out << "\t.size " << symName << ", .end_" << symName << "-" << symName
84 << "\n";
85 }
86
Chris Lattner9530a6f2002-02-11 22:35:46 +000087 // SparcBytecodeWriter - Write bytecode out to a stream that is sparc'ified
88 class SparcBytecodeWriter : public Pass {
89 std::ostream &Out;
90 public:
91 SparcBytecodeWriter(std::ostream &out) : Out(out) {}
92
Chris Lattner96c466b2002-04-29 14:57:45 +000093 const char *getPassName() const { return "Emit Bytecode to Sparc Assembly";}
Mehwish Nagda0009c2e2002-07-25 17:22:48 +000094
Chris Lattner0b12b5f2002-06-25 16:13:21 +000095 virtual bool run(Module &M) {
Brian Gaekebb7cd972003-09-18 17:37:14 +000096 // Write an object containing the bytecode to the SPARC assembly stream
97 writePrologue (Out, "LLVM BYTECODE OUTPUT", "LLVMBytecode");
Mehwish Nagda0009c2e2002-07-25 17:22:48 +000098 osparcasmstream OS(Out);
Chris Lattner0b12b5f2002-06-25 16:13:21 +000099 WriteBytecodeToFile(&M, OS);
Brian Gaekebb7cd972003-09-18 17:37:14 +0000100 writeEpilogue (Out, "LLVMBytecode");
Chris Lattner9530a6f2002-02-11 22:35:46 +0000101
Brian Gaekebb7cd972003-09-18 17:37:14 +0000102 // Write an object containing its length as an integer to the
103 // SPARC assembly stream
104 writePrologue (Out, "LLVM BYTECODE LENGTH", "llvm_length");
Mehwish Nagda0009c2e2002-07-25 17:22:48 +0000105 Out <<"\t.word\t.end_LLVMBytecode-LLVMBytecode\n";
Brian Gaekebb7cd972003-09-18 17:37:14 +0000106 writeEpilogue (Out, "llvm_length");
107
Chris Lattner9530a6f2002-02-11 22:35:46 +0000108 return false;
109 }
110 };
111} // end anonymous namespace
112
Brian Gaekebb7cd972003-09-18 17:37:14 +0000113Pass *UltraSparc::getBytecodeAsmPrinterPass(std::ostream &Out) {
Chris Lattner9530a6f2002-02-11 22:35:46 +0000114 return new SparcBytecodeWriter(Out);
115}