A first cut at normalizing the structure of sleigh error messages

This commit is contained in:
caheckman 2019-09-19 15:59:07 -04:00
parent b0609a1cb3
commit 0ed1540e3a
22 changed files with 661 additions and 408 deletions

View file

@ -15,7 +15,15 @@
*/ */
#include "pcodecompile.hh" #include "pcodecompile.hh"
ExprTree::ExprTree(VarnodeTpl *vn) string Location::format(void) const
{
ostringstream s;
s << filename << ":" << dec << lineno;
return s.str();
}
ExprTree::ExprTree(VarnodeTpl *vn)
{ {
outvn = vn; outvn = vn;
@ -305,9 +313,7 @@ vector<OpTpl *> *PcodeCompile::placeLabel(LabelSymbol *labsym)
{ // Create placeholder OpTpl for a label { // Create placeholder OpTpl for a label
if (labsym->isPlaced()) { if (labsym->isPlaced()) {
string errmsg = "Label " + labsym->getName(); reportError(getLocation(labsym), "Label '" + labsym->getName() + "' is placed more than once");
errmsg += " is placed more than once";
reportError(errmsg);
} }
labsym->setPlaced(); labsym->setPlaced();
vector<OpTpl *> *res = new vector<OpTpl *>; vector<OpTpl *> *res = new vector<OpTpl *>;
@ -335,7 +341,7 @@ vector<OpTpl *> *PcodeCompile::newOutput(bool usesLocalKey,ExprTree *rhs,string
sym = new VarnodeSymbol(*varname,tmpvn->getSpace().getSpace(),tmpvn->getOffset().getReal(),tmpvn->getSize().getReal()); // Create new symbol regardless sym = new VarnodeSymbol(*varname,tmpvn->getSpace().getSpace(),tmpvn->getOffset().getReal(),tmpvn->getSize().getReal()); // Create new symbol regardless
addSymbol(sym); addSymbol(sym);
if ((!usesLocalKey) && enforceLocalKey) if ((!usesLocalKey) && enforceLocalKey)
reportError("Must use 'local' keyword to define symbol: "+*varname); reportError(getLocation(sym), "Must use 'local' keyword to define symbol '"+*varname + "'");
delete varname; delete varname;
return ExprTree::toVector(rhs); return ExprTree::toVector(rhs);
} }
@ -633,7 +639,7 @@ vector<OpTpl *> *PcodeCompile::assignBitRange(VarnodeTpl *vn,uint4 bitoffset,uin
} }
if (errmsg.size()>0) { // Was there an error condition if (errmsg.size()>0) { // Was there an error condition
reportError(errmsg); // Report the error reportError((const Location *)0, errmsg); // Report the error
delete vn; // Clean up delete vn; // Clean up
vector<OpTpl *> *resops = rhs->ops; // Passthru old expression vector<OpTpl *> *resops = rhs->ops; // Passthru old expression
rhs->ops = (vector<OpTpl *> *)0; rhs->ops = (vector<OpTpl *> *)0;
@ -647,6 +653,7 @@ vector<OpTpl *> *PcodeCompile::assignBitRange(VarnodeTpl *vn,uint4 bitoffset,uin
ExprTree *res; ExprTree *res;
VarnodeTpl *finalout = buildTruncatedVarnode(vn,bitoffset,numbits); VarnodeTpl *finalout = buildTruncatedVarnode(vn,bitoffset,numbits);
if (finalout != (VarnodeTpl *)0) { if (finalout != (VarnodeTpl *)0) {
delete vn; // Don't keep the original Varnode object
res = createOpOutUnary(finalout,CPUI_COPY,rhs); res = createOpOutUnary(finalout,CPUI_COPY,rhs);
} }
else { else {
@ -663,7 +670,7 @@ vector<OpTpl *> *PcodeCompile::assignBitRange(VarnodeTpl *vn,uint4 bitoffset,uin
res = createOpOut(finalout,CPUI_INT_OR,res,rhs); res = createOpOut(finalout,CPUI_INT_OR,res,rhs);
} }
if (errmsg.size() > 0) if (errmsg.size() > 0)
reportError(errmsg); reportError((const Location *)0, errmsg);
vector<OpTpl *> *resops = res->ops; vector<OpTpl *> *resops = res->ops;
res->ops = (vector<OpTpl *> *)0; res->ops = (vector<OpTpl *> *)0;
delete res; delete res;
@ -737,7 +744,7 @@ ExprTree *PcodeCompile::createBitRange(SpecificSymbol *sym,uint4 bitoffset,uint4
ExprTree *res = new ExprTree(vn); ExprTree *res = new ExprTree(vn);
if (errmsg.size()>0) { // Check for error condition if (errmsg.size()>0) { // Check for error condition
reportError(errmsg); reportError(getLocation(sym), errmsg);
return res; return res;
} }
@ -774,4 +781,3 @@ VarnodeTpl *PcodeCompile::addressOf(VarnodeTpl *var,uint4 size)
delete var; delete var;
return res; return res;
} }

View file

@ -18,6 +18,17 @@
#include "slghsymbol.hh" #include "slghsymbol.hh"
class Location {
string filename;
int4 lineno;
public:
Location(void) {}
Location(const string &fname, const int4 line) { filename = fname; lineno = line; }
string getFilename(void) const { return filename; }
int4 getLineno(void) const { return lineno; }
string format(void) const;
};
struct StarQuality { struct StarQuality {
ConstTpl id; ConstTpl id;
uint4 size; uint4 size;
@ -53,7 +64,9 @@ public:
PcodeCompile(void) { defaultspace=(AddrSpace *)0; constantspace=(AddrSpace *)0; PcodeCompile(void) { defaultspace=(AddrSpace *)0; constantspace=(AddrSpace *)0;
uniqspace=(AddrSpace *)0; local_labelcount=0; enforceLocalKey=false; } uniqspace=(AddrSpace *)0; local_labelcount=0; enforceLocalKey=false; }
virtual ~PcodeCompile(void) {} virtual ~PcodeCompile(void) {}
virtual void reportError(const string &msg)=0; virtual const Location *getLocation(SleighSymbol *sym) const=0;
virtual void reportError(const Location *loc, const string &msg)=0;
virtual void reportWarning(const Location *loc, const string &msg)=0;
void resetLabelCount(void) { local_labelcount=0; } void resetLabelCount(void) { local_labelcount=0; }
void setDefaultSpace(AddrSpace *spc) { defaultspace = spc; } void setDefaultSpace(AddrSpace *spc) { defaultspace = spc; }
void setConstantSpace(AddrSpace *spc) { constantspace = spc; } void setConstantSpace(AddrSpace *spc) { constantspace = spc; }

View file

@ -82,7 +82,9 @@ public:
void setResult(ConstructTpl *res) { result = res; } void setResult(ConstructTpl *res) { result = res; }
ConstructTpl *releaseResult(void) { ConstructTpl *res = result; result = (ConstructTpl *)0; return res; } ConstructTpl *releaseResult(void) { ConstructTpl *res = result; result = (ConstructTpl *)0; return res; }
virtual ~PcodeSnippet(void); virtual ~PcodeSnippet(void);
virtual void reportError(const string &msg); virtual const Location *getLocation(SleighSymbol *sym) const { return (const Location *)0; }
virtual void reportError(const Location *loc, const string &msg);
virtual void reportWarning(const Location *loc, const string &msg) {}
bool hasErrors(void) const { return (errorcount != 0); } bool hasErrors(void) const { return (errorcount != 0); }
const string getErrorMessage(void) const { return firsterror; } const string getErrorMessage(void) const { return firsterror; }
void setUniqueBase(uintb val) { tempbase = val; } void setUniqueBase(uintb val) { tempbase = val; }

View file

@ -650,7 +650,7 @@ void PcodeSnippet::addSymbol(SleighSymbol *sym)
res = tree.insert( sym ); res = tree.insert( sym );
if (!res.second) { if (!res.second) {
reportError("Duplicate symbol name: "+sym->getName()); reportError((const Location *)0,"Duplicate symbol name: "+sym->getName());
delete sym; // Symbol is unattached to anything else delete sym; // Symbol is unattached to anything else
} }
} }
@ -712,7 +712,7 @@ PcodeSnippet::~PcodeSnippet(void)
} }
} }
void PcodeSnippet::reportError(const string &msg) void PcodeSnippet::reportError(const Location *loc, const string &msg)
{ {
if (errorcount == 0) if (errorcount == 0)
@ -779,11 +779,11 @@ int4 PcodeSnippet::lex(void)
pcode = this; // Setup global object for yyparse pcode = this; // Setup global object for yyparse
int4 res = yyparse(); int4 res = yyparse();
if (res != 0) { if (res != 0) {
reportError("Syntax error"); reportError((const Location *)0,"Syntax error");
return false; return false;
} }
if (!PcodeCompile::propagateSize(result)) { if (!PcodeCompile::propagateSize(result)) {
reportError("Could not resolve at least 1 variable size"); reportError((const Location *)0,"Could not resolve at least 1 variable size");
return false; return false;
} }
return true; return true;
@ -803,6 +803,6 @@ int yylex(void) {
int yyerror(const char *s) int yyerror(const char *s)
{ {
pcode->reportError(s); pcode->reportError((const Location *)0,s);
return 0; return 0;
} }

View file

@ -183,9 +183,10 @@ SubtableSymbol *WithBlock::getCurrentSubtable(const list<WithBlock> &stack)
return (SubtableSymbol *)0; return (SubtableSymbol *)0;
} }
ConsistencyChecker::ConsistencyChecker(SubtableSymbol *rt,bool un,bool warndead) ConsistencyChecker::ConsistencyChecker(SleighCompile *sleigh,SubtableSymbol *rt,bool un,bool warndead)
{ {
slgh = sleigh;
root_symbol = rt; root_symbol = rt;
unnecessarypcode = 0; unnecessarypcode = 0;
readnowrite = 0; readnowrite = 0;
@ -194,6 +195,16 @@ ConsistencyChecker::ConsistencyChecker(SubtableSymbol *rt,bool un,bool warndead)
printdeadwarning = warndead; printdeadwarning = warndead;
} }
void ConsistencyChecker::reportError(const Location *loc, const string &msg)
{
slgh->reportError(loc, msg);
}
void ConsistencyChecker::reportWarning(const Location *loc, const string &msg)
{
slgh->reportWarning(loc, msg);
}
int4 ConsistencyChecker::recoverSize(const ConstTpl &sizeconst,Constructor *ct) int4 ConsistencyChecker::recoverSize(const ConstTpl &sizeconst,Constructor *ct)
{ {
@ -231,9 +242,10 @@ void ConsistencyChecker::dealWithUnnecessaryExt(OpTpl *op,Constructor *ct)
{ // Deal with detected extension (SEXT or ZEXT) where the { // Deal with detected extension (SEXT or ZEXT) where the
// input size is the same as the output size // input size is the same as the output size
if (printextwarning) { if (printextwarning) {
cerr << "Unnecessary "; ostringstream msg;
printOpName(cerr,op); msg << "Unnecessary ";
cerr << " in constructor starting at line " << dec << ct->getLineno() << endl; printOpName(msg,op);
reportWarning(slgh->getLocation(ct), msg.str());
} }
op->setOpcode(CPUI_COPY); // Equivalent to copy op->setOpcode(CPUI_COPY); // Equivalent to copy
unnecessarypcode += 1; unnecessarypcode += 1;
@ -243,9 +255,10 @@ void ConsistencyChecker::dealWithUnnecessaryTrunc(OpTpl *op,Constructor *ct)
{ {
if (printextwarning) { if (printextwarning) {
cerr << "Unnecessary "; ostringstream msg;
printOpName(cerr,op); msg << "Unnecessary ";
cerr << " in constructor starting at line " << dec << ct->getLineno() << endl; printOpName(msg,op);
reportWarning(slgh->getLocation(ct), msg.str());
} }
op->setOpcode(CPUI_COPY); // Equivalent to copy op->setOpcode(CPUI_COPY); // Equivalent to copy
op->removeInput(1); op->removeInput(1);
@ -260,7 +273,7 @@ bool ConsistencyChecker::checkOpMisuse(OpTpl *op,Constructor *ct)
{ {
VarnodeTpl *vn = op->getIn(1); VarnodeTpl *vn = op->getIn(1);
if (vn->getSpace().isConstSpace() && vn->getOffset().isZero()) { if (vn->getSpace().isConstSpace() && vn->getOffset().isZero()) {
cerr << "Unsigned comparison with zero is always false in constructor starting at line " << dec << ct->getLineno() << endl; reportError(slgh->getLocation(ct), "Unsigned comparison with zero is always false");
} }
} }
break; break;
@ -771,21 +784,23 @@ void ConsistencyChecker::printOpError(OpTpl *op,Constructor *ct,int4 err1,int4 e
op2 = getOperandSymbol(err2,op,ct); op2 = getOperandSymbol(err2,op,ct);
else else
op2 = (OperandSymbol *)0; op2 = (OperandSymbol *)0;
cerr << "Size restriction error in table \"" << sym->getName() << "\"" << endl;
cerr << " in constructor starting at line " << dec << ct->getLineno() << endl; ostringstream msgBuilder;
if ((op1 != (OperandSymbol *)0)&&(op2 != (OperandSymbol *)0)) {
cerr << " Problem with \"" << op1->getName(); msgBuilder << "Size restriction error in table '" << sym->getName() << "'" << endl;
cerr << "\" and \"" << op2->getName() << "\""; if ((op1 != (OperandSymbol *)0)&&(op2 != (OperandSymbol *)0))
} msgBuilder << " Problem with operands '" << op1->getName() << "' and '" << op2->getName() << "'";
else if (op1 != (OperandSymbol *)0) else if (op1 != (OperandSymbol *)0)
cerr << " Problem with \"" << op1->getName() << "\""; msgBuilder << " Problem with operand 1 '" << op1->getName() << "'";
else if (op2 != (OperandSymbol *)0) else if (op2 != (OperandSymbol *)0)
cerr << " Problem with \"" << op2->getName() << "\""; msgBuilder << " Problem with operand 2 '" << op2->getName() << "'";
else else
cerr << " Problem"; msgBuilder << " Problem";
cerr << " in "; msgBuilder << " in ";
printOpName(cerr,op); printOpName(msgBuilder,op);
cerr << " operator" << endl << " " << msg << endl; msgBuilder << " operator" << endl << " " << msg;
reportError(slgh->getLocation(ct), msgBuilder.str());
} }
bool ConsistencyChecker::checkConstructorSection(Constructor *ct,ConstructTpl *cttpl) bool ConsistencyChecker::checkConstructorSection(Constructor *ct,ConstructTpl *cttpl)
@ -878,8 +893,10 @@ bool ConsistencyChecker::checkSubtable(SubtableSymbol *sym)
HandleTpl *exportres = ct->getTempl()->getResult(); HandleTpl *exportres = ct->getTempl()->getResult();
if (exportres != (HandleTpl *)0) { if (exportres != (HandleTpl *)0) {
if (seenemptyexport && (!seennonemptyexport)) { if (seenemptyexport && (!seennonemptyexport)) {
cerr << "Table " << sym->getName() << " exports inconsistently" << endl; ostringstream msg;
cerr << "Constructor starting at line " << dec << ct->getLineno() << " is first inconsistency" << endl; msg << "Table '" << sym->getName() << "' exports inconsistently; ";
msg << "Constructor starting at line " << dec << ct->getLineno() << " is first inconsistency";
reportError(slgh->getLocation(ct), msg.str());
testresult = false; testresult = false;
} }
seennonemptyexport = true; seennonemptyexport = true;
@ -887,23 +904,28 @@ bool ConsistencyChecker::checkSubtable(SubtableSymbol *sym)
if (tablesize == 0) if (tablesize == 0)
tablesize = exsize; tablesize = exsize;
if ((exsize!=0)&&(exsize != tablesize)) { if ((exsize!=0)&&(exsize != tablesize)) {
cerr << "Table " << sym->getName() << " has inconsistent export size." << endl; ostringstream msg;
cerr << "Constructor starting at line " << dec << ct->getLineno() << " is first conflict" << endl; msg << "Table '" << sym->getName() << "' has inconsistent export size; ";
msg << "Constructor starting at line " << dec << ct->getLineno() << " is first conflict";
reportError(slgh->getLocation(ct), msg.str());
testresult = false; testresult = false;
} }
} }
else { else {
if (seennonemptyexport && (!seenemptyexport)) { if (seennonemptyexport && (!seenemptyexport)) {
cerr << "Table " << sym->getName() << " exports inconsistently" << endl; ostringstream msg;
cerr << "Constructor starting at line " << dec << ct->getLineno() << " is first inconsistency" << endl; msg << "Table '" << sym->getName() << "' exports inconsistently; ";
msg << "Constructor starting at line " << dec << ct->getLineno() << " is first inconsistency";
reportError(slgh->getLocation(ct), msg.str());
testresult = false; testresult = false;
} }
seenemptyexport = true; seenemptyexport = true;
} }
} }
if (seennonemptyexport) { if (seennonemptyexport) {
if (tablesize == 0) if (tablesize == 0) {
cerr << "Warning: Table " << sym->getName() << " exports size 0" << endl; reportWarning(slgh->getLocation(sym), "Table '" + sym->getName() + "' exports size 0");
}
sizemap[sym] = tablesize; // Remember recovered size sizemap[sym] = tablesize; // Remember recovered size
} }
else else
@ -1212,11 +1234,11 @@ void ConsistencyChecker::checkUnusedTemps(Constructor *ct,const map<uintb,Optimi
const OptimizeRecord &currec( (*iter).second ); const OptimizeRecord &currec( (*iter).second );
if (currec.readcount == 0) { if (currec.readcount == 0) {
if (printdeadwarning) if (printdeadwarning)
cerr << "Warning: temporary is written but not read in constructor starting at line " << dec << ct->getLineno() << endl; reportWarning(slgh->getLocation(ct), "Temporary is written but not read");
writenoread += 1; writenoread += 1;
} }
else if (currec.writecount == 0) { else if (currec.writecount == 0) {
cerr << "Error: temporary is read but not written in constructor starting at line " << dec << ct->getLineno() << endl; reportError(slgh->getLocation(ct), "Temporary is read but not written");
readnowrite += 1; readnowrite += 1;
} }
++iter; ++iter;
@ -1318,10 +1340,10 @@ void MacroBuilder::free(void)
params.clear(); params.clear();
} }
void MacroBuilder::reportError(const string &val) void MacroBuilder::reportError(const Location* loc, const string &val)
{ {
slgh->reportError(val,false); slgh->reportError(loc, val);
haserror = true; haserror = true;
} }
@ -1351,7 +1373,7 @@ bool MacroBuilder::transferOp(OpTpl *op,vector<HandleTpl *> &params)
if (outvn != (VarnodeTpl *)0) { if (outvn != (VarnodeTpl *)0) {
plus = outvn->transfer(params); plus = outvn->transfer(params);
if (plus >= 0) { if (plus >= 0) {
reportError("Cannot currently assign to bitrange of macro parameter that is a temporary"); reportError((const Location *)0, "Cannot currently assign to bitrange of macro parameter that is a temporary");
return false; return false;
} }
} }
@ -1365,7 +1387,7 @@ bool MacroBuilder::transferOp(OpTpl *op,vector<HandleTpl *> &params)
plus = vn->transfer(params); plus = vn->transfer(params);
if (plus >= 0) { if (plus >= 0) {
if (!hasrealsize) { if (!hasrealsize) {
reportError("Problem with bit range operator in macro"); reportError((const Location *)0, "Problem with bit range operator in macro");
return false; return false;
} }
uintb newtemp = slgh->getUniqueAddr(); // Generate a new temporary location uintb newtemp = slgh->getUniqueAddr(); // Generate a new temporary location
@ -1441,10 +1463,22 @@ uintb SleighPcode::allocateTemp(void)
return compiler->getUniqueAddr(); return compiler->getUniqueAddr();
} }
void SleighPcode::reportError(const string &msg) const Location *SleighPcode::getLocation(SleighSymbol *sym) const
{ {
return compiler->reportError(msg,true); return compiler->getLocation(sym);
}
void SleighPcode::reportError(const Location *loc, const string &msg)
{
return compiler->reportError(loc, msg);
}
void SleighPcode::reportWarning(const Location *loc, const string &msg)
{
return compiler->reportWarning(loc, msg);
} }
void SleighPcode::addSymbol(SleighSymbol *sym) void SleighPcode::addSymbol(SleighSymbol *sym)
@ -1506,7 +1540,7 @@ int4 SleighCompile::calcContextVarLayout(int4 start,int4 sz,int4 numbits)
int4 maxbits; int4 maxbits;
if ((sym->getSize()) % 4 != 0) if ((sym->getSize()) % 4 != 0)
reportError("Invalid size of context register: "+sym->getName()+" : must be a multiple of 4 bytes",false); reportError(getCurrentLocation(), "Invalid size of context register '"+sym->getName()+"': must be a multiple of 4 bytes");
maxbits = sym->getSize() * 8 -1; maxbits = sym->getSize() * 8 -1;
i = 0; i = 0;
while(i<sz) { while(i<sz) {
@ -1515,9 +1549,9 @@ int4 SleighCompile::calcContextVarLayout(int4 start,int4 sz,int4 numbits)
int4 min = qual->low; int4 min = qual->low;
int4 max = qual->high; int4 max = qual->high;
if ((max - min) > (8*sizeof(uintm))) if ((max - min) > (8*sizeof(uintm)))
reportError("Size of bitfield " + qual->name + " larger than 32-bits",false); reportError(getCurrentLocation(), "Size of bitfield '" + qual->name + "' larger than 32 bits");
if (max > maxbits) if (max > maxbits)
reportError("Scope of bitfield " + qual->name + " extends beyond the size of context register",false); reportError(getCurrentLocation(), "Scope of bitfield '" + qual->name + "' extends beyond the size of context register");
j = i+1; j = i+1;
// Find union of fields overlapping with first field // Find union of fields overlapping with first field
while(j<sz) { while(j<sz) {
@ -1563,17 +1597,27 @@ void SleighCompile::buildDecisionTrees(void)
for(int4 i=0;i<tables.size();++i) for(int4 i=0;i<tables.size();++i)
tables[i]->buildDecisionTree(props); tables[i]->buildDecisionTree(props);
const vector<string> &ierrors( props.getIdentErrors() ); const vector<pair<Constructor*, Constructor*>> &ierrors( props.getIdentErrors() );
for(int4 i=0;i<ierrors.size();++i) { if (ierrors.size() != 0) {
errors += 1; string identMsg = "Constructor has identical pattern to constructor at ";
cerr << ierrors[i]; for(int4 i=0;i<ierrors.size();++i) {
errors += 1;
const Location* locA = getLocation(ierrors[i].first);
const Location* locB = getLocation(ierrors[i].second);
reportError(locA, identMsg + locB->format());
reportError(locB, identMsg + locA->format());
}
} }
if (!lenientconflicterrors) { const vector<pair<Constructor *, Constructor*>> &cerrors( props.getConflictErrors() );
const vector<string> &cerrors( props.getConflictErrors() ); if (!lenientconflicterrors && cerrors.size() != 0) {
string conflictMsg = "Constructor pattern cannot be distinguished from constructor at ";
for(int4 i=0;i<cerrors.size();++i) { for(int4 i=0;i<cerrors.size();++i) {
errors += 1; errors += 1;
cerr << cerrors[i]; const Location* locA = getLocation(cerrors[i].first);
const Location* locB = getLocation(cerrors[i].second);
reportError(locA, conflictMsg + locB->format());
reportError(locB, conflictMsg + locA->format());
} }
} }
} }
@ -1582,23 +1626,28 @@ void SleighCompile::buildPatterns(void)
{ {
if (root == 0) { if (root == 0) {
reportError("No patterns to match.",false); reportError(nullptr, "No patterns to match.");
return; return;
} }
root->buildPattern(cerr); // This should recursively hit everything ostringstream msg;
if (root->isError()) errors += 1; root->buildPattern(msg); // This should recursively hit everything
if (root->isError()) {
reportError(getLocation(root), msg.str());
errors += 1;
}
for(int4 i=0;i<tables.size();++i) { for(int4 i=0;i<tables.size();++i) {
if (tables[i]->isError()) if (tables[i]->isError())
errors += 1; errors += 1;
if (tables[i]->getPattern() == (TokenPattern *)0) if (tables[i]->getPattern() == (TokenPattern *)0) {
reportWarning("Unreferenced table: "+tables[i]->getName(),false); reportWarning(getLocation(tables[i]), "Unreferenced table '"+tables[i]->getName() + "'");
}
} }
} }
void SleighCompile::checkConsistency(void) void SleighCompile::checkConsistency(void)
{ {
ConsistencyChecker checker(root,warnunnecessarypcode,warndeadtemps); ConsistencyChecker checker(this, root,warnunnecessarypcode,warndeadtemps);
if (!checker.test()) { if (!checker.test()) {
errors += 1; errors += 1;
@ -1609,9 +1658,11 @@ void SleighCompile::checkConsistency(void)
return; return;
} }
if ((!warnunnecessarypcode)&&(checker.getNumUnnecessaryPcode() > 0)) { if ((!warnunnecessarypcode)&&(checker.getNumUnnecessaryPcode() > 0)) {
cerr << dec << checker.getNumUnnecessaryPcode(); ostringstream msg;
cerr << " unnecessary extensions/truncations were converted to copies" << endl; msg << dec << checker.getNumUnnecessaryPcode();
cerr << "Use -u switch to list each individually" << endl; msg << " unnecessary extensions/truncations were converted to copies" << endl;
msg << "Use -u switch to list each individually";
reportInfo(msg.str());
} }
checker.optimizeAll(); checker.optimizeAll();
if (checker.getNumReadNoWrite() > 0) { if (checker.getNumReadNoWrite() > 0) {
@ -1619,9 +1670,11 @@ void SleighCompile::checkConsistency(void)
return; return;
} }
if ((!warndeadtemps)&&(checker.getNumWriteNoRead() > 0)) { if ((!warndeadtemps)&&(checker.getNumWriteNoRead() > 0)) {
cerr << dec << checker.getNumWriteNoRead(); ostringstream msg;
cerr << " operations wrote to temporaries that were not read" << endl; msg << dec << checker.getNumWriteNoRead();
cerr << "Use -t switch to list each individually" << endl; msg << " operations wrote to temporaries that were not read" << endl;
msg << "Use -t switch to list each individually";
reportInfo(msg.str());
} }
} }
@ -1659,10 +1712,10 @@ bool SleighCompile::checkLocalExports(Constructor *ct)
if (collideOperand >= 0) { if (collideOperand >= 0) {
noCollisions = false; noCollisions = false;
if (warnalllocalcollisions) { if (warnalllocalcollisions) {
cerr << "Possible collision with symbols "; reportWarning(getLocation(ct), "Possible operand collision between symbols '"
cerr << ct->getOperand(collideOperand)->getName(); + ct->getOperand(collideOperand)->getName()
cerr << " and " << ct->getOperand(i)->getName(); + "' and '"
cerr << " in constructor starting at line " << dec << ct->getLineno() << endl; + ct->getOperand(i)->getName() + "'");
} }
break; // Don't continue break; // Don't continue
} }
@ -1687,9 +1740,11 @@ void SleighCompile::checkLocalCollisions(void)
sym = tables[i]; sym = tables[i];
} }
if (collisionCount > 0) { if (collisionCount > 0) {
cerr << "WARNING: " << dec << collisionCount << " constructors with local collisions between operands" << endl; ostringstream msg;
msg << dec << collisionCount << " constructors with local collisions between operands";
if (!warnalllocalcollisions) if (!warnalllocalcollisions)
cerr << "Use -c switch to list each individually" << endl; msg << endl << "Use -c switch to list each individually";
reportInfo(msg.str());
} }
} }
@ -1699,28 +1754,30 @@ void SleighCompile::checkNops(void)
if (noplist.size() > 0) { if (noplist.size() > 0) {
if (warnallnops) { if (warnallnops) {
for(int4 i=0;i<noplist.size();++i) for(int4 i=0;i<noplist.size();++i)
cerr << noplist[i] << endl; reportWarning(noplist[i]);
} }
cerr << dec << (int4)noplist.size() << " NOP constructors found" << endl; ostringstream msg;
msg << dec << noplist.size() << " NOP constructors found";
if (!warnallnops) if (!warnallnops)
cerr << "Use -n switch to list each individually" << endl; msg << endl << "Use -n switch to list each individually";
reportInfo(msg.str());
} }
} }
string SleighCompile::checkSymbols(SymbolScope *scope) string SleighCompile::checkSymbols(SymbolScope *scope)
{ // Make sure label symbols are used properly { // Make sure label symbols are used properly
ostringstream s; ostringstream msg;
SymbolTree::const_iterator iter; SymbolTree::const_iterator iter;
for(iter=scope->begin();iter!=scope->end();++iter) { for(iter=scope->begin();iter!=scope->end();++iter) {
LabelSymbol *sym = (LabelSymbol *)*iter; LabelSymbol *sym = (LabelSymbol *)*iter;
if (sym->getType() != SleighSymbol::label_symbol) continue; if (sym->getType() != SleighSymbol::label_symbol) continue;
if (sym->getRefCount() == 0) if (sym->getRefCount() == 0)
s << " Label <" << sym->getName() << "> was placed but not used\n"; msg << " Label <" << sym->getName() << "> was placed but not used" << endl;
else if (!sym->isPlaced()) else if (!sym->isPlaced())
s << " Label <" << sym->getName() << "> was referenced but never placed\n"; msg << " Label <" << sym->getName() << "> was referenced but never placed" << endl;
} }
return s.str(); return msg.str();
} }
void SleighCompile::addSymbol(SleighSymbol *sym) void SleighCompile::addSymbol(SleighSymbol *sym)
@ -1728,33 +1785,79 @@ void SleighCompile::addSymbol(SleighSymbol *sym)
{ // Make sure symbol table errors are caught { // Make sure symbol table errors are caught
try { try {
symtab.addSymbol(sym); symtab.addSymbol(sym);
symbolLocationMap[sym] = *getCurrentLocation();
} }
catch(SleighError &err) { catch(SleighError &err) {
reportError(err.explain,true); reportError(err.explain);
} }
} }
void SleighCompile::reportError(const string &msg,bool includeline) const Location *SleighCompile::getLocation(Constructor *ctor) const
{ {
cerr << "Error in " << filename.back() << ' '; return &ctorLocationMap.at(ctor);
if (includeline) }
cerr << "at line " << dec << lineno.back() << ": ";
cerr << msg << endl; const Location *SleighCompile::getLocation(SleighSymbol *sym) const
{
return &symbolLocationMap.at(sym);
}
const Location *SleighCompile::getCurrentLocation(void) const
{
// Update the location cache field
currentLocCache = Location(filename.back(), lineno.back());
return &currentLocCache;
}
string SleighCompile::formatStatusMessage(const Location* loc, const string &msg)
{
ostringstream s;
if (loc != (Location*)0) {
s << loc->format();
s << ": ";
}
s << msg;
return s.str();
}
void SleighCompile::reportError(const Location* loc, const string &msg)
{
reportError(formatStatusMessage(loc, msg));
}
void SleighCompile::reportError(const string &msg)
{
cerr << "ERROR " << msg << endl;
errors += 1; errors += 1;
if (errors >50) { if (errors > 1000000) {
cerr << "Too many errors: Aborting" << endl; cerr << "Too many errors: Aborting" << endl;
exit(2); exit(2);
} }
} }
void SleighCompile::reportWarning(const string &msg,bool includeline) void SleighCompile::reportWarning(const Location* loc, const string &msg)
{
reportWarning(formatStatusMessage(loc, msg));
}
void SleighCompile::reportWarning(const string &msg)
{ {
cerr << "Warning in " << filename.back() << ' '; cerr << "WARNING " << msg << endl;
if (includeline) }
cerr << "at line " << dec << lineno.back() << ": ";
cerr << msg << endl; void SleighCompile::reportInfo(const Location* loc, const string &msg)
{
reportInfo(formatStatusMessage(loc, msg));
}
void SleighCompile::reportInfo(const string &msg)
{
cerr << "INFO " << msg << endl;
} }
uintb SleighCompile::getUniqueAddr(void) uintb SleighCompile::getUniqueAddr(void)
@ -1770,7 +1873,7 @@ void SleighCompile::process(void)
{ // Do all post processing on the parsed data structures { // Do all post processing on the parsed data structures
checkNops(); checkNops();
if (getDefaultSpace() == (AddrSpace *)0) if (getDefaultSpace() == (AddrSpace *)0)
reportError("No default space specified",false); reportError("No default space specified");
if (errors>0) return; if (errors>0) return;
checkConsistency(); checkConsistency();
if (errors>0) return; if (errors>0) return;
@ -1783,8 +1886,7 @@ void SleighCompile::process(void)
try { try {
buildXrefs(); // Make sure we can build crossrefs properly buildXrefs(); // Make sure we can build crossrefs properly
} catch(SleighError &err) { } catch(SleighError &err) {
cerr << err.explain << endl; reportError(err.explain);
errors += 1;
return; return;
} }
checkUniqueAllocation(); checkUniqueAllocation();
@ -1893,7 +1995,7 @@ TokenSymbol *SleighCompile::defineToken(string *name,uintb *sz)
uint4 size = *sz; uint4 size = *sz;
delete sz; delete sz;
if ((size&7)!=0) { if ((size&7)!=0) {
reportError(*name+"token size must be multiple of 8",true); reportError(getCurrentLocation(), "'" + *name + "': token size must be multiple of 8");
size = (size/8)+1; size = (size/8)+1;
} }
else else
@ -1928,7 +2030,7 @@ void SleighCompile::newSpace(SpaceQuality *qual)
{ {
if (qual->size == 0) { if (qual->size == 0) {
reportError("Space definition missing size attribute",true); reportError(getCurrentLocation(), "Space definition '" + qual->name + "' missing size attribute");
delete qual; delete qual;
return; return;
} }
@ -1938,7 +2040,7 @@ void SleighCompile::newSpace(SpaceQuality *qual)
insertSpace(spc); insertSpace(spc);
if (qual->isdefault) { if (qual->isdefault) {
if (getDefaultSpace() != (AddrSpace *)0) if (getDefaultSpace() != (AddrSpace *)0)
reportError("Multiple default spaces",true); reportError(getCurrentLocation(), "Multiple default spaces -- '" + getDefaultSpace()->getName() + "', '" + qual->name + "'");
else { else {
setDefaultSpace(spc->getIndex()); // Make the flagged space the default setDefaultSpace(spc->getIndex()); // Make the flagged space the default
pcode.setDefaultSpace(spc); pcode.setDefaultSpace(spc);
@ -1955,7 +2057,7 @@ SectionSymbol *SleighCompile::newSectionSymbol(const string &nm)
try { try {
symtab.addGlobalSymbol(sym); symtab.addGlobalSymbol(sym);
} catch(SleighError &err) { } catch(SleighError &err) {
reportError(err.explain,true); reportError(getCurrentLocation(), err.explain);
} }
sections.push_back(sym); sections.push_back(sym);
numSections = sections.size(); numSections = sections.size();
@ -1995,11 +2097,11 @@ void SleighCompile::defineBitrange(string *name,VarnodeSymbol *sym,uint4 bitoffs
delete name; delete name;
uint4 size = 8*sym->getSize(); // Number of bits uint4 size = 8*sym->getSize(); // Number of bits
if (numb == 0) { if (numb == 0) {
reportError("Size of bitrange is zero for: "+namecopy,true); reportError(getCurrentLocation(), "'" + namecopy + "': size of bitrange is zero");
return; return;
} }
if ((bitoffset >= size)||((bitoffset+numb)>size)) { if ((bitoffset >= size)||((bitoffset+numb)>size)) {
reportError("Bad bitrange for: "+namecopy,true); reportError(getCurrentLocation(), "'" + namecopy + "': bad bitrange");
return; return;
} }
if ((bitoffset%8 == 0)&&(numb%8 == 0)) { if ((bitoffset%8 == 0)&&(numb%8 == 0)) {
@ -2050,13 +2152,13 @@ void SleighCompile::attachValues(vector<SleighSymbol *> *symlist,vector<intb> *n
{ {
SleighSymbol *dupsym = dedupSymbolList(symlist); SleighSymbol *dupsym = dedupSymbolList(symlist);
if (dupsym != (SleighSymbol *)0) if (dupsym != (SleighSymbol *)0)
reportWarning("\"attach values\" list contains duplicate entries: "+dupsym->getName(),true); reportWarning(getCurrentLocation(), "'attach values' list contains duplicate entries: "+dupsym->getName());
for(int4 i=0;i<symlist->size();++i) { for(int4 i=0;i<symlist->size();++i) {
ValueSymbol *sym = (ValueSymbol *)(*symlist)[i]; ValueSymbol *sym = (ValueSymbol *)(*symlist)[i];
if (sym == (ValueSymbol *)0) continue; if (sym == (ValueSymbol *)0) continue;
PatternValue *patval = sym->getPatternValue(); PatternValue *patval = sym->getPatternValue();
if (patval->maxValue() + 1 != numlist->size()) { if (patval->maxValue() + 1 != numlist->size()) {
reportError("Attach value " + sym->getName() + " is wrong size for list", true); reportError(getCurrentLocation(), "Attach value '" + sym->getName() + "' is wrong size for list");
} }
symtab.replaceSymbol(sym, new ValueMapSymbol(sym->getName(),patval,*numlist)); symtab.replaceSymbol(sym, new ValueMapSymbol(sym->getName(),patval,*numlist));
} }
@ -2069,13 +2171,13 @@ void SleighCompile::attachNames(vector<SleighSymbol *> *symlist,vector<string> *
{ {
SleighSymbol *dupsym = dedupSymbolList(symlist); SleighSymbol *dupsym = dedupSymbolList(symlist);
if (dupsym != (SleighSymbol *)0) if (dupsym != (SleighSymbol *)0)
reportWarning("\"attach names\" list contains duplicate entries: "+dupsym->getName(),true); reportWarning(getCurrentLocation(), "'attach names' list contains duplicate entries: "+dupsym->getName());
for(int4 i=0;i<symlist->size();++i) { for(int4 i=0;i<symlist->size();++i) {
ValueSymbol *sym = (ValueSymbol *)(*symlist)[i]; ValueSymbol *sym = (ValueSymbol *)(*symlist)[i];
if (sym == (ValueSymbol *)0) continue; if (sym == (ValueSymbol *)0) continue;
PatternValue *patval = sym->getPatternValue(); PatternValue *patval = sym->getPatternValue();
if (patval->maxValue() + 1 != names->size()) { if (patval->maxValue() + 1 != names->size()) {
reportError("Attach name " + sym->getName() + " is wrong size for list", true); reportError(getCurrentLocation(), "Attach name '" + sym->getName() + "' is wrong size for list");
} }
symtab.replaceSymbol(sym,new NameSymbol(sym->getName(),patval,*names)); symtab.replaceSymbol(sym,new NameSymbol(sym->getName(),patval,*names));
} }
@ -2088,13 +2190,13 @@ void SleighCompile::attachVarnodes(vector<SleighSymbol *> *symlist,vector<Sleigh
{ {
SleighSymbol *dupsym = dedupSymbolList(symlist); SleighSymbol *dupsym = dedupSymbolList(symlist);
if (dupsym != (SleighSymbol *)0) if (dupsym != (SleighSymbol *)0)
reportWarning("\"attach variables\" list contains duplicate entries: "+dupsym->getName(),true); reportWarning(getCurrentLocation(), "'attach variables' list contains duplicate entries: "+dupsym->getName());
for(int4 i=0;i<symlist->size();++i) { for(int4 i=0;i<symlist->size();++i) {
ValueSymbol *sym = (ValueSymbol *)(*symlist)[i]; ValueSymbol *sym = (ValueSymbol *)(*symlist)[i];
if (sym == (ValueSymbol *)0) continue; if (sym == (ValueSymbol *)0) continue;
PatternValue *patval = sym->getPatternValue(); PatternValue *patval = sym->getPatternValue();
if (patval->maxValue() + 1 != varlist->size()) { if (patval->maxValue() + 1 != varlist->size()) {
reportError("Attach varnode " + sym->getName() + " is wrong size for list", true); reportError(getCurrentLocation(), "Attach varnode '" + sym->getName() + "' is wrong size for list");
} }
int4 sz = 0; int4 sz = 0;
for(int4 j=0;j<varlist->size();++j) { for(int4 j=0;j<varlist->size();++j) {
@ -2103,7 +2205,9 @@ void SleighCompile::attachVarnodes(vector<SleighSymbol *> *symlist,vector<Sleigh
if (sz == 0) if (sz == 0)
sz = vsym->getFixedVarnode().size; sz = vsym->getFixedVarnode().size;
else if (sz != vsym->getFixedVarnode().size) { else if (sz != vsym->getFixedVarnode().size) {
reportError("Attach statement contains varnodes of different sizes",true); ostringstream msg;
msg << "Attach statement contains varnodes of different sizes -- " << dec << sz << " != " << dec << vsym->getFixedVarnode().size;
reportError(getCurrentLocation(), msg.str());
break; break;
} }
} }
@ -2160,7 +2264,7 @@ void SleighCompile::defineOperand(OperandSymbol *sym,PatternExpression *patexp)
// the operand's offset is irrelevant // the operand's offset is irrelevant
} }
catch(SleighError &err) { catch(SleighError &err) {
reportError(err.explain,true); reportError(getCurrentLocation(), err.explain);
PatternExpression::release(patexp); PatternExpression::release(patexp);
} }
} }
@ -2184,7 +2288,7 @@ PatternEquation *SleighCompile::defineInvisibleOperand(TripleSymbol *sym)
} }
} }
catch(SleighError &err) { catch(SleighError &err) {
reportError(err.explain,true); reportError(getCurrentLocation(), err.explain);
} }
return res; return res;
} }
@ -2194,7 +2298,7 @@ void SleighCompile::selfDefine(OperandSymbol *sym)
{ // Define operand as global symbol of same name { // Define operand as global symbol of same name
TripleSymbol *glob = dynamic_cast<TripleSymbol *>(symtab.findSymbol(sym->getName(),1)); TripleSymbol *glob = dynamic_cast<TripleSymbol *>(symtab.findSymbol(sym->getName(),1));
if (glob == (TripleSymbol *)0) { if (glob == (TripleSymbol *)0) {
reportError(sym->getName()+": No matching global symbol",true); reportError(getCurrentLocation(), "No matching global symbol '" + sym->getName() + "'");
return; return;
} }
SleighSymbol::symbol_type tp = glob->getType(); SleighSymbol::symbol_type tp = glob->getType();
@ -2206,7 +2310,7 @@ void SleighCompile::selfDefine(OperandSymbol *sym)
sym->defineOperand(glob); sym->defineOperand(glob);
} }
catch(SleighError &err) { catch(SleighError &err) {
reportError(err.explain,true); reportError(getCurrentLocation(), err.explain);
} }
} }
@ -2306,12 +2410,9 @@ vector<OpTpl *> *SleighCompile::createMacroUse(MacroSymbol *sym,vector<ExprTree
{ // Create macro build directive, given symbol and parameters { // Create macro build directive, given symbol and parameters
if (sym->getNumOperands() != param->size()) { if (sym->getNumOperands() != param->size()) {
string errmsg = "Invocation of macro \"" + sym->getName(); bool tooManyParams = param->size() > sym->getNumOperands();
if (param->size() > sym->getNumOperands()) string errmsg = "Invocation of macro '" + sym->getName() + "' passes too " + (tooManyParams ? "many" : "few") + " parameters";
errmsg += "\" passes too many parameters"; reportError(getCurrentLocation(), errmsg);
else
errmsg += "\" passes too few parameters";
reportError(errmsg,true);
return new vector<OpTpl *>; return new vector<OpTpl *>;
} }
compareMacroParams(sym,*param); compareMacroParams(sym,*param);
@ -2394,6 +2495,7 @@ Constructor *SleighCompile::createConstructor(SubtableSymbol *sym)
curmacro = (MacroSymbol *)0; // Not currently defining a macro curmacro = (MacroSymbol *)0; // Not currently defining a macro
curct = new Constructor(sym); curct = new Constructor(sym);
curct->setLineno(lineno.back()); curct->setLineno(lineno.back());
ctorLocationMap[curct] = *getCurrentLocation();
sym->addConstructor(curct); sym->addConstructor(curct);
symtab.addScope(); // Make a new symbol scope for our constructor symtab.addScope(); // Make a new symbol scope for our constructor
pcode.resetLabelCount(); pcode.resetLabelCount();
@ -2448,7 +2550,9 @@ bool SleighCompile::finalizeSections(Constructor *big,SectionVector *vec)
string errstring; string errstring;
errstring = checkSymbols(cur.scope); // Check labels in the section's scope errstring = checkSymbols(cur.scope); // Check labels in the section's scope
if (errstring.size()==0) { if (errstring.size()!=0) {
errors.push_back(sectionstring + errstring);
} else {
if (!expandMacros(cur.section,macrotable)) if (!expandMacros(cur.section,macrotable))
errors.push_back(sectionstring + "Could not expand macros"); errors.push_back(sectionstring + "Could not expand macros");
vector<int4> check; vector<int4> check;
@ -2472,10 +2576,11 @@ bool SleighCompile::finalizeSections(Constructor *big,SectionVector *vec)
} }
if (cur.section->delaySlot() != 0) { // Delay slot is present in this constructor if (cur.section->delaySlot() != 0) { // Delay slot is present in this constructor
if (root != big->getParent()) { // it is not in a root constructor if (root != big->getParent()) { // it is not in a root constructor
reportWarning("Delay slot used in",false); ostringstream msg;
cerr << " "; msg << "Delay slot used in non-root constructor ";
big->printInfo(cerr); big->printInfo(msg);
cerr << endl; msg << endl;
reportWarning(getLocation(big), msg.str());
} }
if (cur.section->delaySlot() > maxdelayslotbytes) // Keep track of maximum delayslot parameter if (cur.section->delaySlot() > maxdelayslotbytes) // Keep track of maximum delayslot parameter
maxdelayslotbytes = cur.section->delaySlot(); maxdelayslotbytes = cur.section->delaySlot();
@ -2494,9 +2599,9 @@ bool SleighCompile::finalizeSections(Constructor *big,SectionVector *vec)
ostringstream s; ostringstream s;
s << "in "; s << "in ";
big->printInfo(s); big->printInfo(s);
reportError(s.str(),false); reportError(getLocation(big), s.str());
for(int4 j=0;j<errors.size();++j) for(int4 j=0;j<errors.size();++j)
cerr << errors[j] << endl; reportError(getLocation(big), errors[j]);
return false; return false;
} }
return true; return true;
@ -2637,12 +2742,11 @@ void SleighCompile::buildMacro(MacroSymbol *sym,ConstructTpl *rtl)
{ {
string errstring = checkSymbols(symtab.getCurrentScope()); string errstring = checkSymbols(symtab.getCurrentScope());
if (errstring.size() != 0) { if (errstring.size() != 0) {
reportError(" in definition of macro "+sym->getName(),false); reportError(getCurrentLocation(), "In definition of macro '"+sym->getName() + "': " + errstring);
cerr << errstring;
return; return;
} }
if (!expandMacros(rtl,macrotable)) { if (!expandMacros(rtl,macrotable)) {
reportError("Could not expand submacro in definition of macro "+sym->getName(),true); reportError(getCurrentLocation(), "Could not expand submacro in definition of macro '" + sym->getName() + "'");
return; return;
} }
PcodeCompile::propagateSize(rtl); // Propagate size information (as much as possible) PcodeCompile::propagateSize(rtl); // Propagate size information (as much as possible)
@ -2654,9 +2758,9 @@ void SleighCompile::buildMacro(MacroSymbol *sym,ConstructTpl *rtl)
void SleighCompile::recordNop(void) void SleighCompile::recordNop(void)
{ {
ostringstream s; string msg = formatStatusMessage(getCurrentLocation(), "NOP detected");
s << "NOP detected at " << filename.back() << ':' << dec << lineno.back();
noplist.push_back(s.str()); noplist.push_back(msg);
} }
static int4 run_compilation(const char *filein,const char *fileout,SleighCompile &compiler) static int4 run_compilation(const char *filein,const char *fileout,SleighCompile &compiler)
@ -2853,9 +2957,9 @@ int main(int argc,char **argv)
enableAllCollisionWarning = true; enableAllCollisionWarning = true;
else if (argv[i][1] == 'n') else if (argv[i][1] == 'n')
enableAllNopWarning = true; enableAllNopWarning = true;
else if (argv[1][1] == 't') else if (argv[i][1] == 't')
enableDeadTempWarning = true; enableDeadTempWarning = true;
else if (argv[1][1] == 'e') else if (argv[i][1] == 'e')
enforceLocalKeyWord = true; enforceLocalKeyWord = true;
#ifdef YYDEBUG #ifdef YYDEBUG
else if (argv[i][1] == 'x') else if (argv[i][1] == 'x')
@ -2880,10 +2984,10 @@ int main(int argc,char **argv)
if (i != argc) if (i != argc)
dirStr = argv[i]; dirStr = argv[i];
findSlaSpecs(slaspecs, dirStr,SLASPECEXT); findSlaSpecs(slaspecs, dirStr,SLASPECEXT);
cout << "Compiling " << slaspecs.size() << " slaspec files in " << dirStr << "\n"; cout << "Compiling " << dec << slaspecs.size() << " slaspec files in " << dirStr << endl;
for(int4 j=0;j<slaspecs.size();++j) { for(int4 j=0;j<slaspecs.size();++j) {
string slaspec = slaspecs[j]; string slaspec = slaspecs[j];
cout << "Compiling (" << (j+1) << " of " << slaspecs.size() << ") " << slaspec << "\n"; cout << "Compiling (" << dec << (j+1) << " of " << dec << slaspecs.size() << ") " << slaspec << endl;
string sla = slaspec; string sla = slaspec;
sla.replace(slaspec.length() - slaspecExtLen, slaspecExtLen, SLAEXT); sla.replace(slaspec.length() - slaspecExtLen, slaspecExtLen, SLAEXT);
SleighCompile compiler; SleighCompile compiler;
@ -2904,8 +3008,10 @@ int main(int argc,char **argv)
} }
string fileinExamine(argv[i]); string fileinExamine(argv[i]);
string::size_type extInPos = fileinExamine.find(SLASPECEXT); string::size_type extInPos = fileinExamine.find(SLASPECEXT);
bool autoExtInSet = false; bool autoExtInSet = false;
bool extIsSLASPECEXT = false;
string fileinPreExt = ""; string fileinPreExt = "";
if (extInPos == string::npos) { //No Extension Given... if (extInPos == string::npos) { //No Extension Given...
fileinPreExt = fileinExamine; fileinPreExt = fileinExamine;
@ -2913,6 +3019,7 @@ int main(int argc,char **argv)
autoExtInSet = true; autoExtInSet = true;
} else { } else {
fileinPreExt = fileinExamine.substr(0,extInPos); fileinPreExt = fileinExamine.substr(0,extInPos);
extIsSLASPECEXT = true;
} }
if (i< argc-2) { if (i< argc-2) {
@ -2934,7 +3041,7 @@ int main(int argc,char **argv)
retval = run_compilation(fileinExamine.c_str(),fileoutExamine.c_str(),compiler); retval = run_compilation(fileinExamine.c_str(),fileoutExamine.c_str(),compiler);
}else{ }else{
//First determine whether or not to use Run_XML... //First determine whether or not to use Run_XML...
if (autoExtInSet) { //Assumed format of at least "sleigh file" -> "sleigh file.slaspec file.sla" if (autoExtInSet || extIsSLASPECEXT) { //Assumed format of at least "sleigh file" -> "sleigh file.slaspec file.sla"
string fileoutSTR = fileinPreExt; string fileoutSTR = fileinPreExt;
fileoutSTR.append(SLAEXT); fileoutSTR.append(SLAEXT);
retval = run_compilation(fileinExamine.c_str(),fileoutSTR.c_str(),compiler); retval = run_compilation(fileinExamine.c_str(),fileoutSTR.c_str(),compiler);

View file

@ -78,6 +78,8 @@ public:
static SubtableSymbol *getCurrentSubtable(const list<WithBlock> &stack); static SubtableSymbol *getCurrentSubtable(const list<WithBlock> &stack);
}; };
class SleighCompile;
class ConsistencyChecker { class ConsistencyChecker {
struct OptimizeRecord { struct OptimizeRecord {
int4 writeop; int4 writeop;
@ -91,6 +93,7 @@ class ConsistencyChecker {
OptimizeRecord(void) { OptimizeRecord(void) {
writeop = -1; readop = -1; inslot=-1; writecount=0; readcount=0; writesection=-2; readsection=-2; opttype=-1; } writeop = -1; readop = -1; inslot=-1; writecount=0; readcount=0; writesection=-2; readsection=-2; opttype=-1; }
}; };
SleighCompile *slgh;
int4 unnecessarypcode; int4 unnecessarypcode;
int4 readnowrite; int4 readnowrite;
int4 writenoread; int4 writenoread;
@ -99,6 +102,8 @@ class ConsistencyChecker {
SubtableSymbol *root_symbol; SubtableSymbol *root_symbol;
vector<SubtableSymbol *> postorder; vector<SubtableSymbol *> postorder;
map<SubtableSymbol *,int4> sizemap; // Sizes associated with tables map<SubtableSymbol *,int4> sizemap; // Sizes associated with tables
void reportError(const Location* loc, const string &msg);
void reportWarning(const Location* loc, const string &msg);
OperandSymbol *getOperandSymbol(int4 slot,OpTpl *op,Constructor *ct); OperandSymbol *getOperandSymbol(int4 slot,OpTpl *op,Constructor *ct);
void printOpName(ostream &s,OpTpl *op); void printOpName(ostream &s,OpTpl *op);
void printOpError(OpTpl *op,Constructor *ct,int4 err1,int4 err2,const string &message); void printOpError(OpTpl *op,Constructor *ct,int4 err1,int4 err2,const string &message);
@ -124,7 +129,7 @@ class ConsistencyChecker {
void checkUnusedTemps(Constructor *ct,const map<uintb,OptimizeRecord> &recs); void checkUnusedTemps(Constructor *ct,const map<uintb,OptimizeRecord> &recs);
void optimize(Constructor *ct); void optimize(Constructor *ct);
public: public:
ConsistencyChecker(SubtableSymbol *rt,bool unnecessary,bool warndead); ConsistencyChecker(SleighCompile *sleigh, SubtableSymbol *rt,bool unnecessary,bool warndead);
bool test(void); bool test(void);
bool testTruncations(bool isbigendian); bool testTruncations(bool isbigendian);
void optimizeAll(void); void optimizeAll(void);
@ -140,8 +145,6 @@ struct FieldContext {
FieldContext(VarnodeSymbol *s,FieldQuality *q) { sym=s; qual=q; } FieldContext(VarnodeSymbol *s,FieldQuality *q) { sym=s; qual=q; }
}; };
class SleighCompile;
class MacroBuilder : public PcodeBuilder { class MacroBuilder : public PcodeBuilder {
SleighCompile *slgh; SleighCompile *slgh;
bool haserror; bool haserror;
@ -150,7 +153,7 @@ class MacroBuilder : public PcodeBuilder {
bool transferOp(OpTpl *op,vector<HandleTpl *> &params); bool transferOp(OpTpl *op,vector<HandleTpl *> &params);
virtual void dump( OpTpl *op ); virtual void dump( OpTpl *op );
void free(void); void free(void);
void reportError(const string &val); void reportError(const Location* loc, const string &val);
public: public:
MacroBuilder(SleighCompile *sl,vector<OpTpl *> &ovec,uint4 lbcnt) : PcodeBuilder(lbcnt),outvec(ovec) { MacroBuilder(SleighCompile *sl,vector<OpTpl *> &ovec,uint4 lbcnt) : PcodeBuilder(lbcnt),outvec(ovec) {
slgh = sl; haserror = false; } slgh = sl; haserror = false; }
@ -166,7 +169,9 @@ public:
class SleighPcode : public PcodeCompile { class SleighPcode : public PcodeCompile {
SleighCompile *compiler; SleighCompile *compiler;
virtual uintb allocateTemp(void); virtual uintb allocateTemp(void);
virtual void reportError(const string &msg); virtual const Location *getLocation(SleighSymbol *sym) const;
virtual void reportError(const Location* loc, const string &msg);
virtual void reportWarning(const Location* loc, const string &msg);
virtual void addSymbol(SleighSymbol *sym); virtual void addSymbol(SleighSymbol *sym);
public: public:
SleighPcode(void) : PcodeCompile() { compiler = (SleighCompile *)0; } SleighPcode(void) : PcodeCompile() { compiler = (SleighCompile *)0; }
@ -191,6 +196,8 @@ private:
vector<string> relpath; // Relative path (to cwd) for each filename vector<string> relpath; // Relative path (to cwd) for each filename
vector<string> filename; // Stack of current files being parsed vector<string> filename; // Stack of current files being parsed
vector<int4> lineno; // Current line number for each file in stack vector<int4> lineno; // Current line number for each file in stack
map<Constructor *, Location> ctorLocationMap; // Map constructor to its defining parse location
map<SleighSymbol *, Location> symbolLocationMap; // Map symbol to its defining parse location
int4 userop_count; // Number of userops defined int4 userop_count; // Number of userops defined
bool warnunnecessarypcode; // True if we warn of unnecessary ZEXT or SEXT bool warnunnecessarypcode; // True if we warn of unnecessary ZEXT or SEXT
bool warndeadtemps; // True if we warn of temporaries that are written but not read bool warndeadtemps; // True if we warn of temporaries that are written but not read
@ -198,7 +205,10 @@ private:
bool warnalllocalcollisions; // True if local export collisions generate individual warnings bool warnalllocalcollisions; // True if local export collisions generate individual warnings
bool warnallnops; // True if pcode NOPs generate individual warnings bool warnallnops; // True if pcode NOPs generate individual warnings
vector<string> noplist; // List of individual NOP warnings vector<string> noplist; // List of individual NOP warnings
mutable Location currentLocCache; // Location for (last) request of current location
int4 errors; int4 errors;
const Location* getCurrentLocation(void) const;
void predefinedSymbols(void); void predefinedSymbols(void);
int4 calcContextVarLayout(int4 start,int4 sz,int4 numbits); int4 calcContextVarLayout(int4 start,int4 sz,int4 numbits);
void buildDecisionTrees(void); void buildDecisionTrees(void);
@ -220,9 +230,18 @@ private:
void checkUniqueAllocation(void); void checkUniqueAllocation(void);
public: public:
SleighCompile(void); SleighCompile(void);
void reportError(const string &msg,bool includeline); const Location *getLocation(Constructor* ctor) const;
void reportWarning(const string &msg,bool includeline); const Location *getLocation(SleighSymbol *sym) const;
string formatStatusMessage(const Location* loc, const string &msg);
void reportError(const string &msg);
void reportError(const Location *loc, const string &msg);
void reportWarning(const string &msg);
void reportWarning(const Location *loc, const string &msg);
int4 numErrors(void) const { return errors; } int4 numErrors(void) const { return errors; }
void reportInfo(const string &msg);
void reportInfo(const Location *loc, const string &msg);
uintb getUniqueAddr(void); uintb getUniqueAddr(void);
void setUnnecessaryPcodeWarning(bool val) { warnunnecessarypcode = val; } void setUnnecessaryPcodeWarning(bool val) { warnunnecessarypcode = val; }
void setDeadTempWarning(bool val) { warndeadtemps = val; } void setDeadTempWarning(bool val) { warndeadtemps = val; }

View file

@ -577,6 +577,6 @@ anysymbol: SPACESYM { $$ = $1; }
int yyerror(const char *s) int yyerror(const char *s)
{ {
slgh->reportError(s,true); slgh->reportError(s);
return 0; return 0;
} }

View file

@ -52,44 +52,76 @@ int4 TokenPattern::resolveTokens(const TokenPattern &tok1,const TokenPattern &to
throw SleighError("Right/left ellipsis"); throw SleighError("Right/left ellipsis");
else if (tok2.leftellipsis) else if (tok2.leftellipsis)
leftellipsis = true; leftellipsis = true;
else if (tok1.toklist.size() != minsize) else if (tok1.toklist.size() != minsize) {
throw SleighError("Mismatched pattern sizes"); ostringstream msg;
msg << "Mismatched pattern sizes -- " << dec << tok1.toklist.size()
<< " != "
<< dec << minsize;
throw SleighError(msg.str());
}
else if (tok1.toklist.size()==tok2.toklist.size()) else if (tok1.toklist.size()==tok2.toklist.size())
throw SleighError("Pattern size cannot vary (missing ... ?)"); throw SleighError("Pattern size cannot vary (missing '...'?)");
} }
else if (tok1.rightellipsis) { else if (tok1.rightellipsis) {
if (tok2.leftellipsis) if (tok2.leftellipsis)
throw SleighError("Left/right ellipsis"); throw SleighError("Left/right ellipsis");
else if (tok2.rightellipsis) else if (tok2.rightellipsis)
rightellipsis = true; rightellipsis = true;
else if (tok1.toklist.size() != minsize) else if (tok1.toklist.size() != minsize) {
throw SleighError("Mismatched pattern sizes"); ostringstream msg;
msg << "Mismatched pattern sizes -- " << dec << tok1.toklist.size()
<< " != "
<< dec << minsize;
throw SleighError(msg.str());
}
else if (tok1.toklist.size()==tok2.toklist.size()) else if (tok1.toklist.size()==tok2.toklist.size())
throw SleighError("Pattern size cannot vary (missing ... ?)"); throw SleighError("Pattern size cannot vary (missing '...'?)");
} }
else { else {
if (tok2.leftellipsis) { if (tok2.leftellipsis) {
reversedirection = true; reversedirection = true;
if (tok2.toklist.size() != minsize) if (tok2.toklist.size() != minsize) {
throw SleighError("Mismatched pattern sizes"); ostringstream msg;
msg << "Mismatched pattern sizes -- " << dec << tok2.toklist.size()
<< " != "
<< dec << minsize;
throw SleighError(msg.str());
}
else if (tok1.toklist.size()==tok2.toklist.size()) else if (tok1.toklist.size()==tok2.toklist.size())
throw SleighError("Pattern size cannot vary (missing ... ?)"); throw SleighError("Pattern size cannot vary (missing '...'?)");
} }
else if (tok2.rightellipsis) { else if (tok2.rightellipsis) {
if (tok2.toklist.size() != minsize) if (tok2.toklist.size() != minsize) {
throw SleighError("Mismatched pattern sizes"); ostringstream msg;
msg << "Mismatched pattern sizes -- " << dec << tok2.toklist.size()
<< " != "
<< dec << minsize;
throw SleighError(msg.str());
}
else if (tok1.toklist.size()==tok2.toklist.size()) else if (tok1.toklist.size()==tok2.toklist.size())
throw SleighError("Pattern size cannot vary (missing ... ?)"); throw SleighError("Pattern size cannot vary (missing '...'?)");
} }
else { else {
if (tok2.toklist.size() != tok1.toklist.size()) if (tok2.toklist.size() != tok1.toklist.size()) {
throw SleighError("Mismatched pattern sizes"); ostringstream msg;
msg << "Mismatched pattern sizes -- " << dec << tok2.toklist.size()
<< " != "
<< dec << tok1.toklist.size();
throw SleighError(msg.str());
}
} }
} }
if (reversedirection) { if (reversedirection) {
for(int4 i=0;i<minsize;++i) for(int4 i=0;i<minsize;++i)
if (tok1.toklist[tok1.toklist.size()-1-i] != tok2.toklist[tok2.toklist.size()-1-i]) if (tok1.toklist[tok1.toklist.size()-1-i] != tok2.toklist[tok2.toklist.size()-1-i]) {
throw SleighError("Mismatched tokens when combining patterns");
ostringstream msg;
msg << "Mismatched tokens when combining patterns -- "
<< dec << tok1.toklist[tok1.toklist.size()-1-i]
<< " != "
<< dec << tok2.toklist[tok2.toklist.size()-1-i];
throw SleighError(msg.str());
}
if (tok1.toklist.size() <= tok2.toklist.size()) if (tok1.toklist.size() <= tok2.toklist.size())
for(int4 i=minsize;i<tok2.toklist.size();++i) for(int4 i=minsize;i<tok2.toklist.size();++i)
ressa += tok2.toklist[tok2.toklist.size()-1-i]->getSize(); ressa += tok2.toklist[tok2.toklist.size()-1-i]->getSize();
@ -101,8 +133,14 @@ int4 TokenPattern::resolveTokens(const TokenPattern &tok1,const TokenPattern &to
} }
else { else {
for(int4 i=0;i<minsize;++i) for(int4 i=0;i<minsize;++i)
if (tok1.toklist[i] != tok2.toklist[i]) if (tok1.toklist[i] != tok2.toklist[i]) {
throw SleighError("Mismatched tokens when combining patterns"); ostringstream msg;
msg << "Mismatched tokens when combining patterns -- "
<< dec << tok1.toklist[i]
<< " != "
<< dec << tok2.toklist[i];
throw SleighError(msg.str());
}
} }
// Save the results into -this- // Save the results into -this-
if (tok1.toklist.size() <= tok2.toklist.size()) if (tok1.toklist.size() <= tok2.toklist.size())
@ -126,7 +164,7 @@ PatternBlock *TokenPattern::buildSingle(int4 startbit,int4 endbit,uintm byteval)
offset += 1; offset += 1;
startbit -= 8; startbit -= 8;
endbit -= 8; endbit -= 8;
} }
mask = (~((uintm)0)) << (sizeof(uintm)*8-size); mask = (~((uintm)0)) << (sizeof(uintm)*8-size);
byteval = (byteval << (sizeof(uintm)*8-size))& mask; byteval = (byteval << (sizeof(uintm)*8-size))& mask;
mask >>= startbit; mask >>= startbit;
@ -1645,4 +1683,3 @@ void EquationRightEllipsis::operandOrder(Constructor *ct,vector<OperandSymbol *>
{ {
eq->operandOrder(ct,order); // List operands eq->operandOrder(ct,order); // List operands
} }

View file

@ -43,7 +43,7 @@ int4 negative_if = -1;
void preproc_error(const string &err) void preproc_error(const string &err)
{ {
slgh->reportError(err,true); slgh->reportError((const Location *)0, err);
cerr << "Terminating due to error in preprocessing" << endl; cerr << "Terminating due to error in preprocessing" << endl;
exit(1); exit(1);
} }
@ -669,4 +669,3 @@ with { BEGIN(pattern); withsection = 1; slgh->calcContextLayout(); return WITH
filebuffers.pop_back(); filebuffers.pop_back();
slgh->parseFileFinished(); slgh->parseFileFinished();
} }

View file

@ -86,7 +86,7 @@ void SymbolTable::addGlobalSymbol(SleighSymbol *a)
a->scopeid = scope->getId(); a->scopeid = scope->getId();
SleighSymbol *res = scope->addSymbol(a); SleighSymbol *res = scope->addSymbol(a);
if (res != a) if (res != a)
throw SleighError("Duplicate symbol name: "+a->getName()); throw SleighError("Duplicate symbol name '" + a->getName() + "'");
} }
void SymbolTable::addSymbol(SleighSymbol *a) void SymbolTable::addSymbol(SleighSymbol *a)
@ -2017,13 +2017,8 @@ void DecisionProperties::identicalPattern(Constructor *a,Constructor *b)
if ((!a->isError())&&(!b->isError())) { if ((!a->isError())&&(!b->isError())) {
a->setError(true); a->setError(true);
b->setError(true); b->setError(true);
ostringstream s;
s << "Constructors with identical patterns: \n "; identerrors.push_back(make_pair(a, b));
a->printInfo(s);
s << "\n ";
b->printInfo(s);
s << endl;
identerrors.push_back(s.str());
} }
} }
@ -2033,13 +2028,8 @@ void DecisionProperties::conflictingPattern(Constructor *a,Constructor *b)
if ((!a->isError())&&(!b->isError())) { if ((!a->isError())&&(!b->isError())) {
a->setError(true); a->setError(true);
b->setError(true); b->setError(true);
ostringstream s;
s << "Constructor patterns cannot be distinguished: \n "; conflicterrors.push_back(make_pair(a, b));
a->printInfo(s);
s << "\n ";
b->printInfo(s);
s << endl;
conflicterrors.push_back(s.str());
} }
} }

View file

@ -525,13 +525,13 @@ public:
}; };
class DecisionProperties { class DecisionProperties {
vector<string> identerrors; vector<pair<Constructor *, Constructor *>> identerrors;
vector<string> conflicterrors; vector<pair<Constructor *, Constructor *>> conflicterrors;
public: public:
void identicalPattern(Constructor *a,Constructor *b); void identicalPattern(Constructor *a,Constructor *b);
void conflictingPattern(Constructor *a,Constructor *b); void conflictingPattern(Constructor *a,Constructor *b);
const vector<string> &getIdentErrors(void) const { return identerrors; } const vector<pair<Constructor *, Constructor *>> &getIdentErrors(void) const { return identerrors; }
const vector<string> &getConflictErrors(void) const { return conflicterrors; } const vector<pair<Constructor *, Constructor *>> &getConflictErrors(void) const { return conflicterrors; }
}; };
class DecisionNode { class DecisionNode {

View file

@ -66,7 +66,7 @@ scope Block {
} }
private void redefinedError(SleighSymbol sym, Tree t, String what) { private void redefinedError(SleighSymbol sym, Tree t, String what) {
String msg = "symbol " + sym.getName() + " (from " + sym.getLocation() + ") redefined as " + what; String msg = "symbol '" + sym.getName() + "' (from " + sym.getLocation() + ") redefined as " + what;
reportError(find(t), msg); reportError(find(t), msg);
} }
@ -76,17 +76,17 @@ scope Block {
} }
private void wrongSymbolTypeError(SleighSymbol sym, Location where, String type, String purpose) { private void wrongSymbolTypeError(SleighSymbol sym, Location where, String type, String purpose) {
String msg = sym.getType() + " " + sym + " (defined at " + sym.getLocation() + ") is wrong type (should be " + type + ") in " + purpose; String msg = sym.getType() + " '" + sym + "' (defined at " + sym.getLocation() + ") is wrong type (should be " + type + ") in " + purpose;
reportError(where, msg); reportError(where, msg);
} }
private void undeclaredSymbolError(SleighSymbol sym, Location where, String purpose) { private void undeclaredSymbolError(SleighSymbol sym, Location where, String purpose) {
String msg = sym + " (used in " + purpose + ") is not declared in the pattern list"; String msg = "'" + sym + "' (used in " + purpose + ") is not declared in the pattern list";
reportError(where, msg); reportError(where, msg);
} }
private void unknownSymbolError(String text, Location loc, String type, String purpose) { private void unknownSymbolError(String text, Location loc, String type, String purpose) {
String msg = "unknown " + type + " " + text + " in " + purpose; String msg = "unknown " + type + " '" + text + "' in " + purpose;
reportError(loc, msg); reportError(loc, msg);
} }
@ -205,7 +205,7 @@ fielddef
long start = $s.value.longValue(); long start = $s.value.longValue();
long finish = $e.value.longValue(); long finish = $e.value.longValue();
if (finish < start) { if (finish < start) {
reportError(find($t), "field " + $n.value.getText() + " starts at " + start + " and ends at " + finish); reportError(find($t), "field '" + $n.value.getText() + "' starts at " + start + " and ends at " + finish);
} }
$fielddef::fieldQuality = new FieldQuality($n.value.getText(), find($t), $s.value.longValue(), $e.value.longValue()); $fielddef::fieldQuality = new FieldQuality($n.value.getText(), find($t), $s.value.longValue(), $e.value.longValue());
} }
@ -426,7 +426,7 @@ typemod
space_class type = space_class.valueOf(typeName); space_class type = space_class.valueOf(typeName);
$spacedef::quality.type = type; $spacedef::quality.type = type;
} catch(IllegalArgumentException e) { } catch(IllegalArgumentException e) {
reportError(find(n), "invalid space type " + typeName); reportError(find(n), "invalid space type '" + typeName + "'");
} }
} }
} }
@ -829,7 +829,7 @@ pattern_symbol[String purpose] returns [PatternExpression expr]
} else if(sym.getType() == symbol_type.operand_symbol) { } else if(sym.getType() == symbol_type.operand_symbol) {
OperandSymbol os = (OperandSymbol) sym; OperandSymbol os = (OperandSymbol) sym;
if (os.getDefiningSymbol() != null && os.getDefiningSymbol().getType() == symbol_type.subtable_symbol) { if (os.getDefiningSymbol() != null && os.getDefiningSymbol().getType() == symbol_type.subtable_symbol) {
reportError(find($s), "Subtable symbol " + sym.getName() + " is not allowed in context block"); reportError(find($s), "Subtable symbol '" + sym.getName() + "' is not allowed in context block");
} }
$expr = os.getPatternExpression(); $expr = os.getPatternExpression();
} else if(sym.getType() == symbol_type.start_symbol } else if(sym.getType() == symbol_type.start_symbol
@ -847,7 +847,7 @@ pattern_symbol[String purpose] returns [PatternExpression expr]
FamilySymbol z = (FamilySymbol) sym; FamilySymbol z = (FamilySymbol) sym;
$expr = z.getPatternValue(); $expr = z.getPatternValue();
} else { } else {
reportError(find($s), "Global symbol " + sym.getName() + " is not allowed in action expression"); reportError(find($s), "Global symbol '" + sym.getName() + "' is not allowed in action expression");
} }
} else { } else {
wrongSymbolTypeError(sym, find($s), "start, end, operand, epsilon, or varnode", purpose); wrongSymbolTypeError(sym, find($s), "start, end, operand, epsilon, or varnode", purpose);
@ -908,7 +908,7 @@ cstatement[VectorSTL<ContextChange> r]
} else if(sym.getType() == symbol_type.context_symbol) { } else if(sym.getType() == symbol_type.context_symbol) {
ContextSymbol t = (ContextSymbol) sym; ContextSymbol t = (ContextSymbol) sym;
if (!sc.contextMod(r, t, e)) { if (!sc.contextMod(r, t, e)) {
reportError(find($id), "Cannot use 'inst_next' to set context variable: " + t.getName()); reportError(find($id), "Cannot use 'inst_next' to set context variable: '" + t.getName() + "'");
} }
} else if(sym.getType() == symbol_type.operand_symbol) { } else if(sym.getType() == symbol_type.operand_symbol) {
OperandSymbol t = (OperandSymbol) sym; OperandSymbol t = (OperandSymbol) sym;
@ -919,7 +919,7 @@ cstatement[VectorSTL<ContextChange> r]
} }
| ^(OP_APPLY ^(OP_IDENTIFIER id=.) ^(OP_IDENTIFIER arg1=.) ^(OP_IDENTIFIER arg2=.)) { | ^(OP_APPLY ^(OP_IDENTIFIER id=.) ^(OP_IDENTIFIER arg1=.) ^(OP_IDENTIFIER arg2=.)) {
if (!"globalset".equals(id.getText())) { if (!"globalset".equals(id.getText())) {
reportError(find($id), "unknown context block function " + id.getText()); reportError(find($id), "unknown context block function '" + id.getText() + "'");
} else { } else {
SleighSymbol sym = sc.findSymbol($arg2.getText()); SleighSymbol sym = sc.findSymbol($arg2.getText());
if (sym == null) { if (sym == null) {

View file

@ -0,0 +1,23 @@
package ghidra.pcode.utils;
import ghidra.sleigh.grammar.Location;
public final class MessageFormattingUtils {
/**
* Format a log message.
*
* @param location Referenced file location
* @param message Message
* @return Formatted string with location prepended to message.
*/
public static String format(Location location, CharSequence message) {
StringBuilder sb = new StringBuilder();
if (location != null) {
sb.append(location).append(": ");
}
sb.append(message);
return sb.toString().trim();
}
}

View file

@ -171,7 +171,7 @@ public class ParserContext {
} }
public int getInstructionBytes(int bytestart, int size, int off) { public int getInstructionBytes(int bytestart, int size, int off) {
// Get bytes from the instruction stream into a intm // Get bytes from the instruction stream into an int
// (assuming big endian format) // (assuming big endian format)
off += bytestart; off += bytestart;
if (off >= 16) { if (off >= 16) {

View file

@ -18,6 +18,7 @@ package ghidra.pcodeCPort.sleighbase;
import java.io.PrintStream; import java.io.PrintStream;
import generic.stl.*; import generic.stl.*;
import ghidra.pcode.utils.MessageFormattingUtils;
import ghidra.pcodeCPort.context.SleighError; import ghidra.pcodeCPort.context.SleighError;
import ghidra.pcodeCPort.pcoderaw.VarnodeData; import ghidra.pcodeCPort.pcoderaw.VarnodeData;
import ghidra.pcodeCPort.slghpatexpress.ContextField; import ghidra.pcodeCPort.slghpatexpress.ContextField;
@ -26,10 +27,13 @@ import ghidra.pcodeCPort.space.AddrSpace;
import ghidra.pcodeCPort.space.spacetype; import ghidra.pcodeCPort.space.spacetype;
import ghidra.pcodeCPort.translate.Translate; import ghidra.pcodeCPort.translate.Translate;
import ghidra.pcodeCPort.utils.XmlUtils; import ghidra.pcodeCPort.utils.XmlUtils;
import ghidra.sleigh.grammar.Location;
import ghidra.util.Msg;
public abstract class SleighBase extends Translate implements NamedSymbolProvider { public abstract class SleighBase extends Translate implements NamedSymbolProvider {
// NOTE: restoreXml method removed as it is only used by the decompiler's implementation // NOTE: restoreXml method removed as it is only used by the decompiler's
// implementation
public static final int SLA_FORMAT_VERSION = 2; // What format of the .sla file this produces public static final int SLA_FORMAT_VERSION = 2; // What format of the .sla file this produces
// This value should always match SleighLanguage.SLA_FORMAT_VERSION // This value should always match SleighLanguage.SLA_FORMAT_VERSION
@ -65,6 +69,18 @@ public abstract class SleighBase extends Translate implements NamedSymbolProvide
return (root != null); return (root != null);
} }
public void reportError(Location location, String msg) {
Msg.error(this, MessageFormattingUtils.format(location, msg));
}
public void reportError(Location location, String msg, Throwable t) {
Msg.error(this, MessageFormattingUtils.format(location, msg), t);
}
public void reportWarning(Location location, String msg) {
Msg.warn(this, MessageFormattingUtils.format(location, msg));
}
protected void buildXrefs() { protected void buildXrefs() {
SymbolScope glb = symtab.getGlobalScope(); SymbolScope glb = symtab.getGlobalScope();
int errors = 0; int errors = 0;
@ -74,29 +90,26 @@ public abstract class SleighBase extends Translate implements NamedSymbolProvide
for (iter = glb.begin(); !iter.isEnd(); iter.increment()) { for (iter = glb.begin(); !iter.isEnd(); iter.increment()) {
SleighSymbol sym = iter.get(); SleighSymbol sym = iter.get();
if (sym.getType() == symbol_type.varnode_symbol) { if (sym.getType() == symbol_type.varnode_symbol) {
Pair<IteratorSTL<VarnodeSymbol>, Boolean> res = Pair<IteratorSTL<VarnodeSymbol>, Boolean> res = varnode_xref.insert((VarnodeSymbol) sym);
varnode_xref.insert((VarnodeSymbol) sym);
if (!res.second) { if (!res.second) {
buffer.append("Duplicate (offset,size) pair for registers: ");
buffer.append(sym.getName()); String msg = String.format("Duplicate (offset,size) pair for registers: %s (%s) and %s (%s)",
buffer.append(" ("); sym.getName(), sym.getLocation(), res.first.get().getName(), res.first.get().getLocation());
buffer.append(sym.getLocation());
buffer.append(") and "); buffer.append(msg + "\n");
buffer.append(res.first.get().getName());
buffer.append(" ("); reportError(sym.getLocation(), msg);
buffer.append(res.first.get().getLocation()); reportError(res.first.get().getLocation(), msg);
buffer.append(")\n");
errors += 1; errors += 1;
} }
} } else if (sym.getType() == symbol_type.userop_symbol) {
else if (sym.getType() == symbol_type.userop_symbol) {
int index = ((UserOpSymbol) sym).getIndex(); int index = ((UserOpSymbol) sym).getIndex();
while (userop.size() <= index) { while (userop.size() <= index) {
userop.push_back(""); userop.push_back("");
} }
userop.set(index, sym.getName()); userop.set(index, sym.getName());
} } else if (sym.getType() == symbol_type.context_symbol) {
else if (sym.getType() == symbol_type.context_symbol) {
ContextSymbol csym = (ContextSymbol) sym; ContextSymbol csym = (ContextSymbol) sym;
ContextField field = (ContextField) csym.getPatternValue(); ContextField field = (ContextField) csym.getPatternValue();
int startbit = field.getStartBit(); int startbit = field.getStartBit();
@ -137,10 +150,10 @@ public abstract class SleighBase extends Translate implements NamedSymbolProvide
public VarnodeData getRegister(String nm) { public VarnodeData getRegister(String nm) {
VarnodeSymbol sym = (VarnodeSymbol) findSymbol(nm); VarnodeSymbol sym = (VarnodeSymbol) findSymbol(nm);
if (sym == null) { if (sym == null) {
throw new SleighError("Unknown register name: " + nm, null); throw new SleighError("Unknown register name '" + nm + "'", null);
} }
if (sym.getType() != symbol_type.varnode_symbol) { if (sym.getType() != symbol_type.varnode_symbol) {
throw new SleighError("Symbol is not a register: " + nm, null); throw new SleighError("Symbol is not a register '" + nm + "'", sym.location);
} }
return sym.getFixedVarnode(); return sym.getFixedVarnode();
} }
@ -208,8 +221,8 @@ public abstract class SleighBase extends Translate implements NamedSymbolProvide
s.append(">\n"); s.append(">\n");
for (int i = 0; i < numSpaces(); ++i) { for (int i = 0; i < numSpaces(); ++i) {
AddrSpace spc = getSpace(i); AddrSpace spc = getSpace(i);
if ((spc.getType() == spacetype.IPTR_CONSTANT) || if ((spc.getType() == spacetype.IPTR_CONSTANT) || (spc.getType() == spacetype.IPTR_FSPEC)
(spc.getType() == spacetype.IPTR_FSPEC) || (spc.getType() == spacetype.IPTR_IOP)) { || (spc.getType() == spacetype.IPTR_IOP)) {
continue; continue;
} }
spc.saveXml(s); spc.saveXml(s);

View file

@ -25,6 +25,7 @@ import ghidra.pcodeCPort.semantics.ConstTpl.const_type;
import ghidra.pcodeCPort.semantics.ConstTpl.v_field; import ghidra.pcodeCPort.semantics.ConstTpl.v_field;
import ghidra.pcodeCPort.slghsymbol.*; import ghidra.pcodeCPort.slghsymbol.*;
import ghidra.pcodeCPort.space.AddrSpace; import ghidra.pcodeCPort.space.AddrSpace;
import ghidra.sleigh.grammar.Location;
import ghidra.util.Msg; import ghidra.util.Msg;
class ConsistencyChecker { class ConsistencyChecker {
@ -97,7 +98,8 @@ class ConsistencyChecker {
if ((vnout == 0) || (vn0 == 0)) { if ((vnout == 0) || (vn0 == 0)) {
return true; return true;
} }
printOpError(op, ct, -1, 0, "Input and output sizes must match"); printOpError(op, ct, -1, 0, "Input and output sizes must match; " +
op.getIn(0).getSize() + " != " + op.getOut().getSize());
return false; return false;
case CPUI_INT_ADD: case CPUI_INT_ADD:
case CPUI_INT_SUB: case CPUI_INT_SUB:
@ -324,7 +326,7 @@ class ConsistencyChecker {
if ((vnout == 0) || (vn0 == 0)) { if ((vnout == 0) || (vn0 == 0)) {
return true; return true;
} }
if ((vnout == vn0) && (vn1 == 0)) { // No actual truncation is occuring if ((vnout == vn0) && (vn1 == 0)) { // No actual truncation is occurring
dealWithUnnecessaryTrunc(op, ct); dealWithUnnecessaryTrunc(op, ct);
return true; return true;
} }
@ -478,6 +480,30 @@ class ConsistencyChecker {
} }
} }
private void reportError(Location location, CharSequence message) {
if (location == null) {
Msg.error(this, message);
return;
}
StringBuilder sb = new StringBuilder();
sb.append(location).append(": ").append(message);
Msg.error(this, sb.toString());
}
private void reportWarning(Location location, CharSequence message) {
if (location == null) {
Msg.warn(this, message);
return;
}
StringBuilder sb = new StringBuilder();
sb.append(location).append(": ").append(message);
Msg.warn(this, sb.toString());
}
void printOpError(OpTpl op, Constructor ct, int err1, int err2, String message) { void printOpError(OpTpl op, Constructor ct, int err1, int err2, String message) {
SubtableSymbol sym = ct.getParent(); SubtableSymbol sym = ct.getParent();
OperandSymbol op1, op2; OperandSymbol op1, op2;
@ -489,24 +515,30 @@ class ConsistencyChecker {
else { else {
op2 = null; op2 = null;
} }
Msg.error(this, "Size restriction error in table \"" + sym.getName() +
"\" in constructor at " + ct.location + " from operation located at " + op.location);
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("Size restriction error in table '")
.append(sym.getName())
.append("' in constructor at ").append(ct.location)
.append("\n");
sb.append(" Problem"); sb.append(" Problem");
if ((op1 != null) && (op2 != null)) { if ((op1 != null) && (op2 != null)) {
sb.append(" with \"" + op1.getName() + "\" and \"" + op2.getName() + "\""); sb.append(" with '" + op1.getName() + "' and '" + op2.getName() + "'");
} }
else if (op1 != null) { else if (op1 != null) {
sb.append(" with \"" + op1.getName() + "\""); sb.append(" with '" + op1.getName() + "'");
} }
else if (op2 != null) { else if (op2 != null) {
sb.append(" with \"" + op2.getName() + "\""); sb.append(" with '" + op2.getName() + "'");
} }
sb.append(" in \"" + getOpName(op) + "\" operator"); sb.append(" in '" + getOpName(op) + "' operator");
Msg.error(this, sb.toString());
sb.append("\n ").append(message);
reportError(op.location, sb);
Msg.error(this, " " + message);
} }
int recoverSize(ConstTpl sizeconst, Constructor ct) { int recoverSize(ConstTpl sizeconst, Constructor ct) {
@ -544,7 +576,7 @@ class ConsistencyChecker {
} }
private void handle(String msg, Constructor ct) { private void handle(String msg, Constructor ct) {
Msg.error(this, "Unsigned comparison with " + msg + " in constructor at " + ct.location); reportError(ct.location, " Unsigned comparison with " + msg + " in constructor");
} }
private void handleZero(String trueOrFalse, Constructor ct) { private void handleZero(String trueOrFalse, Constructor ct) {
@ -708,8 +740,9 @@ class ConsistencyChecker {
HandleTpl exportres = ct.getTempl().getResult(); HandleTpl exportres = ct.getTempl().getResult();
if (exportres != null) { if (exportres != null) {
if (seenemptyexport && (!seennonemptyexport)) { if (seenemptyexport && (!seennonemptyexport)) {
Msg.error(this, "Table " + sym.getName() + " exports inconsistently"); reportError(ct.location, String.format(
Msg.error(this, "Constructor at " + ct.location + " is first inconsistency"); "Table '%s' exports inconsistently; Constructor at %s is first inconsitency",
sym.getName(), ct.location));
testresult = false; testresult = false;
} }
seennonemptyexport = true; seennonemptyexport = true;
@ -718,15 +751,17 @@ class ConsistencyChecker {
tablesize = exsize; tablesize = exsize;
} }
if ((exsize != 0) && (exsize != tablesize)) { if ((exsize != 0) && (exsize != tablesize)) {
Msg.error(this, "Table " + sym.getName() + " has inconsistent export size."); reportError(ct.location, String.format(
Msg.error(this, "Constructor at " + ct.location + " is first conflict"); "Table '%s' has inconsistent export size; Constructor at %s is first conflict",
sym.getName(), ct.location));
testresult = false; testresult = false;
} }
} }
else { else {
if (seennonemptyexport && (!seenemptyexport)) { if (seennonemptyexport && (!seenemptyexport)) {
Msg.error(this, "Table " + sym.getName() + " exports inconsistently"); reportError(ct.location, String.format(
Msg.error(this, "Constructor at " + ct.location + " is first inconsistency"); "Table '%s' exports inconsistently; Constructor at %s is first inconsitency",
sym.getName(), ct.location));
testresult = false; testresult = false;
} }
seenemptyexport = true; seenemptyexport = true;
@ -734,7 +769,8 @@ class ConsistencyChecker {
} }
if (seennonemptyexport) { if (seennonemptyexport) {
if (tablesize == 0) { if (tablesize == 0) {
Msg.error(this, "Warning: Table " + sym.getName() + " exports size 0"); reportWarning(sym.location, "Table '" + sym.getName() + "' exports size 0");
} }
sizemap.put(sym, tablesize); // Remember recovered size sizemap.put(sym, tablesize); // Remember recovered size
} }
@ -749,8 +785,7 @@ class ConsistencyChecker {
// input size is the same as the output size // input size is the same as the output size
void dealWithUnnecessaryExt(OpTpl op, Constructor ct) { void dealWithUnnecessaryExt(OpTpl op, Constructor ct) {
if (printextwarning) { if (printextwarning) {
Msg.error(this, "Unnecessary \"" + getOpName(op) + "\" in constructor from " + reportWarning(op.location, "Unnecessary '" + getOpName(op) + "'");
ct.getFilename() + " starting at line " + ct.getLineno());
} }
op.setOpcode(OpCode.CPUI_COPY); // Equivalent to copy op.setOpcode(OpCode.CPUI_COPY); // Equivalent to copy
unnecessarypcode += 1; unnecessarypcode += 1;
@ -758,8 +793,7 @@ class ConsistencyChecker {
void dealWithUnnecessaryTrunc(OpTpl op, Constructor ct) { void dealWithUnnecessaryTrunc(OpTpl op, Constructor ct) {
if (printextwarning) { if (printextwarning) {
Msg.error(this, "Unnecessary \"" + getOpName(op) + "\" in constructor from " + reportWarning(op.location, "Unnecessary '" + getOpName(op) + "'");
ct.getFilename() + " starting at line " + ct.getLineno());
} }
op.setOpcode(OpCode.CPUI_COPY); // Equivalent to copy op.setOpcode(OpCode.CPUI_COPY); // Equivalent to copy
op.removeInput(1); op.removeInput(1);
@ -853,14 +887,8 @@ class ConsistencyChecker {
} }
} }
static boolean possibleIntersection(VarnodeTpl vn1, VarnodeTpl vn2) { // Conservatively static boolean possibleIntersection(VarnodeTpl vn1, VarnodeTpl vn2) {
// test // Conservatively test whether vn1 and vn2 can intersect
// whether
// vn1
// and
// vn2
// can
// intersect
if (vn1.getSpace().isConstSpace()) { if (vn1.getSpace().isConstSpace()) {
return false; return false;
} }
@ -1116,15 +1144,12 @@ class ConsistencyChecker {
OptimizeRecord currec = pair.second; OptimizeRecord currec = pair.second;
if (currec.readcount == 0) { if (currec.readcount == 0) {
if (printdeadwarning) { if (printdeadwarning) {
Msg.error(this, reportWarning(ct.location, "Temporary is written but not read");
"Warning: temporary is written but not read in constructor at " +
ct.location);
} }
writenoread += 1; writenoread += 1;
} }
else if (currec.writecount == 0) { else if (currec.writecount == 0) {
Msg.error(this, reportError(ct.location, "Temporary is read but not written");
"Error: temporary is read but not written in constructor at " + ct.location);
readnowrite += 1; readnowrite += 1;
} }
iter.increment(); iter.increment();

View file

@ -15,13 +15,16 @@
*/ */
package ghidra.pcodeCPort.slgh_compile; package ghidra.pcodeCPort.slgh_compile;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import generic.stl.IteratorSTL; import generic.stl.IteratorSTL;
import generic.stl.VectorSTL; import generic.stl.VectorSTL;
import ghidra.pcode.utils.MessageFormattingUtils;
import ghidra.pcodeCPort.context.SleighError; import ghidra.pcodeCPort.context.SleighError;
import ghidra.pcodeCPort.opcodes.OpCode; import ghidra.pcodeCPort.opcodes.OpCode;
import ghidra.pcodeCPort.semantics.*; import ghidra.pcodeCPort.semantics.*;
@ -89,12 +92,9 @@ public abstract class PcodeCompile {
public void reportError(Location location, String msg) { public void reportError(Location location, String msg) {
entry("reportError", location, msg); entry("reportError", location, msg);
if (location == null) {
log.error(msg); log.error(MessageFormattingUtils.format(location, msg));
}
else {
log.error(location + ": " + msg);
}
++errors; ++errors;
} }
@ -104,12 +104,9 @@ public abstract class PcodeCompile {
public void reportWarning(Location location, String msg) { public void reportWarning(Location location, String msg) {
entry("reportWarning", location, msg); entry("reportWarning", location, msg);
if (location == null) {
log.warn(msg); log.warn(MessageFormattingUtils.format(location, msg));
}
else {
log.warn(location + ": " + msg);
}
++warnings; ++warnings;
} }
@ -147,7 +144,8 @@ public abstract class PcodeCompile {
if ((size.getType() == ConstTpl.const_type.real) && if ((size.getType() == ConstTpl.const_type.real) &&
(vn.getSize().getType() == ConstTpl.const_type.real) && (vn.getSize().getType() == ConstTpl.const_type.real) &&
(vn.getSize().getReal() != 0) && (vn.getSize().getReal() != size.getReal())) { (vn.getSize().getReal() != 0) && (vn.getSize().getReal() != size.getReal())) {
throw new SleighError("Localtemp size mismatch", null); throw new SleighError(String.format("Localtemp size mismatch: %d vs %d",
vn.getSize().getReal(), size.getReal()), op.location);
} }
vn.setSize(size); vn.setSize(size);
} }
@ -158,7 +156,8 @@ public abstract class PcodeCompile {
if ((size.getType() == ConstTpl.const_type.real) && if ((size.getType() == ConstTpl.const_type.real) &&
(vn.getSize().getType() == ConstTpl.const_type.real) && (vn.getSize().getType() == ConstTpl.const_type.real) &&
(vn.getSize().getReal() != 0) && (vn.getSize().getReal() != size.getReal())) { (vn.getSize().getReal() != 0) && (vn.getSize().getReal() != size.getReal())) {
throw new SleighError("Localtemp size mismatch", null); throw new SleighError(String.format("Input size mismatch: %d vs %d",
vn.getSize().getReal(), size.getReal()), op.location);
} }
vn.setSize(size); vn.setSize(size);
} }
@ -189,9 +188,8 @@ public abstract class PcodeCompile {
public VectorSTL<OpTpl> placeLabel(Location location, LabelSymbol labsym) { public VectorSTL<OpTpl> placeLabel(Location location, LabelSymbol labsym) {
entry("placeLabel", location, labsym); entry("placeLabel", location, labsym);
if (labsym.isPlaced()) { if (labsym.isPlaced()) {
String errmsg = "Label " + labsym.getName(); reportError(labsym.getLocation(),
errmsg += " is placed more than once"; String.format("Label '%s' is placed more than once", labsym.getName()));
reportError(labsym.getLocation(), errmsg);
} }
labsym.setPlaced(); labsym.setPlaced();
VectorSTL<OpTpl> res = new VectorSTL<OpTpl>(); VectorSTL<OpTpl> res = new VectorSTL<OpTpl>();
@ -272,7 +270,7 @@ public abstract class PcodeCompile {
tmpvn.getOffset().getReal(), (int) tmpvn.getSize().getReal()); tmpvn.getOffset().getReal(), (int) tmpvn.getSize().getReal());
addSymbol(sym); addSymbol(sym);
if ((!usesLocalKey) && enforceLocalKey) { if ((!usesLocalKey) && enforceLocalKey) {
reportError(location, "Must use 'local' keyword to define symbol: " + varname); reportError(location, "Must use 'local' keyword to define symbol '" + varname + "'");
} }
return ExprTree.toVector(rhs); return ExprTree.toVector(rhs);
} }
@ -465,7 +463,8 @@ public abstract class PcodeCompile {
return null; return null;
} }
if (byteoffset + numbytes > fullsz) { if (byteoffset + numbytes > fullsz) {
throw new SleighError("Requested bit range out of bounds", loc); throw new SleighError(String.format("Requested bit range out of bounds -- %d > %d",
(byteoffset + numbytes), fullsz), loc);
} }
} }
@ -841,10 +840,12 @@ public abstract class PcodeCompile {
} }
break; break;
case CPUI_CPOOLREF: case CPUI_CPOOLREF:
if (op.getOut().isZeroSize() && (!op.getIn(0).isZeroSize())) if (op.getOut().isZeroSize() && (!op.getIn(0).isZeroSize())) {
force_size(op.getOut(),op.getIn(0).getSize(),ops); force_size(op.getOut(),op.getIn(0).getSize(),ops);
if (op.getIn(0).isZeroSize() && (!op.getOut().isZeroSize())) }
if (op.getIn(0).isZeroSize() && (!op.getOut().isZeroSize())) {
force_size(op.getIn(0),op.getOut().getSize(),ops); force_size(op.getIn(0),op.getOut().getSize(),ops);
}
for(i=1;i<op.numInput();++i) { for(i=1;i<op.numInput();++i) {
force_size(op.getIn(i), new ConstTpl(ConstTpl.const_type.real, 8), ops); force_size(op.getIn(i), new ConstTpl(ConstTpl.const_type.real, 8), ops);
} }
@ -891,19 +892,10 @@ public abstract class PcodeCompile {
public static void entry(String name, Object... args) { public static void entry(String name, Object... args) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(name); sb.append(name).append("(");
sb.append("("); sb.append(Arrays.stream(args).map(Object::toString).collect(Collectors.joining(", ")));
int argsSoFar = 0;
for (int ii = 0; ii < args.length; ++ii) {
if (!isLocationIsh(args[ii])) {
if (argsSoFar > 0) {
sb.append(", ");
}
sb.append(args[ii]);
++argsSoFar;
}
}
sb.append(")"); sb.append(")");
log.trace(sb.toString()); log.trace(sb.toString());
} }
@ -991,13 +983,15 @@ public abstract class PcodeCompile {
return createOpConst(location, OpCode.CPUI_INDIRECT, r.outvn.getOffset().getReal()); return createOpConst(location, OpCode.CPUI_INDIRECT, r.outvn.getOffset().getReal());
} }
if ("cpool".equals(name)) { if ("cpool".equals(name)) {
if (operands.size() >= 2) // At least two parameters if (operands.size() >= 2) { // At least two parameters
return createVariadic(location, OpCode.CPUI_CPOOLREF, operands); return createVariadic(location, OpCode.CPUI_CPOOLREF, operands);
}
reportError(location,name+"() expects at least two arguments"); reportError(location,name+"() expects at least two arguments");
} }
if ("newobject".equals(name)) { if ("newobject".equals(name)) {
if (operands.size() >= 1) // At least one parameter if (operands.size() >= 1) { // At least one parameter
return createVariadic(location, OpCode.CPUI_NEW, operands); return createVariadic(location, OpCode.CPUI_NEW, operands);
}
reportError(location,name+"() expects at least one argument"); reportError(location,name+"() expects at least one argument");
} }

View file

@ -17,6 +17,7 @@ package ghidra.pcodeCPort.slgh_compile;
import java.io.*; import java.io.*;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
import org.antlr.runtime.*; import org.antlr.runtime.*;
import org.antlr.runtime.tree.CommonTreeNodeStream; import org.antlr.runtime.tree.CommonTreeNodeStream;
@ -27,6 +28,7 @@ import org.jdom.*;
import generic.stl.VectorSTL; import generic.stl.VectorSTL;
import ghidra.app.plugin.processors.sleigh.SleighException; import ghidra.app.plugin.processors.sleigh.SleighException;
import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.pcode.utils.MessageFormattingUtils;
import ghidra.pcodeCPort.address.Address; import ghidra.pcodeCPort.address.Address;
import ghidra.pcodeCPort.context.SleighError; import ghidra.pcodeCPort.context.SleighError;
import ghidra.pcodeCPort.error.LowlevelError; import ghidra.pcodeCPort.error.LowlevelError;
@ -171,24 +173,24 @@ public class PcodeParser extends PcodeCompile {
// Make sure label symbols are used properly // Make sure label symbols are used properly
private String checkLabels() { private String checkLabels() {
StringBuilder s = new StringBuilder(); List<String> errors = new ArrayList<>();
for (SleighSymbol sym : symbolMap.values()) { for (SleighSymbol sym : symbolMap.values()) {
if (sym.getType() != symbol_type.label_symbol) { if (sym.getType() != symbol_type.label_symbol) {
continue; continue;
} }
LabelSymbol labsym = (LabelSymbol) sym; LabelSymbol labsym = (LabelSymbol) sym;
if (labsym.getRefCount() == 0) { if (labsym.getRefCount() == 0) {
s.append(" Label <"); errors.add(MessageFormattingUtils.format(labsym.location,
s.append(sym.getName()); String.format("Label <%s> was placed but never used", sym.getName())));
s.append("> was placed but not used");
} }
else if (!labsym.isPlaced()) { else if (!labsym.isPlaced()) {
s.append(" Label <"); errors.add(MessageFormattingUtils.format(labsym.location,
s.append(sym.getName()); String.format("Label <%s> was referenced but never placed", sym.getName())));
s.append("> was referenced but never placed");
} }
} }
return s.toString(); return errors.stream().collect(Collectors.joining(" "));
} }
private ConstructTpl buildConstructor(ConstructTpl rtl) { private ConstructTpl buildConstructor(ConstructTpl rtl) {

View file

@ -20,11 +20,13 @@ import java.io.PrintStream;
import java.util.*; import java.util.*;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.antlr.runtime.RecognitionException; import org.antlr.runtime.RecognitionException;
import org.jdom.JDOMException; import org.jdom.JDOMException;
import generic.stl.*; import generic.stl.*;
import ghidra.pcode.utils.MessageFormattingUtils;
import ghidra.pcodeCPort.address.Address; import ghidra.pcodeCPort.address.Address;
import ghidra.pcodeCPort.context.SleighError; import ghidra.pcodeCPort.context.SleighError;
import ghidra.pcodeCPort.error.LowlevelError; import ghidra.pcodeCPort.error.LowlevelError;
@ -72,25 +74,21 @@ public class SleighCompile extends SleighBase {
} }
public static void entry(String name, Object... args) { public static void entry(String name, Object... args) {
// StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
// sb.append(name); sb.append(name).append("(");
// sb.append("("); // @formatter:off
// int argsSoFar = 0; sb.append(Arrays.stream(args)
// for (int ii = 0; ii < args.length; ++ii) { .filter(a -> isLocationIsh(a))
// if (!isLocationIsh(args[ii])) { .map(Object::toString)
// if (argsSoFar > 0) { .collect(Collectors.joining(", ")));
// sb.append(", "); // @formatter:on
// } sb.append(")");
// sb.append(args[ii]); Msg.trace(SleighCompile.class, sb.toString());
// ++argsSoFar;
// }
// }
// sb.append(")");
// Msg.trace(SleighCompile.class, sb.toString());
} }
// Semantic pcode compiler // Semantic pcode compiler
public final PcodeCompile pcode = new PcodeCompile() { public final PcodeCompile pcode = new PcodeCompile() {
@Override @Override
public void reportError(Location location, String msg) { public void reportError(Location location, String msg) {
SleighCompile.this.reportError(location, msg); SleighCompile.this.reportError(location, msg);
@ -382,8 +380,10 @@ public class SleighCompile extends SleighBase {
final int symSize = sym.getSize(); final int symSize = sym.getSize();
if (symSize % 4 != 0) { if (symSize % 4 != 0) {
reportError(sym.location, "Invalid size of context register \"" + sym.getName() + reportError(sym.location,
"\" (" + symSize + "); must be a multiple of 4"); String.format(
"Invalid size of context register '%s' (%d); must be a multiple of 4",
sym.getName(), symSize));
} }
final int maxBits = symSize * 8 - 1; final int maxBits = symSize * 8 - 1;
@ -395,13 +395,15 @@ public class SleighCompile extends SleighBase {
int max = qual.high; int max = qual.high;
if (max - min > (8 * 4)) { if (max - min > (8 * 4)) {
reportError(qual.location, reportError(qual.location,
"Size of bitfield " + qual.name + "=(" + min + "," + max + ") larger than " + String.format(
(8 * 4) + " bits in context register \"" + sym.getName() + "\""); "Size of bitfield %s=(%d,%d) larger than %d bits in context register '%s'",
qual.name, min, (8 * 4), sym.getName()));
} }
if (max > maxBits) { if (max > maxBits) {
reportError(qual.location, reportError(qual.location, String.format(
"Scope of bitfield " + qual.name + "=(" + min + "," + max + "Scope of bitfield %s=(%d,%d) extends beyond the size of context register '%s' (%d)",
") extends beyond the size of context register \"" + sym.getName() + "\""); qual.name, min, max, sym.getName(), maxBits));
} }
j = i + 1; j = i + 1;
@ -489,7 +491,7 @@ public class SleighCompile extends SleighBase {
} }
if (tables.get(i).getPattern() == null) { if (tables.get(i).getPattern() == null) {
reportWarning(tables.get(i).getLocation(), reportWarning(tables.get(i).getLocation(),
"Unreferenced table: " + tables.get(i).getName()); "Unreferenced table: '" + tables.get(i).getName() + "'");
} }
} }
} }
@ -508,9 +510,9 @@ public class SleighCompile extends SleighBase {
return; return;
} }
if ((!warnunnecessarypcode) && (checker.getNumUnnecessaryPcode() > 0)) { if ((!warnunnecessarypcode) && (checker.getNumUnnecessaryPcode() > 0)) {
Msg.warn(this, checker.getNumUnnecessaryPcode() + reportWarning(null, checker.getNumUnnecessaryPcode() +
" unnecessary extensions/truncations were converted to copies"); " unnecessary extensions/truncations were converted to copies");
Msg.warn(this, "Use -u switch to list each individually"); reportWarning(null, "Use -u switch to list each individually");
} }
checker.optimizeAll(); checker.optimizeAll();
if (checker.getNumReadNoWrite() > 0) { if (checker.getNumReadNoWrite() > 0) {
@ -518,9 +520,9 @@ public class SleighCompile extends SleighBase {
return; return;
} }
if ((!warndeadtemps) && (checker.getNumWriteNoRead() > 0)) { if ((!warndeadtemps) && (checker.getNumWriteNoRead() > 0)) {
Msg.warn(this, checker.getNumWriteNoRead() + reportWarning(null, checker.getNumWriteNoRead() +
" operations wrote to temporaries that were not read"); " operations wrote to temporaries that were not read");
Msg.warn(this, "Use -t switch to list each individually"); reportWarning(null, "Use -t switch to list each individually");
} }
} }
@ -560,10 +562,11 @@ public class SleighCompile extends SleighBase {
if (collideOperand >= 0) { if (collideOperand >= 0) {
noCollisions = false; noCollisions = false;
if (warnalllocalcollisions) { if (warnalllocalcollisions) {
Msg.warn(this, "Possible collision with symbol " + reportWarning(ct.location,
ct.getOperand(collideOperand).getName() + " and " + String.format(
ct.getOperand(i).getName() + " in constructor from " + ct.getFilename() + "Possible operand collision between symbols '%s' and '%s'",
" starting at line " + Integer.toString(ct.getLineno())); ct.getOperand(collideOperand).getName(), ct.getOperand(i).getName()));
} }
break; // Don't continue break; // Don't continue
} }
@ -589,10 +592,10 @@ public class SleighCompile extends SleighBase {
sym = tables.get(i); sym = tables.get(i);
} }
if (collisionCount > 0) { if (collisionCount > 0) {
Msg.warn(this, "WARNING: " + Integer.toString(collisionCount) + reportWarning(null,
" constructors with local collisions between operands"); collisionCount + " constructors with local collisions between operands");
if (!warnalllocalcollisions) { if (!warnalllocalcollisions) {
Msg.warn(this, "Use -c switch to list each individually"); reportWarning(null, "Use -c switch to list each individually");
} }
} }
} }
@ -600,7 +603,7 @@ public class SleighCompile extends SleighBase {
// Make sure label symbols are used properly // Make sure label symbols are used properly
String checkSymbols(SymbolScope scope) { String checkSymbols(SymbolScope scope) {
entry("checkSymbols", scope); entry("checkSymbols", scope);
StringBuilder s = new StringBuilder(); List<String> errors = new ArrayList<>();
IteratorSTL<SleighSymbol> iter; IteratorSTL<SleighSymbol> iter;
for (iter = scope.begin(); !iter.equals(scope.end()); iter.increment()) { for (iter = scope.begin(); !iter.equals(scope.end()); iter.increment()) {
SleighSymbol sym = iter.get(); SleighSymbol sym = iter.get();
@ -609,17 +612,15 @@ public class SleighCompile extends SleighBase {
} }
LabelSymbol labsym = (LabelSymbol) sym; LabelSymbol labsym = (LabelSymbol) sym;
if (labsym.getRefCount() == 0) { if (labsym.getRefCount() == 0) {
s.append(" Label <"); errors.add(MessageFormattingUtils.format(labsym.location,
s.append(sym.getName()); String.format("Label <%s> was placed but never used", sym.getName())));
s.append("> was placed but not used");
} }
else if (!labsym.isPlaced()) { else if (!labsym.isPlaced()) {
s.append(" Label <"); errors.add(MessageFormattingUtils.format(labsym.location,
s.append(sym.getName()); String.format("Label <%s> was referenced but never placed", sym.getName())));
s.append("> was referenced but never placed");
} }
} }
return s.toString(); return errors.stream().collect(Collectors.joining(" "));
} }
// Make sure symbol table errors are caught // Make sure symbol table errors are caught
@ -648,25 +649,28 @@ public class SleighCompile extends SleighBase {
pcode.resetLabelCount(); pcode.resetLabelCount();
} }
@Override
public void reportError(Location location, String msg) { public void reportError(Location location, String msg) {
entry("reportError", location, msg); entry("reportError", location, msg);
if (location == null) { super.reportError(location, msg);
Msg.error(this, msg);
}
else {
Msg.error(this, location + ": " + msg);
}
errors += 1; errors += 1;
} }
@Override
public void reportError(Location location, String msg, Throwable t) {
entry("reportError", location, msg);
super.reportError(location, msg, t);
errors += 1;
}
@Override
public void reportWarning(Location location, String msg) { public void reportWarning(Location location, String msg) {
entry("reportWarning", location, msg); entry("reportWarning", location, msg);
if (location == null) { super.reportWarning(location, msg);
Msg.warn(this, msg);
}
else {
Msg.warn(this, location + ": " + msg);
}
warnings += 1; warnings += 1;
} }
@ -757,7 +761,7 @@ public class SleighCompile extends SleighBase {
buildXrefs(); // Make sure we can build crossrefs properly buildXrefs(); // Make sure we can build crossrefs properly
} }
catch (SleighError err) { catch (SleighError err) {
Msg.error(this, err.getMessage(), err); Msg.error(this, err.location + ": " + err.getMessage(), err);
errors += 1; errors += 1;
return; return;
} }
@ -837,7 +841,8 @@ public class SleighCompile extends SleighBase {
entry("defineToken", location, name, sz); entry("defineToken", location, name, sz);
int size = (int) sz; int size = (int) sz;
if ((size & 7) != 0) { if ((size & 7) != 0) {
reportError(location, name + "token size must be multiple of 8"); reportError(location,
"Definition of '" + name + "' token -- size must be multiple of 8");
size = (size / 8) + 1; size = (size / 8) + 1;
} }
else { else {
@ -879,21 +884,24 @@ public class SleighCompile extends SleighBase {
public void newSpace(Location location, SpaceQuality qual) { public void newSpace(Location location, SpaceQuality qual) {
entry("newSpace", location, qual); entry("newSpace", location, qual);
if (qual.size == 0) { if (qual.size == 0) {
reportError(location, "Space definition missing size attribute"); reportError(location, "Space definition '" + qual.name + "' missing size attribute");
return; return;
} }
if (qual.size <= 0 || qual.size > 8) { if (qual.size <= 0 || qual.size > 8) {
throw new SleighError("Space " + qual.name + " has unsupported size: " + 16, location); throw new SleighError("Space '" + qual.name + "' has unsupported size: " + qual.size,
location);
} }
if (qual.wordsize < 1 || qual.wordsize > 8) { if (qual.wordsize < 1 || qual.wordsize > 8) {
throw new SleighError( throw new SleighError(
"Space " + qual.name + " has unsupported wordsize: " + qual.wordsize, location); "Space '" + qual.name + "' has unsupported wordsize: " + qual.wordsize, location);
} }
int addressBits = bitsConsumedByUnitSize(qual.wordsize) + (8 * qual.size); int addressBits = bitsConsumedByUnitSize(qual.wordsize) + (8 * qual.size);
if (addressBits > 64) { if (addressBits > 64) {
throw new SleighError("Space " + qual.name + " has unsupported dimensions, requires " + throw new SleighError(
addressBits + "-bits (limit is 64-bits)", location); "Space '" + qual.name + "' has unsupported dimensions: requires " + addressBits +
" bits -- limit is 64 bits",
location);
} }
int delay = (qual.type == space_class.register_space) ? 0 : 1; int delay = (qual.type == space_class.register_space) ? 0 : 1;
@ -902,7 +910,9 @@ public class SleighCompile extends SleighBase {
insertSpace(spc); insertSpace(spc);
if (qual.isdefault) { if (qual.isdefault) {
if (getDefaultSpace() != null) { if (getDefaultSpace() != null) {
reportError(location, "Multiple default spaces"); reportError(location,
"Multiple default spaces -- '" + getDefaultSpace().getName() + "', '" +
qual.name + "'");
} }
else { else {
setDefaultSpace(spc.getIndex()); // Make the flagged space setDefaultSpace(spc.getIndex()); // Make the flagged space
@ -949,11 +959,11 @@ public class SleighCompile extends SleighBase {
String namecopy = name; String namecopy = name;
int size = 8 * sym.getSize(); // Number of bits int size = 8 * sym.getSize(); // Number of bits
if (numb == 0) { if (numb == 0) {
reportError(location, "Size of bitrange is zero for: " + namecopy); reportError(location, "Size of bitrange is zero for '" + namecopy + "'");
return; return;
} }
if ((bitoffset >= size) || ((bitoffset + numb) > size)) { if ((bitoffset >= size) || ((bitoffset + numb) > size)) {
reportError(location, "Bad bitrange for: " + namecopy); reportError(location, "Bad bitrange for '" + namecopy + "'");
return; return;
} }
if ((bitoffset % 8 == 0) && (numb % 8 == 0)) { if ((bitoffset % 8 == 0) && (numb % 8 == 0)) {
@ -971,8 +981,8 @@ public class SleighCompile extends SleighBase {
} }
else { else {
if (size > 64) { if (size > 64) {
reportError(location, reportError(location, "'" + sym.getName() + "': " +
"Illegal bitrange on varnode larger than 64 bits: " + sym.getName()); "Illegal bitrange on varnode larger than 64 bits");
} }
// Otherwise define the special symbol // Otherwise define the special symbol
addSymbol(new BitrangeSymbol(location, namecopy, sym, bitoffset, numb)); addSymbol(new BitrangeSymbol(location, namecopy, sym, bitoffset, numb));
@ -984,8 +994,8 @@ public class SleighCompile extends SleighBase {
for (int i = 0; i < names.size(); ++i) { for (int i = 0; i < names.size(); ++i) {
boolean isInternal = pcode.isInternalFunction(names.get(i)); boolean isInternal = pcode.isInternalFunction(names.get(i));
if (isInternal) { if (isInternal) {
reportError(locations.get(i), reportError(locations.get(i), "'" + names.get(i) +
names.get(i) + " is an internal pcodeop and cannot be redefined as a pseudoop"); "' is an internal pcodeop and cannot be redefined as a pseudoop");
} }
UserOpSymbol sym = new UserOpSymbol(locations.get(i), names.get(i)); UserOpSymbol sym = new UserOpSymbol(locations.get(i), names.get(i));
sym.setIndex(userop_count++); sym.setIndex(userop_count++);
@ -1020,7 +1030,7 @@ public class SleighCompile extends SleighBase {
SleighSymbol dupsym = dedupSymbolList(symlist); SleighSymbol dupsym = dedupSymbolList(symlist);
if (dupsym != null) { if (dupsym != null) {
reportWarning(dupsym.location, reportWarning(dupsym.location,
"\"attach values\" list contains duplicate entries: " + dupsym.getName()); "'attach values' list contains duplicate entries: " + dupsym.getName());
} }
for (int i = 0; i < symlist.size(); ++i) { for (int i = 0; i < symlist.size(); ++i) {
Location location = locations.get(i); Location location = locations.get(i);
@ -1030,7 +1040,8 @@ public class SleighCompile extends SleighBase {
} }
PatternValue patval = sym.getPatternValue(); PatternValue patval = sym.getPatternValue();
if (patval.maxValue() + 1 != numlist.size()) { if (patval.maxValue() + 1 != numlist.size()) {
reportError(location, "Attach value " + sym + " is wrong size for list " + numlist); reportError(location,
"Attach value '" + sym + "' is wrong size for list: " + numlist);
} }
symtab.replaceSymbol(sym, new ValueMapSymbol(location, sym.getName(), patval, numlist)); symtab.replaceSymbol(sym, new ValueMapSymbol(location, sym.getName(), patval, numlist));
} }
@ -1042,7 +1053,7 @@ public class SleighCompile extends SleighBase {
SleighSymbol dupsym = dedupSymbolList(symlist); SleighSymbol dupsym = dedupSymbolList(symlist);
if (dupsym != null) { if (dupsym != null) {
reportWarning(dupsym.location, reportWarning(dupsym.location,
"\"attach names\" list contains duplicate entries: " + dupsym.getName()); "'attach names' list contains duplicate entries: " + dupsym.getName());
} }
for (int i = 0; i < symlist.size(); ++i) { for (int i = 0; i < symlist.size(); ++i) {
Location location = locations.get(i); Location location = locations.get(i);
@ -1052,7 +1063,7 @@ public class SleighCompile extends SleighBase {
} }
PatternValue patval = sym.getPatternValue(); PatternValue patval = sym.getPatternValue();
if (patval.maxValue() + 1 != names.size()) { if (patval.maxValue() + 1 != names.size()) {
reportError(location, "Attach name " + sym + " is wrong size for list " + names); reportError(location, "Attach name '" + sym + "' is wrong size for list: " + names);
} }
symtab.replaceSymbol(sym, new NameSymbol(location, sym.getName(), patval, names)); symtab.replaceSymbol(sym, new NameSymbol(location, sym.getName(), patval, names));
} }
@ -1064,7 +1075,7 @@ public class SleighCompile extends SleighBase {
SleighSymbol dupsym = dedupSymbolList(symlist); SleighSymbol dupsym = dedupSymbolList(symlist);
if (dupsym != null) { if (dupsym != null) {
reportWarning(dupsym.location, reportWarning(dupsym.location,
"\"attach variables\" list contains duplicate entries: " + dupsym.getName()); "'attach variables' list contains duplicate entries: " + dupsym.getName());
} }
for (int i = 0; i < symlist.size(); ++i) { for (int i = 0; i < symlist.size(); ++i) {
Location location = locations.get(i); Location location = locations.get(i);
@ -1073,7 +1084,7 @@ public class SleighCompile extends SleighBase {
continue; continue;
} }
if (firstContextField != null && sym.getId() == firstContextField) { if (firstContextField != null && sym.getId() == firstContextField) {
reportError(location, sym.getName() + reportError(location, "'" + sym.getName() + "'" +
" cannot be used to attach variables because it occurs at the lowest bit position in context at " + " cannot be used to attach variables because it occurs at the lowest bit position in context at " +
sym.getLocation()); sym.getLocation());
continue; continue;
@ -1081,7 +1092,7 @@ public class SleighCompile extends SleighBase {
PatternValue patval = sym.getPatternValue(); PatternValue patval = sym.getPatternValue();
if (patval.maxValue() + 1 != varlist.size()) { if (patval.maxValue() + 1 != varlist.size()) {
reportError(location, reportError(location,
"Attach varnode " + sym + " is wrong size for list " + varlist); "Attach varnode '" + sym + "' is wrong size for list: " + varlist);
} }
int sz = 0; int sz = 0;
for (int j = 0; j < varlist.size(); ++j) { for (int j = 0; j < varlist.size(); ++j) {
@ -1183,7 +1194,7 @@ public class SleighCompile extends SleighBase {
entry("selfDefine", sym); entry("selfDefine", sym);
SleighSymbol sleighSymbol = symtab.findSymbol(sym.getName(), 1); SleighSymbol sleighSymbol = symtab.findSymbol(sym.getName(), 1);
if (!(sleighSymbol instanceof TripleSymbol)) { if (!(sleighSymbol instanceof TripleSymbol)) {
reportError(sym.getLocation(), sym.getName() + ": No matching global symbol"); reportError(sym.getLocation(), "No matching global symbol '" + sym.getName() + "'");
return; return;
} }
TripleSymbol glob = (TripleSymbol) sleighSymbol; TripleSymbol glob = (TripleSymbol) sleighSymbol;
@ -1280,14 +1291,10 @@ public class SleighCompile extends SleighBase {
VectorSTL<ExprTree> param) { VectorSTL<ExprTree> param) {
entry("createMacroUse", location, sym, param); entry("createMacroUse", location, sym, param);
if (sym.getNumOperands() != param.size()) { if (sym.getNumOperands() != param.size()) {
String errmsg = "Invocation of macro \"" + sym.getName(); boolean tooManyParams = param.size() > sym.getNumOperands();
if (param.size() > sym.getNumOperands()) { reportError(sym.getLocation(), String.format("Invocation of macro '%s' passes too " +
errmsg += "\" passes too many parameters"; (tooManyParams ? "many" : "few") + " parameters", sym.getName()));
}
else {
errmsg += "\" passes too few parameters";
}
reportError(sym.getLocation(), errmsg);
return new VectorSTL<>(); return new VectorSTL<>();
} }
compareMacroParams(sym, param); compareMacroParams(sym, param);
@ -1416,28 +1423,34 @@ public class SleighCompile extends SleighBase {
String sectionstring = " Main section: "; String sectionstring = " Main section: ";
int max = vec.getMaxId(); int max = vec.getMaxId();
for (;;) { for (;;) {
String scopeString = cur.section.loc + ": " + sectionstring;
String errstring; String errstring;
errstring = checkSymbols(cur.scope); // Check labels in the section's scope errstring = checkSymbols(cur.scope); // Check labels in the section's scope
if (errstring.length() == 0) { if (errstring.length() != 0) {
myErrors.push_back(scopeString + errstring);
}
else {
if (!expandMacros(cur.section)) { if (!expandMacros(cur.section)) {
myErrors.push_back(sectionstring + "Could not expand macros"); myErrors.push_back(scopeString + "Could not expand macros");
} }
VectorSTL<Integer> check = new VectorSTL<>(); VectorSTL<Integer> check = new VectorSTL<>();
big.markSubtableOperands(check); big.markSubtableOperands(check);
Pair<Integer, Location> res = cur.section.fillinBuild(check, getConstantSpace()); Pair<Integer, Location> res = cur.section.fillinBuild(check, getConstantSpace());
if (res.first == 1) { if (res.first == 1) {
myErrors.push_back( myErrors.push_back(
sectionstring + "Duplicate BUILD statements at " + res.second); scopeString + "Duplicate BUILD statements at " + res.second);
} }
if (res.first == 2) { if (res.first == 2) {
myErrors.push_back( myErrors.push_back(
sectionstring + "Unnecessary BUILD statements at " + res.second); scopeString + "Unnecessary BUILD statements at " + res.second);
} }
if (!pcode.propagateSize(cur.section)) { if (!pcode.propagateSize(cur.section)) {
myErrors.push_back( myErrors.push_back(
sectionstring + "Could not resolve at least 1 variable size"); scopeString + "Could not resolve at least 1 variable size");
} }
} }
if (i < 0) { // These potential errors only apply to main section if (i < 0) { // These potential errors only apply to main section
@ -1452,7 +1465,7 @@ public class SleighCompile extends SleighBase {
} }
if (cur.section.delaySlot() != 0) { // Delay slot is present in this constructor if (cur.section.delaySlot() != 0) { // Delay slot is present in this constructor
if (root != big.getParent()) { // it is not in a root constructor if (root != big.getParent()) { // it is not in a root constructor
reportWarning(null, "Delay slot used in " + big); reportWarning(big.location, "Delay slot used in " + big);
} }
if (cur.section.delaySlot() > maxdelayslotbytes) { if (cur.section.delaySlot() > maxdelayslotbytes) {
maxdelayslotbytes = cur.section.delaySlot(); maxdelayslotbytes = cur.section.delaySlot();
@ -1476,7 +1489,7 @@ public class SleighCompile extends SleighBase {
if (!myErrors.empty()) { if (!myErrors.empty()) {
reportError(big.location, "in " + big); reportError(big.location, "in " + big);
for (int j = 0; j < myErrors.size(); ++j) { for (int j = 0; j < myErrors.size(); ++j) {
reportError(null, myErrors.get(j)); reportError(big.location, myErrors.get(j));
} }
return false; return false;
} }
@ -1594,8 +1607,8 @@ public class SleighCompile extends SleighBase {
PatternValue patternValue = valueSymbol.getPatternValue(); PatternValue patternValue = valueSymbol.getPatternValue();
if (patternValue instanceof TokenField) { if (patternValue instanceof TokenField) {
if (sleighSymbol.location != Location.INTERNALLY_DEFINED) { if (sleighSymbol.location != Location.INTERNALLY_DEFINED) {
reportWarning(patternValue.location, "token field " + reportWarning(patternValue.location, "token field '" +
sleighSymbol.getName() + " defined but never used"); sleighSymbol.getName() + "' defined but never used");
} }
} }
} }
@ -1648,12 +1661,12 @@ public class SleighCompile extends SleighBase {
String errstring = checkSymbols(symtab.getCurrentScope()); String errstring = checkSymbols(symtab.getCurrentScope());
if (errstring.length() != 0) { if (errstring.length() != 0) {
reportError(sym.getLocation(), reportError(sym.getLocation(),
" in definition of macro " + sym.getName() + ":" + errstring); "Error in definition of macro '" + sym.getName() + "': " + errstring);
return; return;
} }
if (!expandMacros(rtl)) { if (!expandMacros(rtl)) {
reportError(sym.getLocation(), reportError(sym.getLocation(),
"Could not expand submacro in definition of macro " + sym.getName()); "Could not expand submacro in definition of macro '" + sym.getName() + "'");
return; return;
} }
pcode.propagateSize(rtl); // Propagate size information (as much as possible) pcode.propagateSize(rtl); // Propagate size information (as much as possible)

View file

@ -118,7 +118,8 @@ public class TokenPattern {
setLeftEllipsis(true); setLeftEllipsis(true);
} }
else if (tok1.toklist.size() != minsize) { else if (tok1.toklist.size() != minsize) {
throw new SleighError("Mismatched pattern sizes", location); throw new SleighError(String.format("Mismatched pattern sizes -- %d vs %d",
tok1.toklist.size(), minsize), location);
} }
else if (tok1.toklist.size() == tok2.toklist.size()) { else if (tok1.toklist.size() == tok2.toklist.size()) {
throw new SleighError("Pattern size cannot vary (missing ... ?)", location); throw new SleighError("Pattern size cannot vary (missing ... ?)", location);
@ -132,7 +133,8 @@ public class TokenPattern {
setRightEllipsis(true); setRightEllipsis(true);
} }
else if (tok1.toklist.size() != minsize) { else if (tok1.toklist.size() != minsize) {
throw new SleighError("Mismatched pattern sizes", location); throw new SleighError(String.format("Mismatched pattern sizes -- %d vs %d",
tok1.toklist.size(), minsize), location);
} }
else if (tok1.toklist.size() == tok2.toklist.size()) { else if (tok1.toklist.size() == tok2.toklist.size()) {
throw new SleighError("Pattern size cannot vary (missing ... ?)", location); throw new SleighError("Pattern size cannot vary (missing ... ?)", location);
@ -142,7 +144,8 @@ public class TokenPattern {
if (tok2.getLeftEllipsis()) { if (tok2.getLeftEllipsis()) {
reversedirection = true; reversedirection = true;
if (tok2.toklist.size() != minsize) { if (tok2.toklist.size() != minsize) {
throw new SleighError("Mismatched pattern sizes", location); throw new SleighError(String.format("Mismatched pattern sizes -- %d vs %d",
tok2.toklist.size(), minsize), location);
} }
else if (tok1.toklist.size() == tok2.toklist.size()) { else if (tok1.toklist.size() == tok2.toklist.size()) {
throw new SleighError("Pattern size cannot vary (missing ... ?)", location); throw new SleighError("Pattern size cannot vary (missing ... ?)", location);
@ -150,7 +153,8 @@ public class TokenPattern {
} }
else if (tok2.getRightEllipsis()) { else if (tok2.getRightEllipsis()) {
if (tok2.toklist.size() != minsize) { if (tok2.toklist.size() != minsize) {
throw new SleighError("Mismatched pattern sizes", location); throw new SleighError(String.format("Mismatched pattern sizes -- %d vs %d",
tok1.toklist.size(), minsize), location);
} }
else if (tok1.toklist.size() == tok2.toklist.size()) { else if (tok1.toklist.size() == tok2.toklist.size()) {
throw new SleighError("Pattern size cannot vary (missing ... ?)", location); throw new SleighError("Pattern size cannot vary (missing ... ?)", location);
@ -158,7 +162,8 @@ public class TokenPattern {
} }
else { else {
if (tok2.toklist.size() != tok1.toklist.size()) { if (tok2.toklist.size() != tok1.toklist.size()) {
throw new SleighError("Mismatched pattern sizes", location); throw new SleighError(String.format("Mismatched pattern sizes -- %d vs %d",
tok2.toklist.size(), tok1.toklist.size()), location);
} }
} }
} }

View file

@ -16,6 +16,7 @@
package ghidra.pcodeCPort.slghsymbol; package ghidra.pcodeCPort.slghsymbol;
import generic.stl.VectorSTL; import generic.stl.VectorSTL;
import ghidra.pcode.utils.MessageFormattingUtils;
import ghidra.pcodeCPort.slghpattern.DisjointPattern; import ghidra.pcodeCPort.slghpattern.DisjointPattern;
public class DecisionProperties { public class DecisionProperties {
@ -35,7 +36,10 @@ public class DecisionProperties {
if ((!a.isError()) && (!b.isError())) { if ((!a.isError()) && (!b.isError())) {
a.setError(true); a.setError(true);
b.setError(true); b.setError(true);
identerrors.push_back("Constructors with identical patterns: \n " + a + "\n " + b);
String msg = "Constructors with identical patterns:\n " + a + "\n " + b;
identerrors.push_back(MessageFormattingUtils.format(a.location, msg));
identerrors.push_back(MessageFormattingUtils.format(b.location, msg));
} }
} }
@ -45,9 +49,12 @@ public class DecisionProperties {
if ((!a.isError()) && (!b.isError())) { if ((!a.isError()) && (!b.isError())) {
a.setError(true); a.setError(true);
b.setError(true); b.setError(true);
conflicterrors.push_back("Constructor patterns cannot be distinguished: \n" //
String msg = "Constructor patterns cannot be distinguished: \n" //
+ " " + pa + " " + a + "\n" // + " " + pa + " " + a + "\n" //
+ " " + pb + " " + b); + " " + pb + " " + b;
conflicterrors.push_back(MessageFormattingUtils.format(a.location, msg));
conflicterrors.push_back(MessageFormattingUtils.format(b.location, msg));
} }
} }
} }

View file

@ -35,10 +35,8 @@ public class SubtableSymbol extends TripleSymbol {
private TokenPattern pattern; private TokenPattern pattern;
private boolean beingbuilt, errors; private boolean beingbuilt, errors;
private VectorSTL<Constructor> construct = new VectorSTL<Constructor>(); // All // All the Constructors in this table
// the private VectorSTL<Constructor> construct = new VectorSTL<Constructor>();
// Constructors in
// this table
private DecisionNode decisiontree; private DecisionNode decisiontree;
public SubtableSymbol(Location location) { public SubtableSymbol(Location location) {