From 3f3a8b4d040226f3097535f9d689e87e0b534d1b Mon Sep 17 00:00:00 2001
From: Jason Hiser <jdhiser@gmail.com>
Date: Tue, 23 Jul 2019 14:07:41 -0400
Subject: [PATCH] First using of loops in zafl

---
 irdb-libs/libIRDB-deep/src/SConscript         |  1 +
 irdb-libs/libIRDB-deep/src/deep.cpp           | 40 +++++++--
 irdb-libs/libIRDB-deep/src/deep.hpp           |  4 +-
 irdb-libs/libIRDB-deep/src/loops.cpp          | 16 ++++
 irdb-libs/libIRDB-deep/src/loops.hpp          | 85 +++++++++++++++++++
 .../include/MEDS_LoopAnnotation.hpp           | 13 ++-
 .../src/MEDS_LoopAnnotation.cpp               |  2 +-
 irdb-sdk                                      |  2 +-
 8 files changed, 148 insertions(+), 15 deletions(-)
 create mode 100644 irdb-libs/libIRDB-deep/src/loops.cpp
 create mode 100644 irdb-libs/libIRDB-deep/src/loops.hpp

diff --git a/irdb-libs/libIRDB-deep/src/SConscript b/irdb-libs/libIRDB-deep/src/SConscript
index 15daf24c7..4fee56b3a 100644
--- a/irdb-libs/libIRDB-deep/src/SConscript
+++ b/irdb-libs/libIRDB-deep/src/SConscript
@@ -7,6 +7,7 @@ myenv=env
 libname="irdb-deep"
 files=  '''
 	deep.cpp
+	loops.cpp
 	'''
 cpppath=''' 
 	$IRDB_SDK/include/
diff --git a/irdb-libs/libIRDB-deep/src/deep.cpp b/irdb-libs/libIRDB-deep/src/deep.cpp
index 5efbd3457..16f39f74d 100644
--- a/irdb-libs/libIRDB-deep/src/deep.cpp
+++ b/irdb-libs/libIRDB-deep/src/deep.cpp
@@ -3,9 +3,11 @@
 #include <set>
 #include <memory>
 #include <deep.hpp>
+#include <loops.hpp>
 #include <MEDS_DeadRegAnnotation.hpp>
 #include <MEDS_MemoryRangeAnnotation.hpp>
 #include <MEDS_SafeFuncAnnotation.hpp>
+#include <MEDS_LoopAnnotation.hpp>
 
 
 using namespace libIRDB;
@@ -40,7 +42,7 @@ unique_ptr<IRDB_SDK::FunctionSet_t> StarsDeepAnalysis_t::getLeafFunctions()
 	        /* for each annotation for this instruction */
        		for (auto it = the_range.first; it != the_range.second; ++it)
 		{
-		 	auto p_annotation=dynamic_cast<MEDS_SafeFuncAnnotation*>(it->second);
+		 	const auto p_annotation=dynamic_cast<MEDS_SafeFuncAnnotation*>(it->second);
 			if(p_annotation==nullptr)
                                 continue;
 
@@ -142,22 +144,44 @@ unique_ptr<IRDB_SDK::RangeSentinelSet_t> StarsDeepAnalysis_t::getRangeSentinels(
 	return ret;
 }
 
-unique_ptr<IRDB_SDK::LoopNest_t> StarsDeepAnalysis_t::getLoopNest(const IRDB_SDK::Function_t* f) const
+unique_ptr<IRDB_SDK::LoopNest_t> StarsDeepAnalysis_t::getLoops(IRDB_SDK::Function_t* f) const
 {
-	auto ret = unique_ptr<IRDB_SDK::LoopNest_t>();
+	auto cfg = IRDB_SDK::ControlFlowGraph_t::factory(f);
+	auto ret = getLoops(cfg.get());
+	auto real_nest = dynamic_cast<libIRDB::LoopNest_t*>(ret.get()); 
+	real_nest->saveCFG(move(cfg));
+
 	return ret;
 }
 
-unique_ptr<IRDB_SDK::LoopNest_t> StarsDeepAnalysis_t::getLoopNest(const IRDB_SDK::ControlFlowGraph_t* cfg) const 
+unique_ptr<IRDB_SDK::LoopNest_t> StarsDeepAnalysis_t::getLoops(IRDB_SDK::ControlFlowGraph_t* cfg) const 
 {
-	auto ret = unique_ptr<IRDB_SDK::LoopNest_t>();
-	return ret;
-}
+	auto func = cfg->getFunction();
+	auto id_to_block_map = map<IRDB_SDK::DatabaseID_t, IRDB_SDK::BasicBlock_t*>();
+	for(auto blk : cfg->getBlocks())
+		id_to_block_map[blk->getInstructions()[0]->getBaseID()]=blk;
+
+	auto meds_ap=stars_analysis_engine.getAnnotations();
+	const auto the_range = meds_ap.getAnnotations().equal_range(func->getBaseID());
 
+	auto ret = unique_ptr<IRDB_SDK::LoopNest_t>(new LoopNest_t(cfg));
+	for (auto it = the_range.first; it != the_range.second; ++it)
+	{
+		auto p_annotation=dynamic_cast<MEDS_LoopAnnotation*>(it->second);
+		if(p_annotation==nullptr)    continue;
+		if(!p_annotation->isValid()) continue;
+
+		const auto header_id = p_annotation -> getHeaderID();
+		const auto loop_id   = p_annotation -> getLoopID();
+		auto the_loop = unique_ptr<Loop_t>(new Loop_t(id_to_block_map[header_id]));
+		dynamic_cast<libIRDB::LoopNest_t*>(ret.get())->addLoop(loop_id,move(the_loop));
+	}
+
+	return move(ret);
+}
 
 unique_ptr<IRDB_SDK::DeepAnalysis_t> IRDB_SDK::DeepAnalysis_t::factory(FileIR_t* firp, const AnalysisEngine_t& ae, const vector<string>& options)
 {
-
 	auto ret=unique_ptr<IRDB_SDK::DeepAnalysis_t>();
 		
 	switch(ae)
diff --git a/irdb-libs/libIRDB-deep/src/deep.hpp b/irdb-libs/libIRDB-deep/src/deep.hpp
index bba46a9ee..176e8cd93 100644
--- a/irdb-libs/libIRDB-deep/src/deep.hpp
+++ b/irdb-libs/libIRDB-deep/src/deep.hpp
@@ -27,8 +27,8 @@ namespace libIRDB
 			virtual unique_ptr<IRDB_SDK::StaticGlobalStartMap_t> getStaticGlobalRanges() const override;
 			virtual unique_ptr<IRDB_SDK::RangeSentinelSet_t    > getRangeSentinels()     const override;
 
-			virtual unique_ptr<IRDB_SDK::LoopNest_t> getLoopNest(const IRDB_SDK::Function_t* f)           const override;
-                        virtual unique_ptr<IRDB_SDK::LoopNest_t> getLoopNest(const IRDB_SDK::ControlFlowGraph_t* cfg) const override;
+			virtual unique_ptr<IRDB_SDK::LoopNest_t> getLoops(IRDB_SDK::Function_t* f)           const override;
+                        virtual unique_ptr<IRDB_SDK::LoopNest_t> getLoops(IRDB_SDK::ControlFlowGraph_t* cfg) const override;
 
 
 		private:
diff --git a/irdb-libs/libIRDB-deep/src/loops.cpp b/irdb-libs/libIRDB-deep/src/loops.cpp
new file mode 100644
index 000000000..a60bd1ece
--- /dev/null
+++ b/irdb-libs/libIRDB-deep/src/loops.cpp
@@ -0,0 +1,16 @@
+
+#include <loops.hpp>
+
+using namespace libIRDB;
+using namespace std;
+
+IRDB_SDK::LoopSet_t LoopNest_t::getAllLoops()   const 
+{
+	auto ret=IRDB_SDK::LoopSet_t();
+	for(const auto &p : loops)
+	{
+		ret.insert(p.second.get());
+	}
+	return ret;
+}
+
diff --git a/irdb-libs/libIRDB-deep/src/loops.hpp b/irdb-libs/libIRDB-deep/src/loops.hpp
new file mode 100644
index 000000000..7953edf73
--- /dev/null
+++ b/irdb-libs/libIRDB-deep/src/loops.hpp
@@ -0,0 +1,85 @@
+/*
+   Copyright 2018-2019 Zephyr Software, LLC.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+#include <irdb-core>
+#include <irdb-cfg>
+#include <irdb-deep>
+#include <set>
+#include <map>
+
+namespace libIRDB
+{
+	using namespace std;
+	
+	class Loop_t : public IRDB_SDK::Loop_t 
+	{
+		public:
+			Loop_t() = delete;
+			Loop_t(IRDB_SDK::BasicBlock_t* header_blk) 
+				:
+				preheader(nullptr)
+				{ 
+					header = header_blk; 
+					assert(header != nullptr);
+				}
+			Loop_t(const Loop_t& copy) = delete;
+			virtual ~Loop_t() {} 
+
+			virtual IRDB_SDK::BasicBlock_t*   getPreheader()   const override { assert(0); }
+			virtual IRDB_SDK::BasicBlock_t*   getHeader()      const override { return header; }
+			virtual IRDB_SDK::BasicBlockSet_t getAllBlocks()   const override { assert(0); }
+			virtual IRDB_SDK::BasicBlockSet_t getOuterBlocks() const override { assert(0); }
+			virtual IRDB_SDK::LoopSet_t       getInnerLoops()  const override { assert(0); }
+
+			virtual bool isBlockInLoop       (const IRDB_SDK::BasicBlock_t* blk)  const override { assert(0); }
+			virtual bool isBlockInInnerLoop  (const IRDB_SDK::BasicBlock_t* blk)  const override { assert(0); }
+			virtual bool isBlockOuterLoopOnly(const IRDB_SDK::BasicBlock_t* blk)  const override { assert(0); }
+		private:
+			IRDB_SDK::BasicBlock_t*   preheader;
+			IRDB_SDK::BasicBlock_t*   header;
+			IRDB_SDK::BasicBlockSet_t blocks;
+			IRDB_SDK::LoopSet_t       inner_loops;
+	};
+
+	class LoopNest_t : public IRDB_SDK::LoopNest_t
+	{
+		public:
+			LoopNest_t(IRDB_SDK::ControlFlowGraph_t* p_cfg) 
+				: 
+					cfg(p_cfg) 
+				{}
+
+			LoopNest_t(const LoopNest_t& copy) = delete;
+			virtual ~LoopNest_t() {}
+
+			virtual IRDB_SDK::LoopSet_t getAllLoops()   const override ;
+			virtual IRDB_SDK::LoopSet_t getOuterLoops() const override { assert(0); }
+
+			virtual IRDB_SDK::Function_t*         getFunction()   const override { return cfg->getFunction(); }
+			virtual IRDB_SDK::ControlFlowGraph_t* getCFG()        const override { return cfg;  };
+
+
+			void addLoop(const uint64_t loop_id, unique_ptr<IRDB_SDK::Loop_t> loop_ptr) { loops[loop_id]=move(loop_ptr); } 
+			void saveCFG(unique_ptr<IRDB_SDK::ControlFlowGraph_t> cfg_ptr             ) { saved_cfg = move(cfg_ptr); }
+		private:
+			unique_ptr<IRDB_SDK::ControlFlowGraph_t> saved_cfg;
+			IRDB_SDK::ControlFlowGraph_t*            cfg;
+			map<uint64_t,unique_ptr<IRDB_SDK::Loop_t> >        loops;
+
+
+	};
+}
diff --git a/irdb-libs/libMEDSannotation/include/MEDS_LoopAnnotation.hpp b/irdb-libs/libMEDSannotation/include/MEDS_LoopAnnotation.hpp
index f72630926..5b58745b0 100644
--- a/irdb-libs/libMEDSannotation/include/MEDS_LoopAnnotation.hpp
+++ b/irdb-libs/libMEDSannotation/include/MEDS_LoopAnnotation.hpp
@@ -50,6 +50,13 @@ class MEDS_LoopAnnotation : public MEDS_AnnotationBase
 
 		virtual const string toString() const { return "loop annot "; }
 
+		uint64_t getHeaderID()    const { return header;    }
+		uint64_t getPreheaderID() const { return preheader; }
+		uint64_t getLoopID()      const { return loop_no;   }
+
+		const set<uint64_t>& getBlockIDs()     const { return all_blocks; }
+		const set<uint64_t>& getInnerLoopIDs() const { return sub_loops; }
+
 	private:
 		void init();
 		void parse();
@@ -57,9 +64,9 @@ class MEDS_LoopAnnotation : public MEDS_AnnotationBase
 		string m_rawInputLine;
 
 		uint64_t loop_no;
-		IRDB_SDK::VirtualOffset_t preheader;
-		IRDB_SDK::VirtualOffset_t header;
-		set<IRDB_SDK::VirtualOffset_t> all_blocks;
+		uint64_t preheader;
+		uint64_t header;
+		set<uint64_t> all_blocks;
 		set<uint64_t> sub_loops;
 };
 
diff --git a/irdb-libs/libMEDSannotation/src/MEDS_LoopAnnotation.cpp b/irdb-libs/libMEDSannotation/src/MEDS_LoopAnnotation.cpp
index c13f378ec..4fb13be65 100644
--- a/irdb-libs/libMEDSannotation/src/MEDS_LoopAnnotation.cpp
+++ b/irdb-libs/libMEDSannotation/src/MEDS_LoopAnnotation.cpp
@@ -125,7 +125,7 @@ void MEDS_LoopAnnotation::parse()
 	preheader  = readInt<decltype(preheader)>(m_rawInputLine, " PREHEADER ", true);
 
 	all_blocks = readAddrSet<IRDB_SDK::VirtualOffset_t>(m_rawInputLine, " BLOCKLIST ", true);
-	sub_loops  = readAddrSet<uint64_t                 >(m_rawInputLine, " BLOCKLIST ", false);
+	sub_loops  = readAddrSet<uint64_t                 >(m_rawInputLine, " INNERLOOPS ", false);
 
 	setValid();	// no additional info recorded for right now.
 }
diff --git a/irdb-sdk b/irdb-sdk
index 21c2c99f8..3267ac263 160000
--- a/irdb-sdk
+++ b/irdb-sdk
@@ -1 +1 @@
-Subproject commit 21c2c99f8d6f0a37fadd91b0cc3877df5a4ab735
+Subproject commit 3267ac26338c701dffa3267da6c6ca15475b4999
-- 
GitLab