From 0c9e73fd72db0239430370e209ab734b78ed4c77 Mon Sep 17 00:00:00 2001
From: clc5q <clc5q@git.zephyr-software.com>
Date: Fri, 4 Dec 2015 17:43:05 +0000
Subject: [PATCH] Fixes and cleanups for SPARK Ada translation.

Former-commit-id: 1e20c1306f474f69e082dbe7ee97644df311a360
---
 include/base/SMPDataFlowAnalysis.h |  5 +-
 include/base/SMPFunction.h         |  2 +-
 src/base/SMPDataFlowAnalysis.cpp   | 50 +++++++++++++++++++
 src/base/SMPFunction.cpp           | 80 +++++++++++++++++-------------
 src/base/SMPInstr.cpp              | 10 +++-
 src/base/SMPProgram.cpp            |  2 +-
 6 files changed, 111 insertions(+), 38 deletions(-)

diff --git a/include/base/SMPDataFlowAnalysis.h b/include/base/SMPDataFlowAnalysis.h
index 9d154a7f..97dcef60 100644
--- a/include/base/SMPDataFlowAnalysis.h
+++ b/include/base/SMPDataFlowAnalysis.h
@@ -983,7 +983,10 @@ unsigned int CountBitsSet(unsigned int ArgPosBits);
 // Utility to get highest bit set in a byte.
 unsigned int HighestBitSet(unsigned char Byte);
 
-// Is FuncName a standard library function name?
+// Is CalleeName a standard library function name?
 bool IsLibFuncName(std::string CalleeName);
 
+// Is FuncName a startup func called before main(), or a wrapup function called by the system?
+bool IsStartupFuncName(const std::string FuncName);
+
 #endif
diff --git a/include/base/SMPFunction.h b/include/base/SMPFunction.h
index 7d571923..20314964 100644
--- a/include/base/SMPFunction.h
+++ b/include/base/SMPFunction.h
@@ -626,7 +626,7 @@ private:
 	void UpdateLoopFollowBlockNum(int HeaderBlockNum, int FollowBlockNum);
 	int GetLoopNumFromHeaderBlockNum(const int HeaderBlockNum) const; // return -1 if HeaderBlockNum is not a loop header block #
 	std::size_t FindLoopNumFromHeadBlockNum(int LoopHeaderBlockNum) const;  // find loop # corresponding to header block num
-	int FindFollowBlockNum(SMPBasicBlock *CurrBlock); // Based on control flow structure of CurrBlock, find Ada follow block num; -1 if no structure besides fall-through
+	int FindFollowBlockNum(SMPBasicBlock *CurrBlock, bool StartAtLastInst = false); // Based on control flow structure of CurrBlock, find Ada follow block num; -1 if no structure besides fall-through
 	bool AnalyzeSwitchStatement(SMPBasicBlock *CurrBlock); // Analyze switch starting at indir jump at end of CurrBlock; return false if not well-structured
 	void FindSwitchIDom(struct SwitchTableInfo &TableInfo); // Mark jumps to default case, find IDom of entire switch statement
 	bool AnalyzeConditionalStatements(void); // Analyze if-then-elses starting at COND_BRANCH at end of all blocks; return false if not well-structured
diff --git a/src/base/SMPDataFlowAnalysis.cpp b/src/base/SMPDataFlowAnalysis.cpp
index ffacb4a7..719e0b6e 100644
--- a/src/base/SMPDataFlowAnalysis.cpp
+++ b/src/base/SMPDataFlowAnalysis.cpp
@@ -4267,3 +4267,53 @@ bool IsLibFuncName(std::string CalleeName) {
 
 	return false;
 } // end of IsLibFuncName()
