From 22bfeab41c142a9875fbee5ae180c280b0a95173 Mon Sep 17 00:00:00 2001
From: whh8b <whh8b@git.zephyr-software.com>
Date: Mon, 27 Jun 2016 17:19:34 +0000
Subject: [PATCH] Several changes:

1. Update semantics of how plugins determine
   the size and space of the dollop that they
	 will plop.
2. Add sorting for plugin invocation based on
   lexigraphical sorting.
---
 include/plugin_man.h      |   4 +-
 include/zipr_dollop_man.h |   2 +-
 include/zipr_impl.h       |  11 ++--
 include/zipr_utils.h      |   2 +-
 src/dollop.cpp            |   2 +-
 src/plugin_man.cpp        |  28 ++++++--
 src/utils.cpp             |   2 +-
 src/zipr.cpp              | 135 +++++++++++++++++++++++++-------------
 src/zipr_dollop_man.cpp   |   6 +-
 9 files changed, 129 insertions(+), 63 deletions(-)

diff --git a/include/plugin_man.h b/include/plugin_man.h
index 58f464c4b..f32de9ab7 100644
--- a/include/plugin_man.h
+++ b/include/plugin_man.h
@@ -2,7 +2,7 @@
 #define plugin_man_h
 
 typedef Zipr_SDK::ZiprPluginInterface_t* DLFunctionHandle_t;
