mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-15 21:24:00 +00:00
Changes to get some meaningful feedback from the bytecode reader. At some point this stuff should all be exception driven, but for now it is not.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@970 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -18,7 +18,8 @@ class Module;
|
|||||||
|
|
||||||
// Parse and return a class...
|
// Parse and return a class...
|
||||||
//
|
//
|
||||||
Module *ParseBytecodeFile(const string &Filename);
|
Module *ParseBytecodeFile(const string &Filename, string *ErrorStr = 0);
|
||||||
Module *ParseBytecodeBuffer(const char *Buffer, unsigned BufferSize);
|
Module *ParseBytecodeBuffer(const char *Buffer, unsigned BufferSize,
|
||||||
|
string *ErrorStr = 0);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//===- Reader.cpp - Code to read bytecode files -----------------------------===
|
//===- Reader.cpp - Code to read bytecode files ---------------------------===//
|
||||||
//
|
//
|
||||||
// This library implements the functionality defined in llvm/Bytecode/Reader.h
|
// This library implements the functionality defined in llvm/Bytecode/Reader.h
|
||||||
//
|
//
|
||||||
@ -8,7 +8,7 @@
|
|||||||
// TODO: Make error message outputs be configurable depending on an option?
|
// TODO: Make error message outputs be configurable depending on an option?
|
||||||
// TODO: Allow passing in an option to ignore the symbol table
|
// TODO: Allow passing in an option to ignore the symbol table
|
||||||
//
|
//
|
||||||
//===------------------------------------------------------------------------===
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "llvm/Bytecode/Reader.h"
|
#include "llvm/Bytecode/Reader.h"
|
||||||
#include "llvm/Bytecode/Format.h"
|
#include "llvm/Bytecode/Format.h"
|
||||||
@ -256,7 +256,10 @@ bool BytecodeParser::ParseMethod(const uchar *&Buf, const uchar *EndBuf,
|
|||||||
Module *C) {
|
Module *C) {
|
||||||
// Clear out the local values table...
|
// Clear out the local values table...
|
||||||
Values.clear();
|
Values.clear();
|
||||||
if (MethodSignatureList.empty()) return failure(true); // Unexpected method!
|
if (MethodSignatureList.empty()) {
|
||||||
|
Error = "Method found, but MethodSignatureList empty!";
|
||||||
|
return failure(true); // Unexpected method!
|
||||||
|
}
|
||||||
|
|
||||||
const PointerType *PMTy = MethodSignatureList.front().first; // PtrMeth
|
const PointerType *PMTy = MethodSignatureList.front().first; // PtrMeth
|
||||||
const MethodType *MTy = dyn_cast<const MethodType>(PMTy->getValueType());
|
const MethodType *MTy = dyn_cast<const MethodType>(PMTy->getValueType());
|
||||||
@ -272,14 +275,20 @@ bool BytecodeParser::ParseMethod(const uchar *&Buf, const uchar *EndBuf,
|
|||||||
for (MethodType::ParamTypes::const_iterator It = Params.begin();
|
for (MethodType::ParamTypes::const_iterator It = Params.begin();
|
||||||
It != Params.end(); ++It) {
|
It != Params.end(); ++It) {
|
||||||
MethodArgument *MA = new MethodArgument(*It);
|
MethodArgument *MA = new MethodArgument(*It);
|
||||||
if (insertValue(MA, Values) == -1) { delete M; return failure(true); }
|
if (insertValue(MA, Values) == -1) {
|
||||||
|
Error = "Error reading method arguments!\n";
|
||||||
|
delete M; return failure(true);
|
||||||
|
}
|
||||||
M->getArgumentList().push_back(MA);
|
M->getArgumentList().push_back(MA);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (Buf < EndBuf) {
|
while (Buf < EndBuf) {
|
||||||
unsigned Type, Size;
|
unsigned Type, Size;
|
||||||
const uchar *OldBuf = Buf;
|
const uchar *OldBuf = Buf;
|
||||||
if (readBlock(Buf, EndBuf, Type, Size)) { delete M; return failure(true); }
|
if (readBlock(Buf, EndBuf, Type, Size)) {
|
||||||
|
Error = "Error reading Method level block!";
|
||||||
|
delete M; return failure(true);
|
||||||
|
}
|
||||||
|
|
||||||
switch (Type) {
|
switch (Type) {
|
||||||
case BytecodeFormat::ConstantPool:
|
case BytecodeFormat::ConstantPool:
|
||||||
@ -317,6 +326,7 @@ bool BytecodeParser::ParseMethod(const uchar *&Buf, const uchar *EndBuf,
|
|||||||
BCR_TRACE(2, "} end block\n");
|
BCR_TRACE(2, "} end block\n");
|
||||||
|
|
||||||
if (align32(Buf, EndBuf)) {
|
if (align32(Buf, EndBuf)) {
|
||||||
|
Error = "Error aligning Method level block!";
|
||||||
delete M; // Malformed bc file, read past end of block.
|
delete M; // Malformed bc file, read past end of block.
|
||||||
return failure(true);
|
return failure(true);
|
||||||
}
|
}
|
||||||
@ -324,6 +334,7 @@ bool BytecodeParser::ParseMethod(const uchar *&Buf, const uchar *EndBuf,
|
|||||||
|
|
||||||
if (postResolveValues(LateResolveValues) ||
|
if (postResolveValues(LateResolveValues) ||
|
||||||
postResolveValues(LateResolveModuleValues)) {
|
postResolveValues(LateResolveModuleValues)) {
|
||||||
|
Error = "Error resolving method values!";
|
||||||
delete M; return failure(true); // Unresolvable references!
|
delete M; return failure(true); // Unresolvable references!
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -360,8 +371,10 @@ bool BytecodeParser::ParseMethod(const uchar *&Buf, const uchar *EndBuf,
|
|||||||
|
|
||||||
bool BytecodeParser::ParseModuleGlobalInfo(const uchar *&Buf, const uchar *End,
|
bool BytecodeParser::ParseModuleGlobalInfo(const uchar *&Buf, const uchar *End,
|
||||||
Module *Mod) {
|
Module *Mod) {
|
||||||
if (!MethodSignatureList.empty())
|
if (!MethodSignatureList.empty()) {
|
||||||
|
Error = "Two ModuleGlobalInfo packets found!";
|
||||||
return failure(true); // Two ModuleGlobal blocks?
|
return failure(true); // Two ModuleGlobal blocks?
|
||||||
|
}
|
||||||
|
|
||||||
// Read global variables...
|
// Read global variables...
|
||||||
unsigned VarType;
|
unsigned VarType;
|
||||||
@ -370,7 +383,7 @@ bool BytecodeParser::ParseModuleGlobalInfo(const uchar *&Buf, const uchar *End,
|
|||||||
// VarType Fields: bit0 = isConstant, bit1 = hasInitializer, bit2+ = slot#
|
// VarType Fields: bit0 = isConstant, bit1 = hasInitializer, bit2+ = slot#
|
||||||
const Type *Ty = getType(VarType >> 2);
|
const Type *Ty = getType(VarType >> 2);
|
||||||
if (!Ty || !Ty->isPointerType()) {
|
if (!Ty || !Ty->isPointerType()) {
|
||||||
cerr << "Global not pointer type! Ty = " << Ty << endl;
|
Error = "Global not pointer type! Ty = " + Ty->getDescription();
|
||||||
return failure(true);
|
return failure(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -413,7 +426,7 @@ bool BytecodeParser::ParseModuleGlobalInfo(const uchar *&Buf, const uchar *End,
|
|||||||
const Type *Ty = getType(MethSignature);
|
const Type *Ty = getType(MethSignature);
|
||||||
if (!Ty || !isa<PointerType>(Ty) ||
|
if (!Ty || !isa<PointerType>(Ty) ||
|
||||||
!isa<MethodType>(cast<PointerType>(Ty)->getValueType())) {
|
!isa<MethodType>(cast<PointerType>(Ty)->getValueType())) {
|
||||||
cerr << "Method not ptr to meth type! Ty = " << Ty << endl;
|
Error = "Method not ptr to meth type! Ty = " + Ty->getDescription();
|
||||||
return failure(true);
|
return failure(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -458,8 +471,10 @@ bool BytecodeParser::ParseModule(const uchar *Buf, const uchar *EndBuf,
|
|||||||
|
|
||||||
unsigned Type, Size;
|
unsigned Type, Size;
|
||||||
if (readBlock(Buf, EndBuf, Type, Size)) return failure(true);
|
if (readBlock(Buf, EndBuf, Type, Size)) return failure(true);
|
||||||
if (Type != BytecodeFormat::Module || Buf+Size != EndBuf)
|
if (Type != BytecodeFormat::Module || Buf+Size != EndBuf) {
|
||||||
|
Error = "Expected Module packet!";
|
||||||
return failure(true); // Hrm, not a class?
|
return failure(true); // Hrm, not a class?
|
||||||
|
}
|
||||||
|
|
||||||
BCR_TRACE(0, "BLOCK BytecodeFormat::Module: {\n");
|
BCR_TRACE(0, "BLOCK BytecodeFormat::Module: {\n");
|
||||||
MethodSignatureList.clear(); // Just in case...
|
MethodSignatureList.clear(); // Just in case...
|
||||||
@ -505,7 +520,7 @@ bool BytecodeParser::ParseModule(const uchar *Buf, const uchar *EndBuf,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
cerr << " Unknown class block: " << Type << endl;
|
Error = "Expected Module Block!";
|
||||||
Buf += Size;
|
Buf += Size;
|
||||||
if (OldBuf > Buf) return failure(true); // Wrap around!
|
if (OldBuf > Buf) return failure(true); // Wrap around!
|
||||||
break;
|
break;
|
||||||
@ -514,8 +529,10 @@ bool BytecodeParser::ParseModule(const uchar *Buf, const uchar *EndBuf,
|
|||||||
if (align32(Buf, EndBuf)) { delete C; return failure(true); }
|
if (align32(Buf, EndBuf)) { delete C; return failure(true); }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!MethodSignatureList.empty()) // Expected more methods!
|
if (!MethodSignatureList.empty()) { // Expected more methods!
|
||||||
|
Error = "Method expected, but bytecode stream at end!";
|
||||||
return failure(true);
|
return failure(true);
|
||||||
|
}
|
||||||
|
|
||||||
BCR_TRACE(0, "} end block\n\n");
|
BCR_TRACE(0, "} end block\n\n");
|
||||||
return false;
|
return false;
|
||||||
@ -526,8 +543,10 @@ Module *BytecodeParser::ParseBytecode(const uchar *Buf, const uchar *EndBuf) {
|
|||||||
unsigned Sig;
|
unsigned Sig;
|
||||||
// Read and check signature...
|
// Read and check signature...
|
||||||
if (read(Buf, EndBuf, Sig) ||
|
if (read(Buf, EndBuf, Sig) ||
|
||||||
Sig != ('l' | ('l' << 8) | ('v' << 16) | 'm' << 24))
|
Sig != ('l' | ('l' << 8) | ('v' << 16) | 'm' << 24)) {
|
||||||
|
Error = "Invalid bytecode signature!";
|
||||||
return failure<Module*>(0); // Invalid signature!
|
return failure<Module*>(0); // Invalid signature!
|
||||||
|
}
|
||||||
|
|
||||||
Module *Result;
|
Module *Result;
|
||||||
if (ParseModule(Buf, EndBuf, Result)) return 0;
|
if (ParseModule(Buf, EndBuf, Result)) return 0;
|
||||||
@ -542,27 +561,37 @@ Module *ParseBytecodeBuffer(const uchar *Buffer, unsigned Length) {
|
|||||||
|
|
||||||
// Parse and return a class file...
|
// Parse and return a class file...
|
||||||
//
|
//
|
||||||
Module *ParseBytecodeFile(const string &Filename) {
|
Module *ParseBytecodeFile(const string &Filename, string *ErrorStr) {
|
||||||
struct stat StatBuf;
|
struct stat StatBuf;
|
||||||
Module *Result = 0;
|
Module *Result = 0;
|
||||||
|
|
||||||
if (Filename != string("-")) { // Read from a file...
|
if (Filename != string("-")) { // Read from a file...
|
||||||
int FD = open(Filename.c_str(), O_RDONLY);
|
int FD = open(Filename.c_str(), O_RDONLY);
|
||||||
if (FD == -1) return failure<Module*>(0);
|
if (FD == -1) {
|
||||||
|
if (ErrorStr) *ErrorStr = "Error opening file!";
|
||||||
|
return failure<Module*>(0);
|
||||||
|
}
|
||||||
|
|
||||||
if (fstat(FD, &StatBuf) == -1) { close(FD); return failure<Module*>(0); }
|
if (fstat(FD, &StatBuf) == -1) { close(FD); return failure<Module*>(0); }
|
||||||
|
|
||||||
int Length = StatBuf.st_size;
|
int Length = StatBuf.st_size;
|
||||||
if (Length == 0) { close(FD); return failure<Module*>(0); }
|
if (Length == 0) {
|
||||||
|
if (ErrorStr) *ErrorStr = "Error stat'ing file!";
|
||||||
|
close(FD); return failure<Module*>(0);
|
||||||
|
}
|
||||||
uchar *Buffer = (uchar*)mmap(0, Length, PROT_READ,
|
uchar *Buffer = (uchar*)mmap(0, Length, PROT_READ,
|
||||||
MAP_PRIVATE, FD, 0);
|
MAP_PRIVATE, FD, 0);
|
||||||
if (Buffer == (uchar*)-1) { close(FD); return failure<Module*>(0); }
|
if (Buffer == (uchar*)-1) {
|
||||||
|
if (ErrorStr) *ErrorStr = "Error mmapping file!";
|
||||||
|
close(FD); return failure<Module*>(0);
|
||||||
|
}
|
||||||
|
|
||||||
BytecodeParser Parser;
|
BytecodeParser Parser;
|
||||||
Result = Parser.ParseBytecode(Buffer, Buffer+Length);
|
Result = Parser.ParseBytecode(Buffer, Buffer+Length);
|
||||||
|
|
||||||
munmap((char*)Buffer, Length);
|
munmap((char*)Buffer, Length);
|
||||||
close(FD);
|
close(FD);
|
||||||
|
if (ErrorStr) *ErrorStr = Parser.getError();
|
||||||
} else { // Read from stdin
|
} else { // Read from stdin
|
||||||
size_t FileSize = 0;
|
size_t FileSize = 0;
|
||||||
int BlockSize;
|
int BlockSize;
|
||||||
@ -575,7 +604,10 @@ Module *ParseBytecodeFile(const string &Filename) {
|
|||||||
FileSize += BlockSize;
|
FileSize += BlockSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FileSize == 0) { free(FileData); return failure<Module*>(0); }
|
if (FileSize == 0) {
|
||||||
|
if (ErrorStr) *ErrorStr = "Standard Input empty!";
|
||||||
|
free(FileData); return failure<Module*>(0);
|
||||||
|
}
|
||||||
|
|
||||||
#define ALIGN_PTRS 1
|
#define ALIGN_PTRS 1
|
||||||
#if ALIGN_PTRS
|
#if ALIGN_PTRS
|
||||||
@ -596,6 +628,8 @@ Module *ParseBytecodeFile(const string &Filename) {
|
|||||||
#else
|
#else
|
||||||
free(FileData); // Free realloc'd block of memory
|
free(FileData); // Free realloc'd block of memory
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (ErrorStr) *ErrorStr = Parser.getError();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
// Enable to trace to figure out what the heck is going on when parsing fails
|
// Enable to trace to figure out what the heck is going on when parsing fails
|
||||||
#define TRACE_LEVEL 0
|
#define TRACE_LEVEL 10
|
||||||
|
|
||||||
#if TRACE_LEVEL // ByteCodeReading_TRACEer
|
#if TRACE_LEVEL // ByteCodeReading_TRACEer
|
||||||
#include "llvm/Assembly/Writer.h"
|
#include "llvm/Assembly/Writer.h"
|
||||||
@ -45,6 +45,7 @@ struct RawInst { // The raw fields out of the bytecode stream...
|
|||||||
};
|
};
|
||||||
|
|
||||||
class BytecodeParser : public AbstractTypeUser {
|
class BytecodeParser : public AbstractTypeUser {
|
||||||
|
string Error; // Error message string goes here...
|
||||||
public:
|
public:
|
||||||
BytecodeParser() {
|
BytecodeParser() {
|
||||||
// Define this in case we don't see a ModuleGlobalInfo block.
|
// Define this in case we don't see a ModuleGlobalInfo block.
|
||||||
@ -52,6 +53,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Module *ParseBytecode(const uchar *Buf, const uchar *EndBuf);
|
Module *ParseBytecode(const uchar *Buf, const uchar *EndBuf);
|
||||||
|
|
||||||
|
string getError() const { return Error; }
|
||||||
|
|
||||||
private: // All of this data is transient across calls to ParseBytecode
|
private: // All of this data is transient across calls to ParseBytecode
|
||||||
Module *TheModule; // Current Module being read into...
|
Module *TheModule; // Current Module being read into...
|
||||||
|
|
||||||
|
@ -33,26 +33,30 @@ int main(int argc, char **argv) {
|
|||||||
assert(InputFilenames.size() > 0 && "OneOrMore is not working");
|
assert(InputFilenames.size() > 0 && "OneOrMore is not working");
|
||||||
|
|
||||||
// TODO: TEST argv[0]
|
// TODO: TEST argv[0]
|
||||||
|
string ErrorMessage;
|
||||||
|
|
||||||
if (Verbose) cerr << "Loading '" << InputFilenames[0] << "'\n";
|
if (Verbose) cerr << "Loading '" << InputFilenames[0] << "'\n";
|
||||||
std::auto_ptr<Module> Composite(ParseBytecodeFile(InputFilenames[0]));
|
std::auto_ptr<Module> Composite(ParseBytecodeFile(InputFilenames[0],
|
||||||
|
&ErrorMessage));
|
||||||
if (Composite.get() == 0) {
|
if (Composite.get() == 0) {
|
||||||
cerr << "Error opening bytecode file: '" << InputFilenames[0] << "'\n";
|
cerr << "Error opening bytecode file: '" << InputFilenames[0] << "'";
|
||||||
|
if (ErrorMessage.size()) cerr << ": " << ErrorMessage;
|
||||||
|
cerr << endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned i = 1; i < InputFilenames.size(); ++i) {
|
for (unsigned i = 1; i < InputFilenames.size(); ++i) {
|
||||||
if (Verbose) cerr << "Loading '" << InputFilenames[i] << "'\n";
|
if (Verbose) cerr << "Loading '" << InputFilenames[i] << "'\n";
|
||||||
auto_ptr<Module> M(ParseBytecodeFile(InputFilenames[i]));
|
auto_ptr<Module> M(ParseBytecodeFile(InputFilenames[i], &ErrorMessage));
|
||||||
if (M.get() == 0) {
|
if (M.get() == 0) {
|
||||||
cerr << "Error opening bytecode file: '" << InputFilenames[i] << "'\n";
|
cerr << "Error opening bytecode file: '" << InputFilenames[i] << "'";
|
||||||
|
if (ErrorMessage.size()) cerr << ": " << ErrorMessage;
|
||||||
|
cerr << endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Verbose) cerr << "Linking in '" << InputFilenames[i] << "'\n";
|
if (Verbose) cerr << "Linking in '" << InputFilenames[i] << "'\n";
|
||||||
|
|
||||||
string ErrorMessage;
|
|
||||||
if (LinkModules(Composite.get(), M.get(), &ErrorMessage)) {
|
if (LinkModules(Composite.get(), M.get(), &ErrorMessage)) {
|
||||||
cerr << "Error linking in '" << InputFilenames[i] << "': "
|
cerr << "Error linking in '" << InputFilenames[i] << "': "
|
||||||
<< ErrorMessage << endl;
|
<< ErrorMessage << endl;
|
||||||
|
@ -33,26 +33,30 @@ int main(int argc, char **argv) {
|
|||||||
assert(InputFilenames.size() > 0 && "OneOrMore is not working");
|
assert(InputFilenames.size() > 0 && "OneOrMore is not working");
|
||||||
|
|
||||||
// TODO: TEST argv[0]
|
// TODO: TEST argv[0]
|
||||||
|
string ErrorMessage;
|
||||||
|
|
||||||
if (Verbose) cerr << "Loading '" << InputFilenames[0] << "'\n";
|
if (Verbose) cerr << "Loading '" << InputFilenames[0] << "'\n";
|
||||||
std::auto_ptr<Module> Composite(ParseBytecodeFile(InputFilenames[0]));
|
std::auto_ptr<Module> Composite(ParseBytecodeFile(InputFilenames[0],
|
||||||
|
&ErrorMessage));
|
||||||
if (Composite.get() == 0) {
|
if (Composite.get() == 0) {
|
||||||
cerr << "Error opening bytecode file: '" << InputFilenames[0] << "'\n";
|
cerr << "Error opening bytecode file: '" << InputFilenames[0] << "'";
|
||||||
|
if (ErrorMessage.size()) cerr << ": " << ErrorMessage;
|
||||||
|
cerr << endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned i = 1; i < InputFilenames.size(); ++i) {
|
for (unsigned i = 1; i < InputFilenames.size(); ++i) {
|
||||||
if (Verbose) cerr << "Loading '" << InputFilenames[i] << "'\n";
|
if (Verbose) cerr << "Loading '" << InputFilenames[i] << "'\n";
|
||||||
auto_ptr<Module> M(ParseBytecodeFile(InputFilenames[i]));
|
auto_ptr<Module> M(ParseBytecodeFile(InputFilenames[i], &ErrorMessage));
|
||||||
if (M.get() == 0) {
|
if (M.get() == 0) {
|
||||||
cerr << "Error opening bytecode file: '" << InputFilenames[i] << "'\n";
|
cerr << "Error opening bytecode file: '" << InputFilenames[i] << "'";
|
||||||
|
if (ErrorMessage.size()) cerr << ": " << ErrorMessage;
|
||||||
|
cerr << endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Verbose) cerr << "Linking in '" << InputFilenames[i] << "'\n";
|
if (Verbose) cerr << "Linking in '" << InputFilenames[i] << "'\n";
|
||||||
|
|
||||||
string ErrorMessage;
|
|
||||||
if (LinkModules(Composite.get(), M.get(), &ErrorMessage)) {
|
if (LinkModules(Composite.get(), M.get(), &ErrorMessage)) {
|
||||||
cerr << "Error linking in '" << InputFilenames[i] << "': "
|
cerr << "Error linking in '" << InputFilenames[i] << "': "
|
||||||
<< ErrorMessage << endl;
|
<< ErrorMessage << endl;
|
||||||
|
Reference in New Issue
Block a user