+
+// Is FuncName a startup func called before main(), or a wrapup function called by the system?
+bool IsStartupFuncName(const std::string FuncName) {
+	bool NameMatched = false;
+	char IDA_func_name[STARS_MAXSTR];
+	std::size_t SkipCount;
+
+	SkipCount = strspn(FuncName.c_str(), "._");
+	std::string TempFuncName = FuncName.substr(SkipCount); // remove leading periods and underscores
+
+	if (0 == TempFuncName.compare("init_proc")) {
+		NameMatched = true;
+	}
+	else if (0 == TempFuncName.compare("init")) {
+		NameMatched = true;
+	}
+	else if (0 == TempFuncName.compare("start")) {
+		NameMatched = true;
+	}
+	else if (0 == TempFuncName.compare("gmon_start")) {
+		NameMatched = true;
+	}
+	else if (0 == TempFuncName.compare("call_gmon_start")) {
+		NameMatched = true;
+	}
+	else if (0 == TempFuncName.compare("libc_start_main")) {
+		NameMatched = true;
+	}
+	else if (0 == TempFuncName.compare("call_gmon_start__")) {
+		NameMatched = true;
+	}
+	else if (0 == TempFuncName.compare("libc_start_main__")) {
+		NameMatched = true;
+	}
+	else if (0 == TempFuncName.compare("libc_csu_init")) {
+		NameMatched = true;
+	}
+	else if (0 == TempFuncName.compare("libc_csu_fini")) {
+		NameMatched = true;
+	}
+	else if (0 == TempFuncName.compare("do_global_dtors_aux")) {
+		NameMatched = true;
+	}
+	else if (0 == TempFuncName.compare("term_proc")) {
+		NameMatched = true;
+	}
+
+
+	return NameMatched;
+}
diff --git a/src/base/SMPFunction.cpp b/src/base/SMPFunction.cpp
index 36005472..0eadc8e8 100644
--- a/src/base/SMPFunction.cpp
+++ b/src/base/SMPFunction.cpp
@@ -82,6 +82,9 @@ using namespace std;
 #define STARS_DEBUG_FUNC_SCCP 0
 #define STARS_DEBUG_LOOP_INVARIANTS 1
 
+// For debugging purposes, only emit SPARK Ada for main().
+#define STARS_EMIT_ADA_FOR_MAIN_ONLY 0
+
 // Compute LVA/SSA or not? Turn it off for NICECAP demo on 31-JAN-2008
 #define SMP_COMPUTE_LVA_SSA 1
 
