blob: 99c0e6be9ee37fa0f6a8afe5b59ac585ecbceed0 [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
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;
Misha Brukmand57308a2003-09-23 16:13:28 +000079 bool MustDelete;
80
81 BytecodeBufferReader(const BytecodeBufferReader&); // Do not implement
82 void operator=(const BytecodeBufferReader &BFR); // Do not implement
83
84 public:
85 BytecodeBufferReader(const unsigned char *Buf, unsigned Length,
86 const std::string &ModuleID);
87 ~BytecodeBufferReader();
88
89 };
90}
91
92BytecodeBufferReader::BytecodeBufferReader(const unsigned char *Buf,
Misha Brukman34ce14b2003-09-24 22:04:02 +000093 unsigned Length,
Misha Brukmand57308a2003-09-23 16:13:28 +000094 const std::string &ModuleID)
95{
96 // If not aligned, allocate a new buffer to hold the bytecode...
97 const unsigned char *ParseBegin = 0;
Misha Brukmand57308a2003-09-23 16:13:28 +000098 if ((intptr_t)Buf & 3) {
Misha Brukman34ce14b2003-09-24 22:04:02 +000099 Buffer = new unsigned char[Length+4];
Chris Lattner4eed7932003-09-24 22:34:17 +0000100 unsigned Offset = 4 - ((intptr_t)Buffer & 3); // Make sure it's aligned
Misha Brukmand57308a2003-09-23 16:13:28 +0000101 ParseBegin = Buffer + Offset;
Misha Brukman34ce14b2003-09-24 22:04:02 +0000102 memcpy((unsigned char*)ParseBegin, Buf, Length); // Copy it over
Misha Brukmand57308a2003-09-23 16:13:28 +0000103 MustDelete = true;
104 } else {
105 // If we don't need to copy it over, just use the caller's copy
John Criswell4dcbd5e2003-09-23 21:19:11 +0000106 ParseBegin = Buffer = Buf;
Misha Brukmand57308a2003-09-23 16:13:28 +0000107 MustDelete = false;
108 }
Misha Brukman34ce14b2003-09-24 22:04:02 +0000109 ParseBytecode(ParseBegin, Length, ModuleID);
Misha Brukmand57308a2003-09-23 16:13:28 +0000110}
111
112BytecodeBufferReader::~BytecodeBufferReader() {
113 if (MustDelete) delete [] Buffer;
114}
115
116
117namespace {
118 /// BytecodeStdinReader - parses a bytecode file from stdin
119 ///
120 class BytecodeStdinReader : public BytecodeParser {
121 private:
122 std::vector<unsigned char> FileData;
123 unsigned char *FileBuf;
124
125 BytecodeStdinReader(const BytecodeStdinReader&); // Do not implement
126 void operator=(const BytecodeStdinReader &BFR); // Do not implement
127
128 public:
129 BytecodeStdinReader();
Misha Brukmand57308a2003-09-23 16:13:28 +0000130 };
131}
Misha Brukman12c29d12003-09-22 23:38:23 +0000132
Misha Brukman12c29d12003-09-22 23:38:23 +0000133BytecodeStdinReader::BytecodeStdinReader() {
134 int BlockSize;
135 unsigned char Buffer[4096*4];
136
137 // Read in all of the data from stdin, we cannot mmap stdin...
138 while ((BlockSize = read(0 /*stdin*/, Buffer, 4096*4))) {
139 if (BlockSize == -1)
140 throw std::string("Error reading from stdin!");
Misha Brukmand57308a2003-09-23 16:13:28 +0000141
Misha Brukman12c29d12003-09-22 23:38:23 +0000142 FileData.insert(FileData.end(), Buffer, Buffer+BlockSize);
143 }
144
145 if (FileData.empty())
146 throw std::string("Standard Input empty!");
147
Misha Brukman12c29d12003-09-22 23:38:23 +0000148 FileBuf = &FileData[0];
Misha Brukman12c29d12003-09-22 23:38:23 +0000149 ParseBytecode(FileBuf, FileData.size(), "<stdin>");
150}
151
Misha Brukmand57308a2003-09-23 16:13:28 +0000152/////////////////////////////////////////////////////////////////////////////
153//
154// Wrapper functions
155//
156/////////////////////////////////////////////////////////////////////////////
157
158/// getBytecodeBufferModuleProvider - lazy function-at-a-time loading from a
159/// buffer
Chris Lattner00413e32003-10-04 20:14:59 +0000160ModuleProvider*
Misha Brukman12c29d12003-09-22 23:38:23 +0000161getBytecodeBufferModuleProvider(const unsigned char *Buffer, unsigned Length,
162 const std::string &ModuleID) {
Misha Brukmand57308a2003-09-23 16:13:28 +0000163 return new BytecodeBufferReader(Buffer, Length, ModuleID);
Misha Brukman12c29d12003-09-22 23:38:23 +0000164}
165
Misha Brukmand57308a2003-09-23 16:13:28 +0000166/// ParseBytecodeBuffer - Parse a given bytecode buffer
167///
Misha Brukman12c29d12003-09-22 23:38:23 +0000168Module *ParseBytecodeBuffer(const unsigned char *Buffer, unsigned Length,
169 const std::string &ModuleID, std::string *ErrorStr){
Misha Brukmand57308a2003-09-23 16:13:28 +0000170 try {
Chris Lattner00413e32003-10-04 20:14:59 +0000171 std::auto_ptr<ModuleProvider>
Chris Lattnera9833592003-10-04 19:19:37 +0000172 AMP(getBytecodeBufferModuleProvider(Buffer, Length, ModuleID));
173 return AMP->releaseModule();
Misha Brukmand57308a2003-09-23 16:13:28 +0000174 } catch (std::string &err) {
Misha Brukman134aba62003-09-24 22:10:47 +0000175 if (ErrorStr) *ErrorStr = err;
Misha Brukmand57308a2003-09-23 16:13:28 +0000176 return 0;
177 }
Misha Brukman12c29d12003-09-22 23:38:23 +0000178}
179
Misha Brukmand57308a2003-09-23 16:13:28 +0000180/// getBytecodeModuleProvider - lazy function-at-a-time loading from a file
Misha Brukman12c29d12003-09-22 23:38:23 +0000181///
Chris Lattner00413e32003-10-04 20:14:59 +0000182ModuleProvider *getBytecodeModuleProvider(const std::string &Filename) {
Misha Brukman12c29d12003-09-22 23:38:23 +0000183 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 Lattner00413e32003-10-04 20:14:59 +0000193 std::auto_ptr<ModuleProvider> AMP(getBytecodeModuleProvider(Filename));
Chris Lattnera9833592003-10-04 19:19:37 +0000194 return AMP->releaseModule();
Misha Brukmand57308a2003-09-23 16:13:28 +0000195 } catch (std::string &err) {
Misha Brukman134aba62003-09-24 22:10:47 +0000196 if (ErrorStr) *ErrorStr = err;
Misha Brukmand57308a2003-09-23 16:13:28 +0000197 return 0;
198 }
Misha Brukman12c29d12003-09-22 23:38:23 +0000199}