blob: ecdb16d363fe9fee5bc3d8f269dd6562731ee49c [file] [log] [blame]
Misha Brukman46453792003-09-22 23:44:46 +00001//===- ReaderWrappers.cpp - Parse bytecode from file or buffer -----------===//
2//
3// This file implements loading and parsing a bytecode file and parsing a
4// bytecode module from a given buffer.
5//
6//===----------------------------------------------------------------------===//
7
Misha Brukman12c29d12003-09-22 23:38:23 +00008#include "ReaderInternals.h"
9#include "Support/StringExtras.h"
10#include "Config/fcntl.h"
11#include "Config/unistd.h"
12#include "Config/sys/mman.h"
13
Misha Brukman12c29d12003-09-22 23:38:23 +000014namespace {
Misha Brukmand57308a2003-09-23 16:13:28 +000015 /// FDHandle - Simple handle class to make sure a file descriptor gets closed
16 /// when the object is destroyed.
17 ///
18 class FDHandle {
19 int FD;
20 public:
21 FDHandle(int fd) : FD(fd) {}
22 operator int() const { return FD; }
23 ~FDHandle() {
24 if (FD != -1) close(FD);
25 }
26 };
Misha Brukman12c29d12003-09-22 23:38:23 +000027
28 /// BytecodeFileReader - parses a bytecode file from a file
29 ///
30 class BytecodeFileReader : public BytecodeParser {
31 private:
32 unsigned char *Buffer;
33 int Length;
34
35 BytecodeFileReader(const BytecodeFileReader&); // Do not implement
Misha Brukman5c344412003-09-23 15:09:26 +000036 void operator=(const BytecodeFileReader &BFR); // Do not implement
Misha Brukman12c29d12003-09-22 23:38:23 +000037
38 public:
39 BytecodeFileReader(const std::string &Filename);
40 ~BytecodeFileReader();
41
42 };
Misha Brukman12c29d12003-09-22 23:38:23 +000043}
44
45BytecodeFileReader::BytecodeFileReader(const std::string &Filename) {
46 FDHandle FD = open(Filename.c_str(), O_RDONLY);
47 if (FD == -1)
48 throw std::string("Error opening file!");
49
50 // Stat the file to get its length...
51 struct stat StatBuf;
52 if (fstat(FD, &StatBuf) == -1 || StatBuf.st_size == 0)
53 throw std::string("Error stat'ing file!");
54
55 // mmap in the file all at once...
56 Length = StatBuf.st_size;
57 unsigned char *Buffer = (unsigned char*)mmap(0, Length, PROT_READ,
58 MAP_PRIVATE, FD, 0);
59 if (Buffer == (unsigned char*)MAP_FAILED)
60 throw std::string("Error mmapping file!");
61
62 // Parse the bytecode we mmapped in
63 ParseBytecode(Buffer, Length, Filename);
64}
65
66BytecodeFileReader::~BytecodeFileReader() {
67 // Unmmap the bytecode...
68 munmap((char*)Buffer, Length);
69}
70
Misha Brukmand57308a2003-09-23 16:13:28 +000071////////////////////////////////////////////////////////////////////////////
72
73namespace {
74 /// BytecodeBufferReader - parses a bytecode file from a buffer
75 ///
76 class BytecodeBufferReader : public BytecodeParser {
77 private:
78 const unsigned char *Buffer;
79 int Length;
80 bool MustDelete;
81
82 BytecodeBufferReader(const BytecodeBufferReader&); // Do not implement
83 void operator=(const BytecodeBufferReader &BFR); // Do not implement
84
85 public:
86 BytecodeBufferReader(const unsigned char *Buf, unsigned Length,
87 const std::string &ModuleID);
88 ~BytecodeBufferReader();
89
90 };
91}
92
93BytecodeBufferReader::BytecodeBufferReader(const unsigned char *Buf,
94 unsigned Len,
95 const std::string &ModuleID)
96{
97 // If not aligned, allocate a new buffer to hold the bytecode...
98 const unsigned char *ParseBegin = 0;
99 unsigned Offset = 0;
100 if ((intptr_t)Buf & 3) {
101 Length = Len+4;
102 Buffer = new unsigned char[Length];
103 Offset = 4 - ((intptr_t)Buf & 3); // Make sure it's aligned
104 ParseBegin = Buffer + Offset;
105 memcpy((unsigned char*)ParseBegin, Buf, Len); // Copy it over
106 MustDelete = true;
107 } else {
108 // If we don't need to copy it over, just use the caller's copy
John Criswell4dcbd5e2003-09-23 21:19:11 +0000109 ParseBegin = Buffer = Buf;
Misha Brukmand57308a2003-09-23 16:13:28 +0000110 Length = Len;
111 MustDelete = false;
112 }
113 ParseBytecode(ParseBegin, Len, ModuleID);
114}
115
116BytecodeBufferReader::~BytecodeBufferReader() {
117 if (MustDelete) delete [] Buffer;
118}
119
120
121namespace {
122 /// BytecodeStdinReader - parses a bytecode file from stdin
123 ///
124 class BytecodeStdinReader : public BytecodeParser {
125 private:
126 std::vector<unsigned char> FileData;
127 unsigned char *FileBuf;
128
129 BytecodeStdinReader(const BytecodeStdinReader&); // Do not implement
130 void operator=(const BytecodeStdinReader &BFR); // Do not implement
131
132 public:
133 BytecodeStdinReader();
134 ~BytecodeStdinReader();
135 };
136}
Misha Brukman12c29d12003-09-22 23:38:23 +0000137
138#define ALIGN_PTRS 0
139
140BytecodeStdinReader::BytecodeStdinReader() {
141 int BlockSize;
142 unsigned char Buffer[4096*4];
143
144 // Read in all of the data from stdin, we cannot mmap stdin...
145 while ((BlockSize = read(0 /*stdin*/, Buffer, 4096*4))) {
146 if (BlockSize == -1)
147 throw std::string("Error reading from stdin!");
Misha Brukmand57308a2003-09-23 16:13:28 +0000148
Misha Brukman12c29d12003-09-22 23:38:23 +0000149 FileData.insert(FileData.end(), Buffer, Buffer+BlockSize);
150 }
151
152 if (FileData.empty())
153 throw std::string("Standard Input empty!");
154
155#if ALIGN_PTRS
156 FileBuf = (unsigned char*)mmap(0, FileData.size(), PROT_READ|PROT_WRITE,
157 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
158 assert((Buf != (unsigned char*)-1) && "mmap returned error!");
159 memcpy(Buf, &FileData[0], FileData.size());
160#else
161 FileBuf = &FileData[0];
162#endif
163
Misha Brukman12c29d12003-09-22 23:38:23 +0000164 ParseBytecode(FileBuf, FileData.size(), "<stdin>");
165}
166
167BytecodeStdinReader::~BytecodeStdinReader() {
168#if ALIGN_PTRS
169 munmap((char*)FileBuf, FileData.size()); // Free mmap'd data area
170#endif
171}
172
Misha Brukmand57308a2003-09-23 16:13:28 +0000173/////////////////////////////////////////////////////////////////////////////
174//
175// Wrapper functions
176//
177/////////////////////////////////////////////////////////////////////////////
178
179/// getBytecodeBufferModuleProvider - lazy function-at-a-time loading from a
180/// buffer
Misha Brukman12c29d12003-09-22 23:38:23 +0000181AbstractModuleProvider*
182getBytecodeBufferModuleProvider(const unsigned char *Buffer, unsigned Length,
183 const std::string &ModuleID) {
Misha Brukmand57308a2003-09-23 16:13:28 +0000184 return new BytecodeBufferReader(Buffer, Length, ModuleID);
Misha Brukman12c29d12003-09-22 23:38:23 +0000185}
186
Misha Brukmand57308a2003-09-23 16:13:28 +0000187/// ParseBytecodeBuffer - Parse a given bytecode buffer
188///
Misha Brukman12c29d12003-09-22 23:38:23 +0000189Module *ParseBytecodeBuffer(const unsigned char *Buffer, unsigned Length,
190 const std::string &ModuleID, std::string *ErrorStr){
Misha Brukmand57308a2003-09-23 16:13:28 +0000191 Module *M = 0;
192 try {
193 AbstractModuleProvider *AMP =
194 getBytecodeBufferModuleProvider(Buffer, Length, ModuleID);
195 M = AMP->releaseModule();
196 delete AMP;
197 } catch (std::string &err) {
198 return 0;
199 }
Misha Brukman12c29d12003-09-22 23:38:23 +0000200 return M;
201}
202
Misha Brukmand57308a2003-09-23 16:13:28 +0000203/// getBytecodeModuleProvider - lazy function-at-a-time loading from a file
Misha Brukman12c29d12003-09-22 23:38:23 +0000204///
205AbstractModuleProvider*
206getBytecodeModuleProvider(const std::string &Filename) {
207 if (Filename != std::string("-")) // Read from a file...
208 return new BytecodeFileReader(Filename);
209 else // Read from stdin
210 return new BytecodeStdinReader();
211}
212
Misha Brukmand57308a2003-09-23 16:13:28 +0000213/// ParseBytecodeFile - Parse the given bytecode file
214///
Misha Brukman12c29d12003-09-22 23:38:23 +0000215Module *ParseBytecodeFile(const std::string &Filename, std::string *ErrorStr) {
Misha Brukmand57308a2003-09-23 16:13:28 +0000216 Module *M = 0;
217 try {
218 AbstractModuleProvider *AMP = getBytecodeModuleProvider(Filename);
219 M = AMP->releaseModule();
220 delete AMP;
221 } catch (std::string &err) {
222 return 0;
223 }
Misha Brukman12c29d12003-09-22 23:38:23 +0000224 return M;
225}