1 //===- ReaderWrappers.cpp - Parse bytecode from file or buffer -----------===//
3 // This file implements loading and parsing a bytecode file and parsing a
4 // bytecode module from a given buffer.
6 //===----------------------------------------------------------------------===//
8 #include "ReaderInternals.h"
9 #include "Support/StringExtras.h"
10 #include "Config/fcntl.h"
11 #include "Config/unistd.h"
12 #include "Config/sys/mman.h"
15 /// FDHandle - Simple handle class to make sure a file descriptor gets closed
16 /// when the object is destroyed.
21 FDHandle(int fd) : FD(fd) {}
22 operator int() const { return FD; }
24 if (FD != -1) close(FD);
28 /// BytecodeFileReader - parses a bytecode file from a file
30 class BytecodeFileReader : public BytecodeParser {
32 unsigned char *Buffer;
35 BytecodeFileReader(const BytecodeFileReader&); // Do not implement
36 void operator=(const BytecodeFileReader &BFR); // Do not implement
39 BytecodeFileReader(const std::string &Filename);
40 ~BytecodeFileReader();
45 BytecodeFileReader::BytecodeFileReader(const std::string &Filename) {
46 FDHandle FD = open(Filename.c_str(), O_RDONLY);
48 throw std::string("Error opening file!");
50 // Stat the file to get its length...
52 if (fstat(FD, &StatBuf) == -1 || StatBuf.st_size == 0)
53 throw std::string("Error stat'ing file!");
55 // mmap in the file all at once...
56 Length = StatBuf.st_size;
57 unsigned char *Buffer = (unsigned char*)mmap(0, Length, PROT_READ,
59 if (Buffer == (unsigned char*)MAP_FAILED)
60 throw std::string("Error mmapping file!");
62 // Parse the bytecode we mmapped in
63 ParseBytecode(Buffer, Length, Filename);
66 BytecodeFileReader::~BytecodeFileReader() {
67 // Unmmap the bytecode...
68 munmap((char*)Buffer, Length);
71 ////////////////////////////////////////////////////////////////////////////
74 /// BytecodeBufferReader - parses a bytecode file from a buffer
76 class BytecodeBufferReader : public BytecodeParser {
78 const unsigned char *Buffer;
81 BytecodeBufferReader(const BytecodeBufferReader&); // Do not implement
82 void operator=(const BytecodeBufferReader &BFR); // Do not implement
85 BytecodeBufferReader(const unsigned char *Buf, unsigned Length,
86 const std::string &ModuleID);
87 ~BytecodeBufferReader();
92 BytecodeBufferReader::BytecodeBufferReader(const unsigned char *Buf,
94 const std::string &ModuleID)
96 // If not aligned, allocate a new buffer to hold the bytecode...
97 const unsigned char *ParseBegin = 0;
98 if ((intptr_t)Buf & 3) {
99 Buffer = new unsigned char[Length+4];
100 unsigned Offset = 4 - ((intptr_t)Buf & 3); // Make sure it's aligned
101 ParseBegin = Buffer + Offset;
102 memcpy((unsigned char*)ParseBegin, Buf, Length); // Copy it over
105 // If we don't need to copy it over, just use the caller's copy
106 ParseBegin = Buffer = Buf;
109 ParseBytecode(ParseBegin, Length, ModuleID);
112 BytecodeBufferReader::~BytecodeBufferReader() {
113 if (MustDelete) delete [] Buffer;
118 /// BytecodeStdinReader - parses a bytecode file from stdin
120 class BytecodeStdinReader : public BytecodeParser {
122 std::vector<unsigned char> FileData;
123 unsigned char *FileBuf;
125 BytecodeStdinReader(const BytecodeStdinReader&); // Do not implement
126 void operator=(const BytecodeStdinReader &BFR); // Do not implement
129 BytecodeStdinReader();
133 BytecodeStdinReader::BytecodeStdinReader() {
135 unsigned char Buffer[4096*4];
137 // Read in all of the data from stdin, we cannot mmap stdin...
138 while ((BlockSize = read(0 /*stdin*/, Buffer, 4096*4))) {
140 throw std::string("Error reading from stdin!");
142 FileData.insert(FileData.end(), Buffer, Buffer+BlockSize);
145 if (FileData.empty())
146 throw std::string("Standard Input empty!");
148 FileBuf = &FileData[0];
149 ParseBytecode(FileBuf, FileData.size(), "<stdin>");
152 /////////////////////////////////////////////////////////////////////////////
156 /////////////////////////////////////////////////////////////////////////////
158 /// getBytecodeBufferModuleProvider - lazy function-at-a-time loading from a
160 AbstractModuleProvider*
161 getBytecodeBufferModuleProvider(const unsigned char *Buffer, unsigned Length,
162 const std::string &ModuleID) {
163 return new BytecodeBufferReader(Buffer, Length, ModuleID);
166 /// ParseBytecodeBuffer - Parse a given bytecode buffer
168 Module *ParseBytecodeBuffer(const unsigned char *Buffer, unsigned Length,
169 const std::string &ModuleID, std::string *ErrorStr){
172 AbstractModuleProvider *AMP =
173 getBytecodeBufferModuleProvider(Buffer, Length, ModuleID);
174 M = AMP->releaseModule();
176 } catch (std::string &err) {
177 if (ErrorStr) *ErrorStr = err;
183 /// getBytecodeModuleProvider - lazy function-at-a-time loading from a file
185 AbstractModuleProvider*
186 getBytecodeModuleProvider(const std::string &Filename) {
187 if (Filename != std::string("-")) // Read from a file...
188 return new BytecodeFileReader(Filename);
189 else // Read from stdin
190 return new BytecodeStdinReader();
193 /// ParseBytecodeFile - Parse the given bytecode file
195 Module *ParseBytecodeFile(const std::string &Filename, std::string *ErrorStr) {
198 AbstractModuleProvider *AMP = getBytecodeModuleProvider(Filename);
199 M = AMP->releaseModule();
201 } catch (std::string &err) {
202 if (ErrorStr) *ErrorStr = err;