-typedef std::set<DLFunctionHandle_t> DLFunctionHandleSet_t;
+typedef std::vector<DLFunctionHandle_t> DLFunctionHandleSet_t;
 
 typedef Zipr_SDK::ZiprPluginInterface_t* (*GetPluginInterface_t)(
 	Zipr_SDK::Zipr_t*
@@ -43,7 +43,7 @@ class ZiprPluginManager_t : public ZiprPluginInterface_t
 		virtual RangeAddress_t PlaceScoopsBegin(const RangeAddress_t max_addr);
 		virtual RangeAddress_t PlaceScoopsEnd(const RangeAddress_t max_addr);
 
-		virtual bool DoesPluginPlop(libIRDB::Instruction_t*,DLFunctionHandle_t&);
+		virtual bool DoPluginsPlop(libIRDB::Instruction_t*,std::list<DLFunctionHandle_t>&);
 
 		virtual bool DoesPluginAddress(const Dollop_t *, const RangeAddress_t &, Range_t &, bool &coalesce, DLFunctionHandle_t &);
 		virtual bool DoesPluginRetargetCallback(const RangeAddress_t &, const DollopEntry_t *, RangeAddress_t &, DLFunctionHandle_t &) ;
diff --git a/include/zipr_dollop_man.h b/include/zipr_dollop_man.h
index b24fbce40..f50d01cef 100644
--- a/include/zipr_dollop_man.h
+++ b/include/zipr_dollop_man.h
@@ -103,7 +103,7 @@ class ZiprDollopManager_t : public DollopManager_t {
 		/*
 		 * Helper functions.
 		 */
-		int DetermineWorstCaseInsnSize(libIRDB::Instruction_t *insn);
+		size_t DetermineWorstCaseDollopEntrySize(DollopEntry_t *entry);
 	private:
 		/*
 		 * Helper functions.
diff --git a/include/zipr_impl.h b/include/zipr_impl.h
index 6018b6609..40f7c58cf 100644
--- a/include/zipr_impl.h
+++ b/include/zipr_impl.h
@@ -69,14 +69,14 @@ class ZiprImpl_t : public Zipr_t
 			return m_error;
 		}
 		/*
-		 * PluginDetermineWorstCaseInsnSize
+		 * DetermineWorstCaseDollopEntrySize
 		 * 
-		 * Determine the worst case instruction size
+		 * Determine the worst case dollop entry size.
 		 * and account for the possibility that a plugin
 		 * may be plopping this instruction and want
 		 * to do some calculations.
 		 */
-		int PluginDetermineWorstCaseInsnSize(libIRDB::Instruction_t *insn, bool account_for_jump = true);
+		size_t DetermineWorstCaseDollopEntrySize(DollopEntry_t *entry, bool account_for_jump = true);
 
 		/*
 		 * DetermineWorstCaseInsnSize
@@ -86,7 +86,7 @@ class ZiprImpl_t : public Zipr_t
 		 * may be plopping this instruction and want
 		 * to do some calculations.
 		 */
-		int DetermineWorstCaseInsnSize(libIRDB::Instruction_t*, bool account_for_jump = true);
+		size_t DetermineWorstCaseInsnSize(libIRDB::Instruction_t*, bool account_for_jump = true);
 
 		Zipr_SDK::RangeAddress_t PlopDollopEntry(
 			DollopEntry_t *,
@@ -469,7 +469,8 @@ class ZiprImpl_t : public Zipr_t
 
 		ZiprPluginManager_t plugman;
 
-		std::map<libIRDB::Instruction_t*,DLFunctionHandle_t> plopping_plugins;
+		std::map<libIRDB::Instruction_t*,
+		         std::unique_ptr<std::list<DLFunctionHandle_t>>> plopping_plugins;
 		
 		// Options
 		ZiprOptions_t m_zipr_options;
diff --git a/include/zipr_utils.h b/include/zipr_utils.h
index d5c5769ee..0345e1901 100644
--- a/include/zipr_utils.h
+++ b/include/zipr_utils.h
@@ -8,7 +8,7 @@ namespace Utils {
 	extern size_t LONG_PIN_SIZE;
 	extern size_t SHORT_PIN_SIZE;
 	void PrintStat(std::ostream &out, std::string description, double value);
-	int DetermineWorstCaseInsnSize(libIRDB::Instruction_t*, bool account_for_jump = true);
+	size_t DetermineWorstCaseInsnSize(libIRDB::Instruction_t*, bool account_for_jump = true);
 
 	/** \brief Calculate entire size of a dollop 
 	 *         and it's fallthroughs.
diff --git a/src/dollop.cpp b/src/dollop.cpp
index 477010329..23160aed9 100644
--- a/src/dollop.cpp
+++ b/src/dollop.cpp
@@ -47,7 +47,7 @@ namespace Zipr_SDK {
 		{
 			Instruction_t *cur_insn = (*it)->Instruction();
 			if (m_dollop_mgr != NULL)
-				dollop_size += m_dollop_mgr->DetermineWorstCaseInsnSize(cur_insn);
+				dollop_size += m_dollop_mgr->DetermineWorstCaseDollopEntrySize(*it);
 			else
 			{
 				assert(false);
diff --git a/src/plugin_man.cpp b/src/plugin_man.cpp
index 8f928bae0..7d67996db 100644
--- a/src/plugin_man.cpp
+++ b/src/plugin_man.cpp
@@ -59,6 +59,20 @@ for(DLFunctionHandleSet_t::iterator it=m_handleList.begin(); it!=m_handleList.en
 	ZiprPluginInterface_t* zpi=(ZiprPluginInterface_t*)*it; \
 	var=zpi->func(var); \
 } 
+
+/*
+ * sort_plugins_by_name()
+ *
+ * Use this function as the comparator for sorting
+ * the plugins by the name that they return in their
+ * ToString() method. Sorting plugins by name is
+ * useful when trying to debug problems that depend
+ * on specific ordering.
+ */
+bool sort_plugins_by_name(DLFunctionHandle_t a, DLFunctionHandle_t b)
+{
+	return a->ToString() < b->ToString();
+}
  
 void ZiprPluginManager_t::PinningBegin()
 {
@@ -118,19 +132,20 @@ bool ZiprPluginManager_t::DoesPluginAddress(const Dollop_t *dollop, const RangeA
 	return false;
 }
 
-bool ZiprPluginManager_t::DoesPluginPlop(Instruction_t *insn, DLFunctionHandle_t &callback) 
+bool ZiprPluginManager_t::DoPluginsPlop(Instruction_t *insn, std::list<DLFunctionHandle_t> &callbacks) 
 {
+	bool a_plugin_does_plop = false;
 	DLFunctionHandleSet_t::iterator it=m_handleList.begin();
 	for(m_handleList.begin();it!=m_handleList.end();++it)
 	{
 		ZiprPluginInterface_t* zpi=(ZiprPluginInterface_t*)*it;
 		if (zpi->WillPluginPlop(insn))
 		{
-			callback = zpi;
-			return true;
+			callbacks.push_back(zpi);
+			a_plugin_does_plop = true;
 		}
 	}
-	return false;
+	return a_plugin_does_plop;
 }
 
 bool ZiprPluginManager_t::DoesPluginRetargetCallback(const RangeAddress_t &callback_addr, const DollopEntry_t *callback_entry, RangeAddress_t &target_address, DLFunctionHandle_t &patcher)
@@ -231,9 +246,12 @@ void ZiprPluginManager_t::open_plugins
 		}
 		p_opts->AddNamespace(interface->RegisterOptions(global_ns));
 
-		m_handleList.insert(interface);
+		m_handleList.push_back(interface);
 		
     	}
     	closedir(dp);
+
+			std::sort(m_handleList.begin(), m_handleList.end(), sort_plugins_by_name);
+
     	return;
 }
diff --git a/src/utils.cpp b/src/utils.cpp
index c4bb3fd29..cbe612aa6 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -53,7 +53,7 @@ size_t DetermineWorstCaseDollopSizeInclFallthrough(Dollop_t *dollop)
 	return fallthroughs_wcds;
 }
 
-int DetermineWorstCaseInsnSize(Instruction_t* insn, bool account_for_jump)
+size_t DetermineWorstCaseInsnSize(Instruction_t* insn, bool account_for_jump)
 {
 
 	int required_size=0;
diff --git a/src/zipr.cpp b/src/zipr.cpp
index 7ad5b60b9..7856220d0 100644
--- a/src/zipr.cpp
+++ b/src/zipr.cpp
@@ -1413,7 +1413,7 @@ void ZiprImpl_t::WriteDollops()
 
 			start = entry_to_write->Place();
 			end = _PlopDollopEntry(entry_to_write);
-			should_end = start + _DetermineWorstCaseInsnSize(entry_to_write->Instruction(), false);
+			should_end = start + DetermineWorstCaseDollopEntrySize(entry_to_write, false);
 			assert(end <= should_end);
 			/*
 			 * Build up a list of those dollop entries that we have
@@ -1537,7 +1537,7 @@ void ZiprImpl_t::PlaceDollops()
 		to_place->ReCalculateWorstCaseSize();
 
 		minimum_valid_req_size = std::min(
-			_DetermineWorstCaseInsnSize(to_place->front()->Instruction()),
+			DetermineWorstCaseDollopEntrySize(to_place->front()),
 			Utils::DetermineWorstCaseDollopSizeInclFallthrough(to_place));
 		/*
 		 * Ask the plugin manager if there are any plugins
@@ -1842,11 +1842,11 @@ void ZiprImpl_t::PlaceDollops()
 				bool last_de_fits = false;
 				bool disallowed_override = true;
 				de_and_fallthrough_fit = (placement.GetEnd()>= /* fits */
-				     (cur_addr+_DetermineWorstCaseInsnSize(dollop_entry->Instruction()))
+				     (cur_addr+DetermineWorstCaseDollopEntrySize(dollop_entry))
 				                         );
 				last_de_fits = (std::next(dit,1)==dit_end) /* last */ &&
 				               (placement.GetEnd()>=(cur_addr+ /* fits */
-							_DetermineWorstCaseInsnSize(dollop_entry->Instruction(),
+							DetermineWorstCaseDollopEntrySize(dollop_entry,
 							                            to_place->FallthroughDollop()!=NULL))
 							                            /* with or without fallthrough */
 							         );
@@ -1860,8 +1860,8 @@ void ZiprImpl_t::PlaceDollops()
 															 all_fallthroughs_fit && 
 				                       ((placement.GetEnd() - 
 				                        (cur_addr + 
-				                         _DetermineWorstCaseInsnSize(
-				                           dollop_entry->Instruction(),
+				                         DetermineWorstCaseDollopEntrySize(
+				                           dollop_entry,
 				                           false)
 				                         ) < Utils::TRAMPOLINE_SIZE
 				                        )
@@ -1903,7 +1903,7 @@ void ZiprImpl_t::PlaceDollops()
 					}
 #endif
 					dollop_entry->Place(cur_addr);
-					cur_addr+=_DetermineWorstCaseInsnSize(dollop_entry->Instruction(),
+					cur_addr+=DetermineWorstCaseDollopEntrySize(dollop_entry,
 					                                      false);
 					if (dollop_entry->TargetDollop())
 					{
@@ -2035,9 +2035,8 @@ void ZiprImpl_t::PlaceDollops()
 				/*
 				 * ... or maybe we just want to start the next dollop.
 				 */
-				fallthrough_wcis = _DetermineWorstCaseInsnSize(fallthrough->
-				                                               front()->
-				                                               Instruction());
+				fallthrough_wcis=DetermineWorstCaseDollopEntrySize(fallthrough->
+				                                               front());
 				remaining_size = placement.GetEnd() - cur_addr;
 
 				/*
@@ -2071,8 +2070,7 @@ void ZiprImpl_t::PlaceDollops()
 
 					patch_de->TargetDollop(fallthrough);
 					patch_de->Place(cur_addr);
-					cur_addr+=_DetermineWorstCaseInsnSize(patch_de->Instruction(),
-					                                      false);
+					cur_addr+=DetermineWorstCaseDollopEntrySize(patch_de, false);
 
 					to_place->push_back(patch_de);
 					to_place->FallthroughPatched(true);
@@ -2273,54 +2271,92 @@ void ZiprImpl_t::PatchJump(RangeAddress_t at_addr, RangeAddress_t to_addr)
 	}
 }
 
-int ZiprImpl_t::PluginDetermineWorstCaseInsnSize(Instruction_t *insn, bool account_for_jump)
+size_t ZiprImpl_t::DetermineWorstCaseDollopEntrySize(DollopEntry_t *entry, bool account_for_jump)
 {
-	return (int)_DetermineWorstCaseInsnSize(insn, account_for_jump);
+	std::map<Instruction_t*,unique_ptr<list<DLFunctionHandle_t>>>::const_iterator plop_it;
+	size_t padding = 0;
+	size_t wcis = _DetermineWorstCaseInsnSize(entry->Instruction(), account_for_jump);
+
+	plop_it = plopping_plugins.find(entry->Instruction());
+	if (plop_it != plopping_plugins.end())
+	{
+		for (auto handle : *(plop_it->second))
+		{
+			ZiprPluginInterface_t *zpi = dynamic_cast<ZiprPluginInterface_t*>(handle);
+			padding += zpi->InsnPaddingSize(entry->Instruction(),this);
+		}
+	}
+
+	if (m_verbose)
+	{
+		cout << "Adding padding of " << padding << "." << endl;
+		cout << "WCDES of " << std::hex << entry << ":" << std::dec << wcis+padding << endl;
+	}
+
+	return wcis+padding;
 }
 
 size_t ZiprImpl_t::_DetermineWorstCaseInsnSize(Instruction_t* insn, bool account_for_jump)
 {
-	std::map<Instruction_t*,DLFunctionHandle_t>::const_iterator plop_it;
+	std::map<Instruction_t*,unique_ptr<list<DLFunctionHandle_t>>>::const_iterator plop_it;
 	size_t worst_case_size = 0;
+	size_t default_worst_case_size = 0;
+
+	default_worst_case_size = DetermineWorstCaseInsnSize(insn, account_for_jump);
 
 	plop_it = plopping_plugins.find(insn);
 	if (plop_it != plopping_plugins.end())
 	{
-		DLFunctionHandle_t handle = plop_it->second;
-		ZiprPluginInterface_t *zpi = dynamic_cast<ZiprPluginInterface_t*>(handle);
-		worst_case_size = zpi->WorstCaseInsnSize(insn,account_for_jump,this);
+		for (auto handle : *(plop_it->second))
+		{
+			ZiprPluginInterface_t *zpi = dynamic_cast<ZiprPluginInterface_t*>(handle);
+			worst_case_size = std::max(zpi->WorstCaseInsnSize(insn,
+			                                                  account_for_jump,
+			                                                  this),
+			                           worst_case_size);
+		}
 	}
 	else
-		worst_case_size = DetermineWorstCaseInsnSize(insn, account_for_jump);
+	{
+		worst_case_size = default_worst_case_size;
+	}
 
 #if 1
 	if (m_verbose)
-		cout << "Worst case size" << ((account_for_jump) ? " (including jump)" : "")
+		cout << "Worst case size" 
+		     << ((account_for_jump) ? " (including jump)" : "")
 		     << ": " << worst_case_size << endl;
 #endif
 
 	return worst_case_size;
 }
 
-int ZiprImpl_t::DetermineWorstCaseInsnSize(Instruction_t* insn, bool account_for_jump)
+size_t ZiprImpl_t::DetermineWorstCaseInsnSize(Instruction_t *insn, bool account_for_jump)
 {
 	return Utils::DetermineWorstCaseInsnSize(insn, account_for_jump);
 }
 
 bool ZiprImpl_t::AskPluginsAboutPlopping(Instruction_t *insn)
 {
-	DLFunctionHandle_t plopping_plugin;
-	if (plugman.DoesPluginPlop(insn, plopping_plugin))
+	/*
+	 * Plopping plugins should hold a set.
+	 */
+	unique_ptr<list<DLFunctionHandle_t>> found_plopping_plugins = 
+	unique_ptr<list<DLFunctionHandle_t>>(new std::list<DLFunctionHandle_t>());
+
+	if (plugman.DoPluginsPlop(insn, *found_plopping_plugins))
 	{
-		ZiprPluginInterface_t *zipr_plopping_plugin =
-			dynamic_cast<ZiprPluginInterface_t*>(plopping_plugin);
 		if (m_verbose)
-		{
-			cout << zipr_plopping_plugin->ToString()
-			     << " will plop "<<dec<<insn->GetBaseID() << ":"
-			     << insn->getDisassembly() << endl;
-		}
-		plopping_plugins[insn] = plopping_plugin;
+			for (auto pp : *found_plopping_plugins)
+			{
+				ZiprPluginInterface_t *zipr_plopping_plugin =
+					dynamic_cast<ZiprPluginInterface_t*>(pp);
+				cout << zipr_plopping_plugin->ToString()
+				     << " will plop "<<dec<<insn->GetBaseID() << ":"
+				     << insn->getDisassembly() << endl;
+			}
+
+		plopping_plugins[insn] = std::move(found_plopping_plugins);
 		return true;
 	}
 	return false;
@@ -2437,28 +2473,39 @@ void ZiprImpl_t::PatchInstruction(RangeAddress_t from_addr, Instruction_t* to_in
 RangeAddress_t ZiprImpl_t::_PlopDollopEntry(DollopEntry_t *entry, RangeAddress_t override_address)
 {
 	Instruction_t *insn = entry->Instruction();
-	RangeAddress_t addr = entry->Place();
-	RangeAddress_t updated_addr;
-	std::map<Instruction_t*,DLFunctionHandle_t>::const_iterator plop_it;
+	size_t insn_wcis = _DetermineWorstCaseInsnSize(insn, false);
+	RangeAddress_t updated_addr = 0;
+	RangeAddress_t placed_address = entry->Place();
 
-	if (override_address != 0)
-		addr = override_address;
+	map<Instruction_t*,unique_ptr<std::list<DLFunctionHandle_t>>>::const_iterator plop_it;
 
+	if (override_address != 0)
+		placed_address = override_address;
+	
 	plop_it = plopping_plugins.find(insn);
 	if (plop_it != plopping_plugins.end())
 	{
-		DLFunctionHandle_t handle = plop_it->second;
-		RangeAddress_t placed_address = 0;
-		ZiprPluginInterface_t *zpi = dynamic_cast<ZiprPluginInterface_t*>(handle);
-		updated_addr = zpi->PlopDollopEntry(entry, placed_address, this);
-		if (m_verbose)
-			cout << "Placed address: " << std::hex << placed_address << endl;
+		for (auto pp : *(plop_it->second))
+		{
+			DLFunctionHandle_t handle = pp;
+			ZiprPluginInterface_t *zpi = dynamic_cast<ZiprPluginInterface_t*>(handle);
+			updated_addr = std::max(zpi->PlopDollopEntry(entry,
+			                                             placed_address,
+																									 insn_wcis,
+																									 this),
+			                        updated_addr);
+			if (m_verbose)
+				cout << zpi->ToString() << " placed entry " 
+				     << std::hex << entry 
+						 << " at address: " << std::hex << placed_address 
+						 << endl;
+		}
 		final_insn_locations[insn] = placed_address;
 	}
 	else
 	{
-		final_insn_locations[insn] = addr;
-		updated_addr = PlopDollopEntry(entry, addr);
+		final_insn_locations[insn] = placed_address;
+		updated_addr = PlopDollopEntry(entry, placed_address);
 	}
 	return updated_addr;
 }
diff --git a/src/zipr_dollop_man.cpp b/src/zipr_dollop_man.cpp
index a1cb1ee9b..89e7b5b6c 100644
--- a/src/zipr_dollop_man.cpp
+++ b/src/zipr_dollop_man.cpp
@@ -134,11 +134,11 @@ namespace zipr {
 		}
 	}
 
-	int ZiprDollopManager_t::DetermineWorstCaseInsnSize(libIRDB::Instruction_t *insn) {
+	size_t ZiprDollopManager_t::DetermineWorstCaseDollopEntrySize(DollopEntry_t *entry) {
 		if (m_zipr != NULL)
-			return m_zipr->PluginDetermineWorstCaseInsnSize(insn, false);
+			return m_zipr->DetermineWorstCaseDollopEntrySize(entry, false);
 		else
-			return Utils::DetermineWorstCaseInsnSize(insn, false);
+			return Utils::DetermineWorstCaseInsnSize(entry->Instruction(), false);
 	}
 
 	void ZiprDollopManager_t::PrintDollopPatches(const ostream &out) {
-- 
GitLab