blob: 9b6327437d80e3f1b026044335d4bcaf3c91dbc4 [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
126
127namespace {
128 /// BytecodeStdinReader - parses a bytecode file from stdin
129 ///
130 class BytecodeStdinReader : public BytecodeParser {
131 private:
132 std::vector<unsigned char> FileData;
133 unsigned char *FileBuf;
134
135 BytecodeStdinReader(const BytecodeStdinReader&); // Do not implement
136 void operator=(const BytecodeStdinReader &BFR); // Do not implement
137
138 public:
139 BytecodeStdinReader();
Misha Brukmand57308a2003-09-23 16:13:28 +0000140 };
141}
Misha Brukman12c29d12003-09-22 23:38:23 +0000142
Misha Brukman12c29d12003-09-22 23:38:23 +0000143BytecodeStdinReader::BytecodeStdinReader() {
144 int BlockSize;
145 unsigned char Buffer[4096*4];
146
147 // Read in all of the data from stdin, we cannot mmap stdin...
148 while ((BlockSize = read(0 /*stdin*/, Buffer, 4096*4))) {
149 if (BlockSize == -1)
150 throw std::string("Error reading from stdin!");
Misha Brukmand57308a2003-09-23 16:13:28 +0000151
Misha Brukman12c29d12003-09-22 23:38:23 +0000152 FileData.insert(FileData.end(), Buffer, Buffer+BlockSize);
153 }
154
155 if (FileData.empty())
156 throw std::string("Standard Input empty!");
157
Misha Brukman12c29d12003-09-22 23:38:23 +0000158 FileBuf = &FileData[0];
Misha Brukman12c29d12003-09-22 23:38:23 +0000159 ParseBytecode(FileBuf, FileData.size(), "<stdin>");
160}
161
Misha Brukmand57308a2003-09-23 16:13:28 +0000162/////////////////////////////////////////////////////////////////////////////
163//
164// Wrapper functions
165//
166/////////////////////////////////////////////////////////////////////////////
167
168/// getBytecodeBufferModuleProvider - lazy function-at-a-time loading from a
169/// buffer
Chris Lattner00413e32003-10-04 20:14:59 +0000170ModuleProvider*
Misha Brukman12c29d12003-09-22 23:38:23 +0000171getBytecodeBufferModuleProvider(const unsigned char *Buffer, unsigned Length,
172 const std::string &ModuleID) {
Misha Brukmand57308a2003-09-23 16:13:28 +0000173 return new BytecodeBufferReader(Buffer, Length, ModuleID);
Misha Brukman12c29d12003-09-22 23:38:23 +0000174}
175
Misha Brukmand57308a2003-09-23 16:13:28 +0000176/// ParseBytecodeBuffer - Parse a given bytecode buffer
177///
Misha Brukman12c29d12003-09-22 23:38:23 +0000178Module *ParseBytecodeBuffer(const unsigned char *Buffer, unsigned Length,
179 const std::string &ModuleID, std::string *ErrorStr){
Misha Brukmand57308a2003-09-23 16:13:28 +0000180 try {
Chris Lattner00413e32003-10-04 20:14:59 +0000181 std::auto_ptr<ModuleProvider>
Chris Lattnera9833592003-10-04 19:19:37 +0000182 AMP(getBytecodeBufferModuleProvider(Buffer, Length, ModuleID));
183 return AMP->releaseModule();
Misha Brukmand57308a2003-09-23 16:13:28 +0000184 } catch (std::string &err) {
Misha Brukman134aba62003-09-24 22:10:47 +0000185 if (ErrorStr) *ErrorStr = err;
Misha Brukmand57308a2003-09-23 16:13:28 +0000186 return 0;
187 }
Misha Brukman12c29d12003-09-22 23:38:23 +0000188}
189
Misha Brukmand57308a2003-09-23 16:13:28 +0000190/// getBytecodeModuleProvider - lazy function-at-a-time loading from a file
Misha Brukman12c29d12003-09-22 23:38:23 +0000191///
Chris Lattner00413e32003-10-04 20:14:59 +0000192ModuleProvider *getBytecodeModuleProvider(const std::string &Filename) {
Misha Brukman12c29d12003-09-22 23:38:23 +0000193 if (Filename != std::string("-")) // Read from a file...
194 return new BytecodeFileReader(Filename);
195 else // Read from stdin
196 return new BytecodeStdinReader();
197}
198
Misha Brukmand57308a2003-09-23 16:13:28 +0000199/// ParseBytecodeFile - Parse the given bytecode file
200///
Misha Brukman12c29d12003-09-22 23:38:23 +0000201Module *ParseBytecodeFile(const std::string &Filename, std::string *ErrorStr) {
Misha Brukmand57308a2003-09-23 16:13:28 +0000202 try {
Chris Lattner00413e32003-10-04 20:14:59 +0000203 std::auto_ptr<ModuleProvider> AMP(getBytecodeModuleProvider(Filename));
Chris Lattnera9833592003-10-04 19:19:37 +0000204 return AMP->releaseModule();
Misha Brukmand57308a2003-09-23 16:13:28 +0000205 } catch (std::string &err) {
Misha Brukman134aba62003-09-24 22:10:47 +0000206 if (ErrorStr) *ErrorStr = err;
Misha Brukmand57308a2003-09-23 16:13:28 +0000207 return 0;
208 }
Misha Brukman12c29d12003-09-22 23:38:23 +0000209}