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