@@ -8568,7 +8571,7 @@ void SMPFunction::MarkSpecialNumericErrorCases(void) {
 	if ((this->LoopCount > 0) && this->HasReducibleControlFlow() && (!this->HasUnresolvedIndirectJumps())) {
 #endif
 		list<SMPInstr *>::iterator InstIter;
-		for (InstIter = this->Instrs.begin(); InstIter != this->Instrs.end(); ++InstIter) {
+		for (InstIter = this->Instrs.begin(); InstIter != this->Instrs.end(); ++InstIter) {  // !!!!****!!!! loop through blocks !!
 			CurrInst = (*InstIter);
 			STARS_ea_t InstAddr = CurrInst->GetAddr();
 			SMPitype CurrDataFlowType = CurrInst->GetDataFlowType();
@@ -9586,9 +9589,6 @@ void SMPFunction::PreProcessForSPARKAdaTranslation(void) {
 	return;
 } // end of SMPFunction::PreProcessForSPARKAdaTranslation()
 
-// For debugging purposes, only emit SPARK Ada for main().
-#define STARS_EMIT_ADA_FOR_MAIN_ONLY 1
-
 // Emit SPARK Ada translation of function
 void SMPFunction::EmitFuncSPARKAda(void) {
 	if (this->IsLinkerStub()) {
@@ -9601,6 +9601,9 @@ void SMPFunction::EmitFuncSPARKAda(void) {
 		return;
 	}
 #endif
+	if (IsStartupFuncName(AdaFuncName)) {
+		return;
+	}
 
 	// Convert dashes to underscores in the func name to suit Ada standards.
 	replace(AdaFuncName.begin(), AdaFuncName.end(), '-', '_');
@@ -9725,8 +9728,8 @@ void SMPFunction::EmitFuncSPARKAda(void) {
 	this->EmitSPARKAdaForBlock(0, FollowBlockNum, BodyFile);
 #endif
 
-	SMP_fprintf(BodyFile, "\nend %s;\n", AdaFuncName.c_str());
-	STARS_SPARK_IndentCount = 0;
+	SMP_fprintf(BodyFile, "\nend %s;\n\n", AdaFuncName.c_str());
+	STARS_SPARK_IndentCount = 1;
 
 	return;
 } // end of SMPFunction::EmitFuncSPARKAda()
@@ -9774,7 +9777,7 @@ void SMPFunction::EmitSPARKAdaForBlock(int CurrBlockNum, int FollowBlockNum, FIL
 				ControlFlowType LastCFType = this->GetControlFlowType(LastAddr);
 				if (FlowType == INDIR_JUMP) {
 					// Translate switch-case statement.
-					int NextFollowBlockNum = this->FindFollowBlockNum(CurrBlock);
+					int NextFollowBlockNum = this->FindFollowBlockNum(CurrBlock, true);
 					this->EmitSPARKAdaForSwitch(CurrBlockNum, NextFollowBlockNum, SPARKBodyFile);
 					ResumeBlockNum = NextFollowBlockNum;
 				}
@@ -9808,7 +9811,7 @@ void SMPFunction::EmitSPARKAdaForBlock(int CurrBlockNum, int FollowBlockNum, FIL
 					else {
 						assert((LastCFType == BRANCH_IF_THEN) || (LastCFType == BRANCH_IF_THEN_ELSE));
 						// Translate if-else structure previously identified
-						int NextFollowBlockNum = this->FindFollowBlockNum(CurrBlock);
+						int NextFollowBlockNum = this->FindFollowBlockNum(CurrBlock, true);
 						LastInst->EmitSPARKAda(SPARKBodyFile); // emit if (inverted condition) then
 						this->EmitSPARKAdaForConditional(CurrBlockNum, NextFollowBlockNum, SPARKBodyFile);
 						ResumeBlockNum = NextFollowBlockNum;
@@ -9848,7 +9851,7 @@ void SMPFunction::EmitSPARKAdaForBlock(int CurrBlockNum, int FollowBlockNum, FIL
 			else {
 				// Last inst was translated by SMPBasicBlock::EmitSPARKAdaForFallThroughInsts().
 				//  CurrBlock can only have one successor, a fall-through block.
-				// NOTE: If CurrBlock ends with a call to a NORET function, we can have no successors.
+				// NOTE: If CurrBlock ends with a HALT or a call to a NORET function, we can have no successors.
 				size_t NumSuccessors = CurrBlock->GetNumSuccessors();
 				if (1 == NumSuccessors) {
 					SMPBasicBlock *FallThroughSucc = (*(CurrBlock->GetFirstSucc()));
@@ -9856,7 +9859,7 @@ void SMPFunction::EmitSPARKAdaForBlock(int CurrBlockNum, int FollowBlockNum, FIL
 					ResumeBlockNum = FallThroughSucc->GetNumber();
 				}
 				else {
-					assert((FlowType == CALL) && (0 == NumSuccessors));
+					assert(((FlowType == CALL) || (FlowType == HALT)) && (0 == NumSuccessors));
 				}
 			}
 		} // end if header block ... elsif tail block ... else ...
@@ -9907,13 +9910,13 @@ void SMPFunction::EmitSPARKAdaForLoop(int HeaderBlockNum, int FollowBlockNum, FI
 			CurrBlock->EmitSPARKAdaForFallThroughInsts(SPARKBodyFile); // all except last inst if it is control flow terminator for block
 			vector<SMPInstr *>::reverse_iterator LastInstIter = CurrBlock->GetRevInstBegin();
 			SMPInstr *LastInst = (*LastInstIter);
+			STARS_ea_t LastAddr = LastInst->GetAddr();
+			SMPitype FlowType = LastInst->GetDataFlowType();
 			if (LastInst->IsBasicBlockTerminator()) {
-				STARS_ea_t LastAddr = LastInst->GetAddr();
-				SMPitype FlowType = LastInst->GetDataFlowType();
 				ControlFlowType LastCFType = this->GetControlFlowType(LastAddr);
 				if (FlowType == INDIR_JUMP) {
 					// Translate switch-case statement.
-					int NextFollowBlockNum = this->FindFollowBlockNum(CurrBlock);
+					int NextFollowBlockNum = this->FindFollowBlockNum(CurrBlock, true);
 					this->EmitSPARKAdaForSwitch(CurrBlockNum, NextFollowBlockNum, SPARKBodyFile);
 					ResumeBlockNum = NextFollowBlockNum;
 				}
@@ -9930,7 +9933,7 @@ void SMPFunction::EmitSPARKAdaForLoop(int HeaderBlockNum, int FollowBlockNum, FI
 					}
 					else if ((LastCFType == BRANCH_IF_THEN) || (LastCFType == BRANCH_IF_THEN_ELSE)) {
 						// Translate if-else structure previously identified
-						int NextFollowBlockNum = this->FindFollowBlockNum(CurrBlock);
+						int NextFollowBlockNum = this->FindFollowBlockNum(CurrBlock, true);
 						LastInst->EmitSPARKAda(SPARKBodyFile); // emit if (inverted condition) then
 						this->EmitSPARKAdaForConditional(CurrBlockNum, NextFollowBlockNum, SPARKBodyFile);
 						ResumeBlockNum = NextFollowBlockNum;
@@ -9998,16 +10001,23 @@ void SMPFunction::EmitSPARKAdaForLoop(int HeaderBlockNum, int FollowBlockNum, FI
 			else {
 				// Last inst was translated by SMPBasicBlock::EmitSPARKAdaForFallThroughInsts().
 				//  CurrBlock can only have one successor, a fall-through block.
-				assert(1 == CurrBlock->GetNumSuccessors());
-				SMPBasicBlock *FallThroughSucc = (*(CurrBlock->GetFirstSucc()));
-				ResumeBlockNum = FallThroughSucc->GetNumber();
+				// NOTE: If CurrBlock ends with a HALT or a call to a NORET function, we can have no successors.
+				size_t NumSuccessors = CurrBlock->GetNumSuccessors();
+				if (1 == NumSuccessors) {
+					SMPBasicBlock *FallThroughSucc = (*(CurrBlock->GetFirstSucc()));
+					assert(NULL != FallThroughSucc);
+					ResumeBlockNum = FallThroughSucc->GetNumber();
+				}
+				else {
+					assert(((FlowType == CALL) || (FlowType == HALT)) && (0 == NumSuccessors));
+				}
 			} // end if LastInst is basic block terminator ... else ...
-
-			// We have translated the header block, and recursed into the next control flow structure if the end of the
-			//  header block indicated a new structure was beginning. Time to pick up with ResumeBlock unless it is our
-			//  follow block.
-			CurrBlockNum = ResumeBlockNum;
 		} // end if loop tail block ... else ...
+
+		// We have translated the header block, and recursed into the next control flow structure if the end of the
+		//  header block indicated a new structure was beginning. Time to pick up with ResumeBlock unless it is our
+		//  follow block.
+		CurrBlockNum = ResumeBlockNum;
 	} // end while CurrBlockNum is in the loop
 
 	return;
@@ -10152,18 +10162,20 @@ void SMPFunction::EmitSPARKAdaForConditional(int HeaderBlockNum, int FollowBlock
 } // end of SMPFunction::EmitSPARKAdaForConditional()
 
 // Based on control flow structure of CurrBlock, find Ada follow block num; -1 if no structure besides fall-through
-int SMPFunction::FindFollowBlockNum(SMPBasicBlock *CurrBlock) {
+int SMPFunction::FindFollowBlockNum(SMPBasicBlock *CurrBlock, bool StartAtLastInst) {
 	int FollowBlockNum = SMP_BLOCKNUM_UNINIT;
-	if (CurrBlock->IsLoopHeaderBlock()) {
-		int LoopNum = this->GetLoopNumFromHeaderBlockNum(CurrBlock->GetNumber());
-		assert(0 <= LoopNum);
-		FollowBlockNum = this->LoopFollowNodes[LoopNum];
-		assert(SMP_BLOCKNUM_UNINIT != FollowBlockNum);
-	}
-	else if (CurrBlock->IsSwitchDefaultCase()) {
-		STARS_ea_t DefaultCaseAddr = CurrBlock->GetFirstAddr();
-		size_t SwitchIndex = this->FindSwitchIndexForDefaultCaseAddr(DefaultCaseAddr);
-		FollowBlockNum = this->SwitchInfoArray.at(SwitchIndex).FollowNodeNum;
+	if (!StartAtLastInst) { // StartAtLastInst => Key is to examine branch or jump, not starting a new loop or switch default case
+		if (CurrBlock->IsLoopHeaderBlock()) {
+			int LoopNum = this->GetLoopNumFromHeaderBlockNum(CurrBlock->GetNumber());
+			assert(0 <= LoopNum);
+			FollowBlockNum = this->LoopFollowNodes[LoopNum];
+			assert(SMP_BLOCKNUM_UNINIT != FollowBlockNum);
+		}
+		else if (CurrBlock->IsSwitchDefaultCase()) {
+			STARS_ea_t DefaultCaseAddr = CurrBlock->GetFirstAddr();
+			size_t SwitchIndex = this->FindSwitchIndexForDefaultCaseAddr(DefaultCaseAddr);
+			FollowBlockNum = this->SwitchInfoArray.at(SwitchIndex).FollowNodeNum;
+		}
 	}
 	else {
 		vector<SMPInstr *>::iterator LastInstIter = --(CurrBlock->GetLastInst());
@@ -10184,7 +10196,7 @@ int SMPFunction::FindFollowBlockNum(SMPBasicBlock *CurrBlock) {
 		else if (FlowType == COND_BRANCH) {
 			ControlFlowType LastCFType = GetControlFlowType(LastAddr);
 			if (LastCFType == LOOP_EXIT) {
-				// Middle exit from loop. Follow block is fall-through.
+				// Middle exit from loop. Follow block is fall-through.  !!!!****!!!! What structure has loop exit, then a follow block?
 				list<SMPBasicBlock *>::iterator SuccIter = CurrBlock->GetFallThroughSucc();
 				assert(SuccIter != CurrBlock->GetLastSucc()); // COND_BRANCH must have fall through
 				FollowBlockNum = (*SuccIter)->GetNumber();
diff --git a/src/base/SMPInstr.cpp b/src/base/SMPInstr.cpp
index 0bd82941..ad7ced53 100644
--- a/src/base/SMPInstr.cpp
+++ b/src/base/SMPInstr.cpp
@@ -1685,7 +1685,7 @@ char *SMPInstr::GetDisasm(void) const {
 // Is the instruction the type that terminates a basic block?
 bool SMPInstr::IsBasicBlockTerminator() const {
 	return ((type == JUMP) || (type == COND_BRANCH)
-			|| (type == INDIR_JUMP) || (type == RETURN));
+			|| (type == INDIR_JUMP) || (type == RETURN) || (type == HALT));
 }
 
 // Get non-flags DEF, usually for arithmetic opcode.
@@ -2355,6 +2355,10 @@ void SMPInstr::MDEmitSPARKAdaCompareOrTest(FILE *OutFile) {
 		this->PrintSPARKAdaOperand(RightOp, OutFile, false, UseFP);
 		SMP_fprintf(OutFile, ");\n");
 	}
+	else { // TEST opcode always zeroes the CarryFlag
+		PrintSPARKIndentTabs(OutFile);
+		SMP_fprintf(OutFile, " X86.CarryFlag := 0;\n");
+	}
 
 	// OverflowFlag
 	if (EmitOverflowFlag) {
@@ -2372,6 +2376,10 @@ void SMPInstr::MDEmitSPARKAdaCompareOrTest(FILE *OutFile) {
 		this->PrintSPARKAdaOperand(RightOp, OutFile, false, UseFP);
 		SMP_fprintf(OutFile, " <= X86.MaxSignedInt%d)));\n", LeftBitWidth);
 	}
+	else { // TEST opcode always zeroes the OverflowFlag
+		PrintSPARKIndentTabs(OutFile);
+		SMP_fprintf(OutFile, " X86.OverflowFlag := 0;\n");
+	}
 
 	return;
 } // end of SMPInstr::MDEmitSPARKAdaCompareOrTest()
diff --git a/src/base/SMPProgram.cpp b/src/base/SMPProgram.cpp
index 9205ba54..eda54ccb 100644
--- a/src/base/SMPProgram.cpp
+++ b/src/base/SMPProgram.cpp
@@ -843,7 +843,7 @@ bool SMPProgram::EmitProgramSPARKAda(void) {
 		SMP_fprintf(BodyFile, "end %s;\n\n", LibFuncName.c_str());
 	}
 
-	// Loop through all functions and emit annotations for each.
+	// Loop through all functions and emit SPARK Ada for each.
 	for (FuncIter = this->FuncMap.begin(); FuncIter != this->FuncMap.end(); ++FuncIter) {
 		SMPFunction *TempFunc = FuncIter->second;
 		if (TempFunc == NULL) continue;
-- 
GitLab