Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • opensrc/SMPStaticAnalyzer
1 result
Show changes
Commits on Source (1)
......@@ -398,7 +398,7 @@ public:
void EmitSPARKAdaForAllInsts(FILE *BodyFile); // Call SMPInstr::EmitSPARKAda() for all insts in block.
void EmitSPARKAdaDisasmOnly(FILE *BodyFile); // For coalesced blocks, emit disasm comments so the original code is visible.
void EmitSPARKAdaForExpression(FILE *BodyFile); // For SingleExpression block, emit SPARK Ada expression
bool EmitSPARKAdaForExprUse(FILE *BodyFile, std::vector<SMPInstr *>::const_reverse_iterator RevInstIter, STARSOpndTypePtr UseOp, int UseSSANum); // Emit SPARK expression for UseOp at RevInstIter
bool EmitSPARKAdaForExprUse(FILE *BodyFile, std::vector<SMPInstr *>::const_reverse_iterator RevInstIter, const STARSOpndTypePtr &UseOp, int UseSSANum); // Emit SPARK expression for UseOp at RevInstIter
// Analysis methods
bool AllPredecessorsNumbered(void);
......@@ -491,6 +491,7 @@ public:
bool MarkTaintWarningInArgs(void); // Trace critical args for critical library calls back to InArgs, if possible. Return true if critical arg traced to InArg.
// Is DefOp+DefSSANum (from WorkList head) at DefAddr used as address reg or as source operand in unsafe memory write?
bool IsDefUsedInUnsafeMemWrite(std::list<std::pair<std::pair<STARSOpndTypePtr, int>, STARS_ea_t> > &WorkList, const STARSOpndTypePtr &DefOp, int DefSSANum, STARS_ea_t DefAddr);
bool IsNextDownwardUseNotByExternalCallInst(const STARSOpndTypePtr &UseRegOp); // Trace downward only; is next USE of UseRegOp not in a CALL-to-linker-stub inst?
STARS_sval_t ComputeStackAdjustmentAfterCall(STARS_ea_t CallAddr); // find stack pointer adjustment code after call, return stack delta or zero
STARS_ea_t FindFixedCallFallThrough(void) const; // Find the push operand that passed the fall-through address to a fixed call
......@@ -582,7 +583,7 @@ private:
STARSOpndSetIter EraseLiveOut(STARSOpndSetIter LiveOutIter);
STARSOpndSetIter EraseUpExposed(STARSOpndSetIter UpExposedIter);
STARSOpndSetIter EraseVarKill(STARSOpndSetIter VarKillIter);
void EmitSPARKAdaExprHelper(FILE *BodyFile, SMPInstr *CompareInst, const STARSOpndTypePtr LeftOp, const STARSOpndTypePtr LeftOpNoNorm, const bool HeaderBlock, const bool UseFP);
void EmitSPARKAdaExprHelper(FILE *BodyFile, SMPInstr *CompareInst, const STARSOpndTypePtr &LeftOp, const STARSOpndTypePtr &LeftOpNoNorm, const bool HeaderBlock, const bool UseFP);
std::set<SMPPhiFunction, LessPhi>::iterator InferPhiDefType(std::set<SMPPhiFunction, LessPhi>::iterator DefPhi, bool &changed); // infer, propagate to all uses
#if STARS_BUILD_DEF_USE_CHAINS
unsigned int GetLocalDUIndex(STARSOpndTypePtr DefOp, int SSANum);
......
......@@ -837,7 +837,8 @@ public:
inline std::set<DefOrUse, LessDefUse>::const_iterator GetFirstConstRef(void) const { return Refs.cbegin(); };
inline std::set<DefOrUse, LessDefUse>::const_iterator GetLastConstRef(void) const { return Refs.cend(); };
std::set<DefOrUse, LessDefUse>::iterator FindRef(const STARSOpndTypePtr &SearchOp);
std::set<DefOrUse, LessDefUse>::const_iterator FindConstRef(const STARSOpndTypePtr &SearchOp) const;
// Set methods
// Insert a new DEF or USE; must be new, insert must succeed else we assert.
std::set<DefOrUse, LessDefUse>::iterator InsertRef(DefOrUse Ref);
......
......@@ -213,7 +213,7 @@ extern const char *OperatorText[]; // for printing operators in Dump() methods a
void PrintOperandSPARKAdaSuffix(const STARSOpndTypePtr &Opnd, FILE *OutFile);
// Print an operator in SPARK-Ada form.
void PrintSPARKAdaOperator(SMPoperator Oper, std::string &OutString, bool &PrefixProcCall, bool &PrefixUnary, bool ConstFollows = false);
void PrintSPARKAdaOperator(SMPoperator Oper, std::string &OutString, bool &PrefixProcCall, bool &PrefixUnary, bool ConstFollows, bool ShortCircuitExpr = false);
// Print current indentation level using tabs.
void PrintSPARKIndentTabs(FILE *OutFile);
......@@ -821,6 +821,8 @@ public:
// Query methods
inline bool RegOpndMatches(std::size_t OpndNum, STARS_regnum_t RegNum) const { return STARSInstPtr->RegOpndMatches(OpndNum, RegNum); };
inline bool IsOpndUsed(const STARSOpndTypePtr &CurrOp) const { return (Uses.FindConstRef(CurrOp) != Uses.GetLastConstRef()); };
inline bool IsOpndDefined(const STARSOpndTypePtr &CurrOp) const { return (Defs.FindConstRef(CurrOp) != Defs.GetLastConstRef()); };
bool HasDestMemoryOperand(void) const; // Does instruction write to memory?
bool HasSourceMemoryOperand(void) const; // Does instruction read from memory?
inline bool HasIndirectMemoryWrite(void) const { return (booleans2 & INSTR_SET_INDIRECT_MEM_WRITE); };
......
......@@ -686,7 +686,7 @@ void SMPBasicBlock::EmitSPARKAdaDisasmOnly(FILE *BodyFile) {
}
// Factored-out operand emitter.
void SMPBasicBlock::EmitSPARKAdaExprHelper(FILE *BodyFile, SMPInstr *CompareInst, const STARSOpndTypePtr LeftOp, const STARSOpndTypePtr LeftOpNoNorm, const bool HeaderBlock, const bool UseFP) {
void SMPBasicBlock::EmitSPARKAdaExprHelper(FILE *BodyFile, SMPInstr *CompareInst, const STARSOpndTypePtr &LeftOp, const STARSOpndTypePtr &LeftOpNoNorm, const bool HeaderBlock, const bool UseFP) {
if (LeftOp->IsImmedOp() || HeaderBlock) {
if (!LeftOp->IsImmedOp()) {
CompareInst->PrintSPARKAdaOperand(LeftOpNoNorm, BodyFile, false, UseFP, true, false);
......@@ -706,7 +706,8 @@ void SMPBasicBlock::EmitSPARKAdaExprHelper(FILE *BodyFile, SMPInstr *CompareInst
SMP_fprintf(BodyFile, "ERROR in compare operand\n");
}
}
}
return;
} // end of SMPBasicBlock::EmitSPARKAdaExprHelper()
// For SingleExpression block, emit SPARK Ada expression
......@@ -921,7 +922,7 @@ void SMPBasicBlock::EmitSPARKAdaForExpression(FILE *BodyFile) {
} // end of SMPBasicBlock::EmitSPARKAdaForExpression()
// Emit SPARK expression for *UseIter at RevInstIter
bool SMPBasicBlock::EmitSPARKAdaForExprUse(FILE *BodyFile, vector<SMPInstr *>::const_reverse_iterator RevInstIter, STARSOpndTypePtr UseOp, int UseSSANum) {
bool SMPBasicBlock::EmitSPARKAdaForExprUse(FILE *BodyFile, vector<SMPInstr *>::const_reverse_iterator RevInstIter, const STARSOpndTypePtr &UseOp, int UseSSANum) {
// Search backwards in this block for DEF of UseIter operand. If not found,
// just print UseIter operand. If DEF found, recursively follow and print ultimate DEF expression.
bool Printed = false;
......@@ -985,12 +986,8 @@ bool SMPBasicBlock::EmitSPARKAdaForExprUse(FILE *BodyFile, vector<SMPInstr *>::c
bool PrefixUnaryOperator = false;
bool ConstFollows = (!DefRT->HasRightSubTree()) && DefRT->GetConstRightOperandNoNorm()->IsImmedOp();
SMPoperator DefRTOperator = DefRT->GetOperator();
PrintSPARKAdaOperator(DefRTOperator, OperatorString, OperatorIsProcCall, PrefixUnaryOperator, ConstFollows);
if (OperatorIsProcCall) {
SMP_fprintf(BodyFile, "ERROR ");
return true;
}
if (PrefixUnaryOperator) {
PrintSPARKAdaOperator(DefRTOperator, OperatorString, OperatorIsProcCall, PrefixUnaryOperator, ConstFollows, true);
if (PrefixUnaryOperator || OperatorIsProcCall) {
SMP_fprintf(BodyFile, "%s(", OperatorString.c_str());
}
else {
......@@ -1012,13 +1009,19 @@ bool SMPBasicBlock::EmitSPARKAdaForExprUse(FILE *BodyFile, vector<SMPInstr *>::c
SMP_fprintf(BodyFile, ") ");
}
else { // Have tracked & printed DefLeftOp; now print infix operator, then right-hand-side.
SMP_fprintf(BodyFile, " %s ", OperatorString.c_str());
if (!OperatorIsProcCall) { // Proc call is already printed; not infix
SMP_fprintf(BodyFile, " %s ", OperatorString.c_str());
}
if ((SMP_DECREMENT == DefRTOperator) || (SMP_INCREMENT == DefRTOperator)) {
Printed = true; // Operator string was +1 or -1; no right operand
SMP_fprintf(BodyFile, ") ");
}
else {
// If we have yet another right tree, terminate the tracking by printing it.
if (OperatorIsProcCall) {
// Separate left and right operands with a comma.
SMP_fprintf(BodyFile, ", ");
}
if (DefRT->HasRightSubTree()) {
SMP_fprintf(BodyFile, " (");
DefRT->EmitSPARKAdaForRHS(BodyFile, true);
......@@ -2591,9 +2594,7 @@ void SMPBasicBlock::SCCPGlobalPropagationHelper(const STARSOpndTypePtr &GlobalOp
}
else if (this->IsUpExposed(GlobalOp)) { // case 2
FoundReDEF = false;
vector<SMPInstr *>::iterator InstIter;
for (InstIter = this->GetFirstInst(); InstIter != this->GetLastInst(); ++InstIter) {
SMPInstr *CurrInst = (*InstIter);
for (SMPInstr *CurrInst : this->InstVec) {
set<DefOrUse, LessDefUse>::iterator UseIter = CurrInst->FindUse(GlobalOp);
if (UseIter != CurrInst->GetLastUse()) { // operand is USEd; check SSANum
int UseSSANum = UseIter->GetSSANum();
......@@ -5216,8 +5217,7 @@ bool SMPBasicBlock::IsDefOnlyUsedAsAddressReg(STARS_ea_t DefAddr, const STARSOpn
vector<SMPInstr *>::iterator InstIter;
STARSOpndTypePtr SearchOp = DefOp;
set<DefOrUse, LessDefUse>::iterator UseIter;
for (InstIter = this->GetFirstInst(); InstIter != this->GetLastInst(); ++InstIter) {
SMPInstr *CurrInst = (*InstIter);
for (SMPInstr *CurrInst : this->InstVec) {
STARS_ea_t InstAddr = CurrInst->GetAddr();
if (CurrInst->IsMarkerInst())
continue;
......@@ -5314,8 +5314,7 @@ bool SMPBasicBlock::IsDefUsedInLoopCompareAndBranch(STARS_ea_t DefAddr, const ST
set<DefOrUse, LessDefUse>::iterator UseIter;
bool FoundDefAddrInst = false;
for (InstIter = this->GetFirstInst(); InstIter != this->GetLastInst(); ++InstIter) {
SMPInstr *CurrInst = (*InstIter);
for (SMPInstr *CurrInst : this->InstVec) {
STARS_ea_t InstAddr = CurrInst->GetAddr();
if (CurrInst->IsMarkerInst())
continue;
......@@ -5521,6 +5520,41 @@ bool SMPBasicBlock::FindSingleExpression(void) {
} // end while reverse inst iteration
} // end if COND_BRANCH for LastInst
// Don't classify as single-expr if the block has register side effects.
if (FoundSingleExpr) {
for (STARSOpndTypePtr KillOp : this->KillSet) {
assert(KillOp->IsRegOp());
if (this->IsLiveOut(KillOp)) {
// We make one exception. The DEADREGS annotations are conservative, partly depending on
// the addition of numerous registers to the USE and DEF lists for external (linker-resolved)
// function calls. In particular, it is probably too conservative to assume that the register
// used for func return values is a USE of the external func (e.g. RAX in X86).
// We don't want to trust the LiveOut status of the return reg; we want to see if is next use
// on all paths out of the current block is for a CALL to an external func. If so, it is not
// sufficient cause to invalidate our SingleExpr determination.
bool ReturnValueReg = (MD_RETURN_VALUE_REG == KillOp->GetReg());
bool InvalidatingUse = false;
if (ReturnValueReg) {
int CurrBlockNum = this->GetNumber();
for (SMPBasicBlock *SuccBlock : this->GetConstSuccList()) {
// bool BackEdge = (SuccBlock->GetNumber() <= CurrBlockNum);
if (SuccBlock->IsLiveIn(KillOp)) { // Only LiveIn paths are worth following.
this->GetFunc()->ResetProcessedBlocks();
InvalidatingUse = SuccBlock->IsNextDownwardUseNotByExternalCallInst(KillOp);
if (InvalidatingUse)
break; // Any non-call-to-linker-stub use is final failure for this search.
}
} // end for all successor blocks
}
if ((!ReturnValueReg) || InvalidatingUse) {
FoundSingleExpr = false;
SMP_msg("WARNING: SPARK: SingleExpr block %d invalidated due to LiveOut reg %s ", this->GetNumber(), MDGetRegName(KillOp));
this->GetFunc()->DumpFuncNameAndAddr();
}
}
} // end for all KillSet operands
}
return FoundSingleExpr;
} // end of SMPBasicBlock::FindSingleExpression()
......@@ -8103,6 +8137,62 @@ bool SMPBasicBlock::IsDefUsedInUnsafeMemWrite(list<pair<pair<STARSOpndTypePtr, i
return FoundMemWriteUse;
} // end of SMPBasicBlock::IsDefUsedInUnsafeMemWrite()
// Trace downward only; is next USE of UseRegOp not in a CALL-to-linker-stub inst?
bool SMPBasicBlock::IsNextDownwardUseNotByExternalCallInst(const STARSOpndTypePtr &UseRegOp) {
bool FoundNonCallUse = false;
bool FoundCallUse = false;
bool UseSeen = false;
bool RedefinedByCallee = false; // could be used to allow pass-through of non-linker-stub-call with no redef; dangerous
int CurrBlockNum = this->GetNumber();
if (!this->IsProcessed()) {
this->SetProcessed(true);
if (this->IsUpExposed(UseRegOp)) { // must be used in an inst in this block
for (SMPInstr *CurrInst : this->InstVec) {
if (CurrInst->IsOpndUsed(UseRegOp)) {
UseSeen = true;
FoundCallUse = (CALL == CurrInst->GetDataFlowType());
if (FoundCallUse) {
// Internal calls have actual analysis of USEs, not just assumptions.
// We want to accept their USE of a register as precise, but not
// the pseudo-USEs by external (linker-resolved) calls.
STARS_ea_t CallTargetAddr = CurrInst->GetCallTarget();
FoundCallUse = (STARS_BADADDR != CallTargetAddr);
if (FoundCallUse) {
SMPFunction *TargetFunc = this->GetFunc()->GetProg()->FindFunction(CallTargetAddr);
FoundCallUse = ((nullptr != TargetFunc) && TargetFunc->IsLinkerStub());
RedefinedByCallee = CurrInst->IsOpndDefined(UseRegOp);
}
}
if (!FoundCallUse) {
FoundNonCallUse = true;
SMP_msg("INFO: SPARK: IsNextDownwardUseNotByExternalCallInst() returns true due to use at %llx of reg %s ",
(uint64_t)CurrInst->GetAddr(), RegNames[(size_t)UseRegOp->GetReg()]);
this->GetFunc()->DumpFuncNameAndAddr();
}
break;
}
} // end for all insts in block
assert(UseSeen); // UpExposed implies USE within block
}
if (!UseSeen && this->IsLiveOut(UseRegOp) && (!this->IsVarKill(UseRegOp))) { // pass-through case
// Recurse into successors
for (SMPBasicBlock *SuccBlock : this->GetConstSuccList()) {
// bool BackEdge = (CurrBlockNum >= SuccBlock->GetNumber());
if (SuccBlock->IsLiveIn(UseRegOp)) {
bool SuccNonCallUse = SuccBlock->IsNextDownwardUseNotByExternalCallInst(UseRegOp);
FoundNonCallUse = SuccNonCallUse;
if (SuccNonCallUse) {
break; // one true path makes final result true
}
}
} // end for all successor blocks
}
}
return FoundNonCallUse;
} // end of SMPBasicBlock::IsNextDownwardUseByExternalCallInst()
// recursive allocation/copy of subexprs into new expr.
STARSCondExpr *STARSCondExpr::DeepCopyExpr(void) {
STARSCondExpr *NewExpr = new STARSCondExpr(*this);
......
......@@ -3215,6 +3215,14 @@ set<DefOrUse, LessDefUse>::iterator DefOrUseSet::FindRef(const STARSOpndTypePtr
return CurrRef;
}
std::set<DefOrUse, LessDefUse>::const_iterator DefOrUseSet::FindConstRef(const STARSOpndTypePtr &SearchOp) const {
set<DefOrUse, LessDefUse>::const_iterator CurrRef;
DefOrUse DummyRef(SearchOp);
CurrRef = this->Refs.find(DummyRef);
return CurrRef;
}
// Insert a new DEF or USE; must be new, insert must succeed else we assert.
set<DefOrUse, LessDefUse>::iterator DefOrUseSet::InsertRef(DefOrUse Ref) {
pair<set<DefOrUse, LessDefUse>::iterator, bool> InsertResult;
......
......@@ -13635,6 +13635,21 @@ int SMPFunction::FindConditionalFollowNode4(const int HeadBlockNum, bool &IfThen
if (!TightError) {
TightError = (NFTNotDominated && NFTBlock->IsBlockPred(FTBlock) && (1 < FTForwardCount));
}
if (!TightError) {
// Tight merge might not be tight enough if it passes through a short circuit block set. Check.
STARSCFGBlock *FTCFGBlock = this->GetClonedCFGBlockByNum((size_t)FTBlockNum);
if (NFTNotDominated && FTCFGBlock->IsExprHeadBlock()) {
TightError = ((FTCFGBlock->GetExpr()->GetFallThroughBlockNum() == NFTBlockNum)
|| (FTCFGBlock->GetExpr()->GetNonFallThroughBlockNum() == NFTBlockNum));
}
if (!TightError) {
STARSCFGBlock *NFTCFGBlock = this->GetClonedCFGBlockByNum((size_t)NFTBlockNum);
if (FTNotDominated && NFTCFGBlock->IsExprHeadBlock()) {
TightError = ((NFTCFGBlock->GetExpr()->GetFallThroughBlockNum() == FTBlockNum)
|| (NFTCFGBlock->GetExpr()->GetNonFallThroughBlockNum() == FTBlockNum));
}
}
}
if (TightError) {
FollowBlockNum = SMP_BLOCKNUM_UNINIT;
IfThenCase = false;
......@@ -13818,6 +13833,9 @@ int SMPFunction::FindConditionalFollowNode4(const int HeadBlockNum, bool &IfThen
this->DumpDotCFG();
}
}
if (!SafeCloning) {
FollowBlockNum = SMP_BLOCKNUM_UNINIT; // Not cloning
}
}
else if (OddIfThenError) { // NFTNotDominated is the problem; clone starting at NFT
this->ResetTCFGVisitedBlocks();
......@@ -1083,7 +1083,7 @@ void SMPInstr::PrintSPARKAdaAddressExpr(const STARSOpndTypePtr &Opnd, FILE *OutF
} // end of PrintSPARKAdaAddressExpr()
 
// Print an operator in SPARK-Ada form.
void PrintSPARKAdaOperator(SMPoperator Oper, string &OutString, bool &PrefixProcCall, bool &PrefixUnary, bool ConstFollows) {
void PrintSPARKAdaOperator(SMPoperator Oper, string &OutString, bool &PrefixProcCall, bool &PrefixUnary, bool ConstFollows, bool ShortCircuitExpr) {
PrefixProcCall = false;
PrefixUnary = false;
 
......@@ -1115,27 +1115,52 @@ void PrintSPARKAdaOperator(SMPoperator Oper, string &OutString, bool &PrefixProc
 
case SMP_U_LEFT_SHIFT: // unsigned left shift
case SMP_REVERSE_SHIFT_U: // Shift right operand by bit count in left operand
OutString = " Interfaces.Shift_Left";
if (ShortCircuitExpr) {
OutString = " X86.Shift_Left_Func";
}
else {
OutString = " Interfaces.Shift_Left";
}
PrefixProcCall = true;
break;
 
case SMP_U_RIGHT_SHIFT: // unsigned right shift
OutString = " Interfaces.Shift_Right";
if (ShortCircuitExpr) {
OutString = " X86.Shift_Right_Func";
}
else {
OutString = " Interfaces.Shift_Right";
}
PrefixProcCall = true;
break;
 
case SMP_S_RIGHT_SHIFT: // signed right shift
OutString = " Interfaces.Shift_Right_Arithmetic";
if (ShortCircuitExpr) {
OutString = " X86.Shift_Right_Arithmetic_Func";
}
else {
OutString = " Interfaces.Shift_Right_Arithmetic";
}
PrefixProcCall = true;
break;
 
case SMP_ROTATE_LEFT:
OutString = " Interfaces.Rotate_Left";
if (ShortCircuitExpr) {
OutString = " X86.Rotate_Left_Func";
}
else {
OutString = " Interfaces.Rotate_Left";
}
PrefixProcCall = true;
break;
 
case SMP_ROTATE_RIGHT:
OutString = " Interfaces.Rotate_Right";
if (ShortCircuitExpr) {
OutString = " X86.Rotate_Right_Func";
}
else {
OutString = " Interfaces.Rotate_Right";
}
PrefixProcCall = true;
break;
 
......@@ -1291,11 +1316,10 @@ void PrintSPARKAdaOperator(SMPoperator Oper, string &OutString, bool &PrefixProc
PrefixUnary = true;
break;
 
// Odd binary operations
case SMP_GENERAL_COMPARE: // comparisons of packed data, strings, signed, unsigned depending on control words
case SMP_UNARY_NUMERIC_OPERATION: // miscellaneous; produces NUMERIC result
case SMP_BINARY_NUMERIC_OPERATION: // miscellaneous; produces NUMERIC result
case SMP_SYSTEM_OPERATION: // for instructions such as CPUID, RDTSC, etc.; NUMERIC
case SMP_UNARY_FLOATING_ARITHMETIC: // all the same to our type system; all NUMERIC
case SMP_BINARY_FLOATING_ARITHMETIC: // all the same to our type system; all NUMERIC
 
case SMP_SHUFFLE: // Shuffle bytes, words, etc. within destination operation per source mask
......@@ -1314,15 +1338,24 @@ void PrintSPARKAdaOperator(SMPoperator Oper, string &OutString, bool &PrefixProc
case SMP_MAX_U: // dest := unsigned_max(dest, src)
case SMP_MIN_S: // dest := signed_min(dest, src)
case SMP_MIN_U: // dest := unsigned_min(dest, src)
case SMP_ABSOLUTE_VALUE: // take absolute value
case SMP_CREATE_MASK: // Create AND-mask from operand and byte/word/dword position # in immediate
case SMP_INTERLEAVE: // extended-precision interleaving of bytes or words or dwords etc.; NUMERIC
case SMP_CONCATENATE: // extended-precision concatenation; NUMERIC
case SMP_EXTRACT_ZERO_EXTEND: // Extract sub-reg and zero-extend to reg length
case SMP_ENCRYPTION_OPERATION: // encryption or decryption bit manipulation operation
case SMP_UNARY_POINTER_OPERATION:
case SMP_SIGNAL: // signal or raise exception
default:
SMP_msg("ERROR: SPARK: Cannot translate unknown operator: ");
SMP_msg(" %s \n", OperatorText[Oper]);
OutString = "X86.StrangeArithmetic";
PrefixProcCall = true;
break;
// Odd unary operations
case SMP_UNARY_NUMERIC_OPERATION: // miscellaneous; produces NUMERIC result
case SMP_UNARY_FLOATING_ARITHMETIC: // all the same to our type system; all NUMERIC
case SMP_ABSOLUTE_VALUE: // take absolute value
case SMP_UNARY_POINTER_OPERATION:
SMP_msg("ERROR: SPARK: Cannot translate unknown operator: ");
SMP_msg(" %s \n", OperatorText[Oper]);
OutString = "ERROR";
......@@ -2054,7 +2087,7 @@ void SMPRegTransfer::EmitSPARKAdaForRHS(FILE *OutFile, bool RecursiveCall) const
SMP_fprintf(OutFile, "(");
SMPoperator CurrOper = RightRT->GetOperator();
bool ConstFollows = (!RightRT->HasRightSubTree()) && RightRT->GetConstRightOperandNoNorm()->IsImmedOp();
PrintSPARKAdaOperator(CurrOper, OperatorString, OperatorIsProcCall, PrefixUnaryOperator, ConstFollows);
PrintSPARKAdaOperator(CurrOper, OperatorString, OperatorIsProcCall, PrefixUnaryOperator, ConstFollows, false);
const STARSOpndTypePtr LeftOp = RightRT->GetConstLeftOperandNoNorm();
if (!OperatorIsProcCall) {
if (!PrefixUnaryOperator) {
......@@ -2152,7 +2185,7 @@ void SMPRegTransfer::EmitSPARKAda(FILE *OutFile) {
if (!SubregWrite) {
// Print := operator unless we are assigning with a procedure call.
string OutString;
PrintSPARKAdaOperator(CurrOper, OutString, OperatorIsProcCall, PrefixUnaryOperator, false);
PrintSPARKAdaOperator(CurrOper, OutString, OperatorIsProcCall, PrefixUnaryOperator, false, false);
assert(!OperatorIsProcCall);
assert(!PrefixUnaryOperator);
SMP_fprintf(OutFile, "%s", OutString.c_str());
......@@ -2837,7 +2870,7 @@ void STARSExpression::EmitSPARKAda(FILE *OutputFile, bool ProcessingLoop, bool O
}
 
if (SMP_ASSIGN != CurrOperator) {
PrintSPARKAdaOperator(CurrOperator, OperatorString, PrefixProcCall, UnaryPrefix, ConstFollows);
PrintSPARKAdaOperator(CurrOperator, OperatorString, PrefixProcCall, UnaryPrefix, ConstFollows, false);
if (PrefixProcCall) { // operator comes first, as a procedure call
SMP_fprintf(OutputFile, "%s(", OperatorString.c_str());
}
......@@ -2964,7 +2997,7 @@ void STARSExpression::EmitSPARKAdaString(std::string &OutString, bool Processing
}
 
if (SMP_ASSIGN != CurrOperator) {
PrintSPARKAdaOperator(CurrOperator, OperatorString, PrefixProcCall, UnaryPrefix, ConstFollows);
PrintSPARKAdaOperator(CurrOperator, OperatorString, PrefixProcCall, UnaryPrefix, ConstFollows, false);
if (PrefixProcCall) { // operator comes first, as a procedure call
OutString.append(OperatorString);
OutString.append("(");
......@@ -6278,7 +6311,7 @@ void SMPInstr::MDEmitSPARKAdaArithmeticSetsCondCodes(FILE *OutFile) {
} // end for all LiveFlagRegs set members
}
 
PrintSPARKAdaOperator(CurrOper, OperatorString, PrefixProcCall, PrefixUnary, ConstFollows);
PrintSPARKAdaOperator(CurrOper, OperatorString, PrefixProcCall, PrefixUnary, ConstFollows, false);
 
if (!ProcCallHandlesCondCodes) {
bool Subtraction = OperatorString == " - ";
......@@ -7379,7 +7412,7 @@ void SMPInstr::EmitSPARKAda(FILE *OutFile, const bool DisAsmOnly) {
 
case HALT:
break;
}
} // end switch on flow type
 
if (PrintOperands) {
int BlockNum = this->GetBlock()->GetNumber();