blob: 2773d36e504d66654647647b6fd1b7fdc77c2313 [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
14#define CHECK_ALIGN32(begin,end) \
15 if (align32(begin,end)) \
16 throw std::string("Alignment error: ReaderWrappers.cpp:" + \
17 utostr((unsigned)__LINE__));
18
19namespace {
20
21 /// BytecodeFileReader - parses a bytecode file from a file
22 ///
23 class BytecodeFileReader : public BytecodeParser {
24 private:
25 unsigned char *Buffer;
26 int Length;
27
28 BytecodeFileReader(const BytecodeFileReader&); // Do not implement
29 void operator=(BytecodeFileReader &BFR); // Do not implement
30
31 public:
32 BytecodeFileReader(const std::string &Filename);
33 ~BytecodeFileReader();
34
35 };
36
37 /// BytecodeStdinReader - parses a bytecode file from stdin
38 ///
39 class BytecodeStdinReader : public BytecodeParser {
40 private:
41 std::vector<unsigned char> FileData;
42 unsigned char *FileBuf;
43
44 BytecodeStdinReader(const BytecodeStdinReader&); // Do not implement
45 void operator=(BytecodeStdinReader &BFR); // Do not implement
46
47 public:
48 BytecodeStdinReader();
49 ~BytecodeStdinReader();
50 };
51
52 /// FDHandle - Simple handle class to make sure a file descriptor gets closed
53 /// when the object is destroyed.
54 ///
55 class FDHandle {
56 int FD;
57 public:
58 FDHandle(int fd) : FD(fd) {}
59 operator int() const { return FD; }
60 ~FDHandle() {
61 if (FD != -1) close(FD);
62 }
63 };
64}
65
66BytecodeFileReader::BytecodeFileReader(const std::string &Filename) {
67 FDHandle FD = open(Filename.c_str(), O_RDONLY);
68 if (FD == -1)
69 throw std::string("Error opening file!");
70
71 // Stat the file to get its length...
72 struct stat StatBuf;
73 if (fstat(FD, &StatBuf) == -1 || StatBuf.st_size == 0)
74 throw std::string("Error stat'ing file!");
75
76 // mmap in the file all at once...
77 Length = StatBuf.st_size;
78 unsigned char *Buffer = (unsigned char*)mmap(0, Length, PROT_READ,
79 MAP_PRIVATE, FD, 0);
80 if (Buffer == (unsigned char*)MAP_FAILED)
81 throw std::string("Error mmapping file!");
82
83 // Parse the bytecode we mmapped in
84 ParseBytecode(Buffer, Length, Filename);
85}
86
87BytecodeFileReader::~BytecodeFileReader() {
88 // Unmmap the bytecode...
89 munmap((char*)Buffer, Length);
90}
91
92
93#define ALIGN_PTRS 0
94
95BytecodeStdinReader::BytecodeStdinReader() {
96 int BlockSize;
97 unsigned char Buffer[4096*4];
98
99 // Read in all of the data from stdin, we cannot mmap stdin...
100 while ((BlockSize = read(0 /*stdin*/, Buffer, 4096*4))) {
101 if (BlockSize == -1)
102 throw std::string("Error reading from stdin!");
103
104 FileData.insert(FileData.end(), Buffer, Buffer+BlockSize);
105 }
106
107 if (FileData.empty())
108 throw std::string("Standard Input empty!");
109
110#if ALIGN_PTRS
111 FileBuf = (unsigned char*)mmap(0, FileData.size(), PROT_READ|PROT_WRITE,
112 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
113 assert((Buf != (unsigned char*)-1) && "mmap returned error!");
114 memcpy(Buf, &FileData[0], FileData.size());
115#else
116 FileBuf = &FileData[0];
117#endif
118
119#if 0
120 // Allocate a new buffer to hold the bytecode...
121 unsigned char *ParseBegin=0;
122 unsigned Offset=0;
123 if ((intptr_t)Buffer & 3) {
124 delete [] Buffer;
125 Buffer = new unsigned char[Length+4];
126 Offset = 4-((intptr_t)Buffer & 3); // Make sure it's aligned
127 }
128 memcpy(Buffer+Offset, Buf, Length); // Copy it over
129 ParseBegin = Buffer+Offset;
130#endif
131
132 ParseBytecode(FileBuf, FileData.size(), "<stdin>");
133}
134
135BytecodeStdinReader::~BytecodeStdinReader() {
136#if ALIGN_PTRS
137 munmap((char*)FileBuf, FileData.size()); // Free mmap'd data area
138#endif
139}
140
141///
142///
143AbstractModuleProvider*
144getBytecodeBufferModuleProvider(const unsigned char *Buffer, unsigned Length,
145 const std::string &ModuleID) {
146 CHECK_ALIGN32(Buffer, Buffer+Length);
147 BytecodeParser *Parser = new BytecodeParser();
148 Parser->ParseBytecode(Buffer, Length, ModuleID);
149 return Parser;
150}
151
152Module *ParseBytecodeBuffer(const unsigned char *Buffer, unsigned Length,
153 const std::string &ModuleID, std::string *ErrorStr){
154 AbstractModuleProvider *AMP =
155 getBytecodeBufferModuleProvider(Buffer, Length, ModuleID);
156 Module *M = AMP->releaseModule();
157 delete AMP;
158 return M;
159}
160
161
162/// Parse and return a class file...
163///
164AbstractModuleProvider*
165getBytecodeModuleProvider(const std::string &Filename) {
166 if (Filename != std::string("-")) // Read from a file...
167 return new BytecodeFileReader(Filename);
168 else // Read from stdin
169 return new BytecodeStdinReader();
170}
171
172Module *ParseBytecodeFile(const std::string &Filename, std::string *ErrorStr) {
173 AbstractModuleProvider *AMP = getBytecodeModuleProvider(Filename);
174 Module *M = AMP->releaseModule();
175 delete AMP;
176 return M;
177}