blob: a936c0f72aa8699e6460f066c9710051a45aac69 [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();
Misha Brukman12c29d12003-09-22 23:38:23 +000041 };
Misha Brukman12c29d12003-09-22 23:38:23 +000042}
43
44BytecodeFileReader::BytecodeFileReader(const std::string &Filename) {
45 FDHandle FD = open(Filename.c_str(), O_RDONLY);
46 if (FD == -1)
47 throw std::string("Error opening file!");
48
49 // Stat the file to get its length...
50 struct stat StatBuf;
51 if (fstat(FD, &StatBuf) == -1 || StatBuf.st_size == 0)
52 throw std::string("Error stat'ing file!");
53
54 // mmap in the file all at once...
55 Length = StatBuf.st_size;
Chris Lattner735289c2003-09-25 04:13:53 +000056 Buffer = (unsigned char*)mmap(0, Length, PROT_READ, MAP_PRIVATE, FD, 0);
57
Misha Brukman12c29d12003-09-22 23:38:23 +000058 if (Buffer == (unsigned char*)MAP_FAILED)
59 throw std::string("Error mmapping file!");
60
61 // Parse the bytecode we mmapped in
62 ParseBytecode(Buffer, Length, Filename);
63}
64
65BytecodeFileReader::~BytecodeFileReader() {
66 // Unmmap the bytecode...
67 munmap((char*)Buffer, Length);
68}
69
Misha Brukmand57308a2003-09-23 16:13:28 +000070////////////////////////////////////////////////////////////////////////////
71
72namespace {
73 /// BytecodeBufferReader - parses a bytecode file from a buffer
74 ///
75 class BytecodeBufferReader : public BytecodeParser {
76 private:
77 const unsigned char *Buffer;
Misha Brukmand57308a2003-09-23 16:13:28 +000078 bool MustDelete;
79
80 BytecodeBufferReader(const BytecodeBufferReader&); // Do not implement
81 void operator=(const BytecodeBufferReader &BFR); // Do not implement
82
83 public:
84 BytecodeBufferReader(const unsigned char *Buf, unsigned Length,
85 const std::string &ModuleID);
86 ~BytecodeBufferReader();
87
88 };
89}
90
91BytecodeBufferReader::BytecodeBufferReader(const unsigned char *Buf,
Misha Brukman34ce14b2003-09-24 22:04:02 +000092 unsigned Length,
Misha Brukmand57308a2003-09-23 16:13:28 +000093 const std::string &ModuleID)
94{
95 // If not aligned, allocate a new buffer to hold the bytecode...
96 const unsigned char *ParseBegin = 0;
Misha Brukmand57308a2003-09-23 16:13:28 +000097 if ((intptr_t)Buf & 3) {
Misha Brukman34ce14b2003-09-24 22:04:02 +000098 Buffer = new unsigned char[Length+4];
Chris Lattner4eed7932003-09-24 22:34:17 +000099 unsigned Offset = 4 - ((intptr_t)Buffer & 3); // Make sure it's aligned
Misha Brukmand57308a2003-09-23 16:13:28 +0000100 ParseBegin = Buffer + Offset;
Misha Brukman34ce14b2003-09-24 22:04:02 +0000101 memcpy((unsigned char*)ParseBegin, Buf, Length); // Copy it over
Misha Brukmand57308a2003-09-23 16:13:28 +0000102 MustDelete = true;
103 } else {
104 // If we don't need to copy it over, just use the caller's copy
John Criswell4dcbd5e2003-09-23 21:19:11 +0000105 ParseBegin = Buffer = Buf;
Misha Brukmand57308a2003-09-23 16:13:28 +0000106 MustDelete = false;
107 }
Misha Brukman34ce14b2003-09-24 22:04:02 +0000108 ParseBytecode(ParseBegin, Length, ModuleID);
Misha Brukmand57308a2003-09-23 16:13:28 +0000109}
110
111BytecodeBufferReader::~BytecodeBufferReader() {
112 if (MustDelete) delete [] Buffer;
113}
114
115
116namespace {
117 /// BytecodeStdinReader - parses a bytecode file from stdin
118 ///
119 class BytecodeStdinReader : public BytecodeParser {
120 private:
121 std::vector<unsigned char> FileData;
122 unsigned char *FileBuf;
123
124 BytecodeStdinReader(const BytecodeStdinReader&); // Do not implement
125 void operator=(const BytecodeStdinReader &BFR); // Do not implement
126
127 public:
128 BytecodeStdinReader();
Misha Brukmand57308a2003-09-23 16:13:28 +0000129 };
130}
Misha Brukman12c29d12003-09-22 23:38:23 +0000131
Misha Brukman12c29d12003-09-22 23:38:23 +0000132BytecodeStdinReader::BytecodeStdinReader() {
133 int BlockSize;
134 unsigned char Buffer[4096*4];
135
136 // Read in all of the data from stdin, we cannot mmap stdin...
137 while ((BlockSize = read(0 /*stdin*/, Buffer, 4096*4))) {
138 if (BlockSize == -1)
139 throw std::string("Error reading from stdin!");
Misha Brukmand57308a2003-09-23 16:13:28 +0000140
Misha Brukman12c29d12003-09-22 23:38:23 +0000141 FileData.insert(FileData.end(), Buffer, Buffer+BlockSize);
142 }
143
144 if (FileData.empty())
145 throw std::string("Standard Input empty!");
146
Misha Brukman12c29d12003-09-22 23:38:23 +0000147 FileBuf = &FileData[0];
Misha Brukman12c29d12003-09-22 23:38:23 +0000148 ParseBytecode(FileBuf, FileData.size(), "<stdin>");
149}
150
Misha Brukmand57308a2003-09-23 16:13:28 +0000151/////////////////////////////////////////////////////////////////////////////
152//
153// Wrapper functions
154//
155/////////////////////////////////////////////////////////////////////////////
156
157/// getBytecodeBufferModuleProvider - lazy function-at-a-time loading from a
158/// buffer
Misha Brukman12c29d12003-09-22 23:38:23 +0000159AbstractModuleProvider*
160getBytecodeBufferModuleProvider(const unsigned char *Buffer, unsigned Length,
161 const std::string &ModuleID) {
Misha Brukmand57308a2003-09-23 16:13:28 +0000162 return new BytecodeBufferReader(Buffer, Length, ModuleID);
Misha Brukman12c29d12003-09-22 23:38:23 +0000163}
164
Misha Brukmand57308a2003-09-23 16:13:28 +0000165/// ParseBytecodeBuffer - Parse a given bytecode buffer
166///
Misha Brukman12c29d12003-09-22 23:38:23 +0000167Module *ParseBytecodeBuffer(const unsigned char *Buffer, unsigned Length,
168 const std::string &ModuleID, std::string *ErrorStr){
Misha Brukmand57308a2003-09-23 16:13:28 +0000169 try {
Chris Lattnera9833592003-10-04 19:19:37 +0000170 std::auto_ptr<AbstractModuleProvider>
171 AMP(getBytecodeBufferModuleProvider(Buffer, Length, ModuleID));
172 return AMP->releaseModule();
Misha Brukmand57308a2003-09-23 16:13:28 +0000173 } catch (std::string &err) {
Misha Brukman134aba62003-09-24 22:10:47 +0000174 if (ErrorStr) *ErrorStr = err;
Misha Brukmand57308a2003-09-23 16:13:28 +0000175 return 0;
176 }
Misha Brukman12c29d12003-09-22 23:38:23 +0000177}
178
Misha Brukmand57308a2003-09-23 16:13:28 +0000179/// getBytecodeModuleProvider - lazy function-at-a-time loading from a file
Misha Brukman12c29d12003-09-22 23:38:23 +0000180///
181AbstractModuleProvider*
182getBytecodeModuleProvider(const std::string &Filename) {
183 if (Filename != std::string("-")) // Read from a file...
184 return new BytecodeFileReader(Filename);
185 else // Read from stdin
186 return new BytecodeStdinReader();
187}
188
Misha Brukmand57308a2003-09-23 16:13:28 +0000189/// ParseBytecodeFile - Parse the given bytecode file
190///
Misha Brukman12c29d12003-09-22 23:38:23 +0000191Module *ParseBytecodeFile(const std::string &Filename, std::string *ErrorStr) {
Misha Brukmand57308a2003-09-23 16:13:28 +0000192 try {
Chris Lattnera9833592003-10-04 19:19:37 +0000193 std::auto_ptr<AbstractModuleProvider>
194 AMP(getBytecodeModuleProvider(Filename));
195 return AMP->releaseModule();
Misha Brukmand57308a2003-09-23 16:13:28 +0000196 } catch (std::string &err) {
Misha Brukman134aba62003-09-24 22:10:47 +0000197 if (ErrorStr) *ErrorStr = err;
Misha Brukmand57308a2003-09-23 16:13:28 +0000198 return 0;
199 }
Misha Brukman12c29d12003-09-22 23:38:23 +0000200}