blob: 82a06ea50fd8a9a2160fc577d41355a524ba6d51 [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"
Brian Gaeke378b5242003-10-06 03:30:28 +000011#include <sys/stat.h>
Misha Brukman12c29d12003-09-22 23:38:23 +000012#include "Config/unistd.h"
13#include "Config/sys/mman.h"
14
Misha Brukman12c29d12003-09-22 23:38:23 +000015namespace {
Misha Brukmand57308a2003-09-23 16:13:28 +000016 /// FDHandle - Simple handle class to make sure a file descriptor gets closed
17 /// when the object is destroyed.
18 ///
19 class FDHandle {
20 int FD;
21 public:
22 FDHandle(int fd) : FD(fd) {}
23 operator int() const { return FD; }
24 ~FDHandle() {
25 if (FD != -1) close(FD);
26 }
27 };
Misha Brukman12c29d12003-09-22 23:38:23 +000028
29 /// BytecodeFileReader - parses a bytecode file from a file
30 ///
31 class BytecodeFileReader : public BytecodeParser {
32 private:
33 unsigned char *Buffer;
34 int Length;
35
36 BytecodeFileReader(const BytecodeFileReader&); // Do not implement
Misha Brukman5c344412003-09-23 15:09:26 +000037 void operator=(const BytecodeFileReader &BFR); // Do not implement
Misha Brukman12c29d12003-09-22 23:38:23 +000038
39 public:
40 BytecodeFileReader(const std::string &Filename);
41 ~BytecodeFileReader();
Misha Brukman12c29d12003-09-22 23:38:23 +000042 };
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;
Chris Lattner735289c2003-09-25 04:13:53 +000057 Buffer = (unsigned char*)mmap(0, Length, PROT_READ, MAP_PRIVATE, FD, 0);
58
Misha Brukman12c29d12003-09-22 23:38:23 +000059 if (Buffer == (unsigned char*)MAP_FAILED)
60 throw std::string("Error mmapping file!");
61
Misha Brukman7f58de22003-10-08 19:55:47 +000062 try {
63 // Parse the bytecode we mmapped in
64 ParseBytecode(Buffer, Length, Filename);
65 } catch (...) {
66 munmap((char*)Buffer, Length);
67 throw;
68 }
Misha Brukman12c29d12003-09-22 23:38:23 +000069}
70
71BytecodeFileReader::~BytecodeFileReader() {
72 // Unmmap the bytecode...
73 munmap((char*)Buffer, Length);
74}
75
Misha Brukmand57308a2003-09-23 16:13:28 +000076////////////////////////////////////////////////////////////////////////////
77
78namespace {
79 /// BytecodeBufferReader - parses a bytecode file from a buffer
80 ///
81 class BytecodeBufferReader : public BytecodeParser {
82 private:
83 const unsigned char *Buffer;
Misha Brukmand57308a2003-09-23 16:13:28 +000084 bool MustDelete;
85
86 BytecodeBufferReader(const BytecodeBufferReader&); // Do not implement
87 void operator=(const BytecodeBufferReader &BFR); // Do not implement
88
89 public:
90 BytecodeBufferReader(const unsigned char *Buf, unsigned Length,
91 const std::string &ModuleID);
92 ~BytecodeBufferReader();
93
94 };
95}
96
97BytecodeBufferReader::BytecodeBufferReader(const unsigned char *Buf,
Misha Brukman34ce14b2003-09-24 22:04:02 +000098 unsigned Length,
Misha Brukmand57308a2003-09-23 16:13:28 +000099 const std::string &ModuleID)
100{
101 // If not aligned, allocate a new buffer to hold the bytecode...
102 const unsigned char *ParseBegin = 0;
Misha Brukmand57308a2003-09-23 16:13:28 +0000103 if ((intptr_t)Buf & 3) {
Misha Brukman34ce14b2003-09-24 22:04:02 +0000104 Buffer = new unsigned char[Length+4];
Chris Lattner4eed7932003-09-24 22:34:17 +0000105 unsigned Offset = 4 - ((intptr_t)Buffer & 3); // Make sure it's aligned
Misha Brukmand57308a2003-09-23 16:13:28 +0000106 ParseBegin = Buffer + Offset;
Misha Brukman34ce14b2003-09-24 22:04:02 +0000107 memcpy((unsigned char*)ParseBegin, Buf, Length); // Copy it over
Misha Brukmand57308a2003-09-23 16:13:28 +0000108 MustDelete = true;
109 } else {
110 // If we don't need to copy it over, just use the caller's copy
John Criswell4dcbd5e2003-09-23 21:19:11 +0000111 ParseBegin = Buffer = Buf;
Misha Brukmand57308a2003-09-23 16:13:28 +0000112 MustDelete = false;
113 }
Misha Brukman7f58de22003-10-08 19:55:47 +0000114 try {
115 ParseBytecode(ParseBegin, Length, ModuleID);
116 } catch (...) {
117 if (MustDelete) delete [] Buffer;
118 throw;
119 }
Misha Brukmand57308a2003-09-23 16:13:28 +0000120}
121
122BytecodeBufferReader::~BytecodeBufferReader() {
123 if (MustDelete) delete [] Buffer;
124}
125
Misha Brukman9fcdadb2003-10-16 21:19:54 +0000126////////////////////////////////////////////////////////////////////////////
Misha Brukmand57308a2003-09-23 16:13:28 +0000127
128namespace {
129 /// BytecodeStdinReader - parses a bytecode file from stdin
130 ///
131 class BytecodeStdinReader : public BytecodeParser {
132 private:
133 std::vector<unsigned char> FileData;
134 unsigned char *FileBuf;
135
136 BytecodeStdinReader(const BytecodeStdinReader&); // Do not implement
137 void operator=(const BytecodeStdinReader &BFR); // Do not implement
138
139 public:
140 BytecodeStdinReader();
Misha Brukmand57308a2003-09-23 16:13:28 +0000141 };
142}
Misha Brukman12c29d12003-09-22 23:38:23 +0000143
Misha Brukman12c29d12003-09-22 23:38:23 +0000144BytecodeStdinReader::BytecodeStdinReader() {
145 int BlockSize;
146 unsigned char Buffer[4096*4];
147
148 // Read in all of the data from stdin, we cannot mmap stdin...
149 while ((BlockSize = read(0 /*stdin*/, Buffer, 4096*4))) {
150 if (BlockSize == -1)
151 throw std::string("Error reading from stdin!");
Misha Brukmand57308a2003-09-23 16:13:28 +0000152
Misha Brukman12c29d12003-09-22 23:38:23 +0000153 FileData.insert(FileData.end(), Buffer, Buffer+BlockSize);
154 }
155
156 if (FileData.empty())
157 throw std::string("Standard Input empty!");
158
Misha Brukman12c29d12003-09-22 23:38:23 +0000159 FileBuf = &FileData[0];
Misha Brukman12c29d12003-09-22 23:38:23 +0000160 ParseBytecode(FileBuf, FileData.size(), "<stdin>");
161}
162
Misha Brukmand57308a2003-09-23 16:13:28 +0000163/////////////////////////////////////////////////////////////////////////////
164//
165// Wrapper functions
166//
167/////////////////////////////////////////////////////////////////////////////
168
169/// getBytecodeBufferModuleProvider - lazy function-at-a-time loading from a
170/// buffer
Chris Lattner00413e32003-10-04 20:14:59 +0000171ModuleProvider*
Misha Brukman12c29d12003-09-22 23:38:23 +0000172getBytecodeBufferModuleProvider(const unsigned char *Buffer, unsigned Length,
173 const std::string &ModuleID) {
Misha Brukmand57308a2003-09-23 16:13:28 +0000174 return new BytecodeBufferReader(Buffer, Length, ModuleID);
Misha Brukman12c29d12003-09-22 23:38:23 +0000175}
176
Misha Brukmand57308a2003-09-23 16:13:28 +0000177/// ParseBytecodeBuffer - Parse a given bytecode buffer
178///
Misha Brukman12c29d12003-09-22 23:38:23 +0000179Module *ParseBytecodeBuffer(const unsigned char *Buffer, unsigned Length,
180 const std::string &ModuleID, std::string *ErrorStr){
Misha Brukmand57308a2003-09-23 16:13:28 +0000181 try {
Chris Lattner00413e32003-10-04 20:14:59 +0000182 std::auto_ptr<ModuleProvider>
Chris Lattnera9833592003-10-04 19:19:37 +0000183 AMP(getBytecodeBufferModuleProvider(Buffer, Length, ModuleID));
184 return AMP->releaseModule();
Misha Brukmand57308a2003-09-23 16:13:28 +0000185 } catch (std::string &err) {
Misha Brukman134aba62003-09-24 22:10:47 +0000186 if (ErrorStr) *ErrorStr = err;
Misha Brukmand57308a2003-09-23 16:13:28 +0000187 return 0;
188 }
Misha Brukman12c29d12003-09-22 23:38:23 +0000189}
190
Misha Brukmand57308a2003-09-23 16:13:28 +0000191/// getBytecodeModuleProvider - lazy function-at-a-time loading from a file
Misha Brukman12c29d12003-09-22 23:38:23 +0000192///
Chris Lattner00413e32003-10-04 20:14:59 +0000193ModuleProvider *getBytecodeModuleProvider(const std::string &Filename) {
Misha Brukman12c29d12003-09-22 23:38:23 +0000194 if (Filename != std::string("-")) // Read from a file...
195 return new BytecodeFileReader(Filename);
196 else // Read from stdin
197 return new BytecodeStdinReader();
198}
199
Misha Brukmand57308a2003-09-23 16:13:28 +0000200/// ParseBytecodeFile - Parse the given bytecode file
201///
Misha Brukman12c29d12003-09-22 23:38:23 +0000202Module *ParseBytecodeFile(const std::string &Filename, std::string *ErrorStr) {
Misha Brukmand57308a2003-09-23 16:13:28 +0000203 try {
Chris Lattner00413e32003-10-04 20:14:59 +0000204 std::auto_ptr<ModuleProvider> AMP(getBytecodeModuleProvider(Filename));
Chris Lattnera9833592003-10-04 19:19:37 +0000205 return AMP->releaseModule();
Misha Brukmand57308a2003-09-23 16:13:28 +0000206 } catch (std::string &err) {
Misha Brukman134aba62003-09-24 22:10:47 +0000207 if (ErrorStr) *ErrorStr = err;
Misha Brukmand57308a2003-09-23 16:13:28 +0000208 return 0;
209 }
Misha Brukman12c29d12003-09-22 23:38:23 +0000210}