Start building up code generation

- Introduce (perhaps poorly named) SpirvRoutine type for
routine-emit-time state (reactor objects).
- Add SpirvShader::emitEarly (intended for definitions that are needed
in shader preamble) and SpirvShader::emit (intended for general actual
code generation) passes.
- Wire up new passes to VertexProgram/VertexRoutine

Change-Id: Iac42eae7dc04adfd4163fd74ba407b613551d14e
Bug: b/120799499
Reviewed-on: https://swiftshader-review.googlesource.com/c/24375
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Tested-by: Chris Forbes <chrisforbes@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index ae76ff8..36227b9 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -517,4 +517,47 @@
 		assert(getType(insn.word(1)).definition.opcode() == spv::OpTypeInt);
 		return insn.word(3);
 	}
+
+	// emit-time
+
+	void SpirvShader::emitEarly(SpirvRoutine *routine) const
+	{
+		for (auto insn : *this)
+		{
+			switch (insn.opcode())
+			{
+			case spv::OpVariable:
+			{
+				auto &object = getObject(insn.word(2));
+				// Want to exclude: location-oriented interface variables; special things that consume zero slots.
+				// TODO: what to do about zero-slot objects?
+				if (object.kind != Object::Kind::InterfaceVariable && object.sizeInComponents > 0)
+				{
+					// any variable not in a location-oriented interface
+					routine->lvalues.emplace(insn.word(2), std::unique_ptr<Array<Float4>>(
+							new Array<Float4>(object.sizeInComponents)));
+				}
+				break;
+			}
+			default:
+				printf("emitEarly: ignoring opcode %d\n", insn.opcode());
+				break;
+			}
+		}
+	}
+
+	void SpirvShader::emit(SpirvRoutine *routine) const
+	{
+		(void) routine;
+
+		for (auto insn : *this)
+		{
+			switch (insn.opcode())
+			{
+			default:
+				printf("emit: ignoring opcode %d\n", insn.opcode());
+				break;
+			}
+		}
+	}
 }
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp
index 52e9143..e6bc13c 100644
--- a/src/Pipeline/SpirvShader.hpp
+++ b/src/Pipeline/SpirvShader.hpp
@@ -17,16 +17,24 @@
 
 #include "System/Types.hpp"
 #include "Vulkan/VkDebug.hpp"
+#include "ShaderCore.hpp"
 
 #include <string>
 #include <vector>
 #include <unordered_map>
 #include <cstdint>
 #include <type_traits>
+#include <memory>
 #include <spirv/unified1/spirv.hpp>
 
 namespace sw
 {
+	class SpirvRoutine
+	{
+	public:
+		std::unordered_map<uint32_t, std::unique_ptr<Array<Float4>>> lvalues;
+	};
+
 	class SpirvShader
 	{
 	public:
@@ -212,12 +220,9 @@
 		std::vector<InterfaceComponent> inputs;
 		std::vector<InterfaceComponent> outputs;
 
-	private:
-		const int serialID;
-		static volatile int serialCounter;
-		Modes modes;
-		std::unordered_map<uint32_t, Object> types;
-		std::unordered_map<uint32_t, Object> defs;
+		void emitEarly(SpirvRoutine *routine) const;
+
+		void emit(SpirvRoutine *routine) const;
 
 		using BuiltInHash = std::hash<std::underlying_type<spv::BuiltIn>::type>;
 		std::unordered_map<spv::BuiltIn, BuiltinMapping, BuiltInHash> inputBuiltins;
@@ -230,12 +235,20 @@
 			return it->second;
 		}
 
-		Object const &getObject(uint32_t id) const {
+		Object const &getObject(uint32_t id) const
+		{
 			auto it = defs.find(id);
 			assert(it != defs.end());
 			return it->second;
 		}
 
+	private:
+		const int serialID;
+		static volatile int serialCounter;
+		Modes modes;
+		std::unordered_map<uint32_t, Object> types;
+		std::unordered_map<uint32_t, Object> defs;
+
 		void ProcessExecutionMode(InsnIterator it);
 
 		uint32_t ComputeTypeSize(InsnIterator insn);
diff --git a/src/Pipeline/VertexProgram.cpp b/src/Pipeline/VertexProgram.cpp
index fc75f13..1e0e162 100644
--- a/src/Pipeline/VertexProgram.cpp
+++ b/src/Pipeline/VertexProgram.cpp
@@ -64,7 +64,7 @@
 		//	}
 		//}
 
-		// Actually emit code here
+		spirvShader->emit(&routine);
 
 		if(currentLabel != -1)
 		{
diff --git a/src/Pipeline/VertexRoutine.cpp b/src/Pipeline/VertexRoutine.cpp
index 7d76dbe..636351f 100644
--- a/src/Pipeline/VertexRoutine.cpp
+++ b/src/Pipeline/VertexRoutine.cpp
@@ -19,6 +19,7 @@
 #include "Device/Renderer.hpp"
 #include "System/Half.hpp"
 #include "Vulkan/VkDebug.hpp"
+#include "SpirvShader.hpp"
 
 namespace sw
 {
@@ -28,6 +29,7 @@
 		  state(state),
 		  spirvShader(spirvShader)
 	{
+	  	spirvShader->emitEarly(&routine);
 	}
 
 	VertexRoutine::~VertexRoutine()
diff --git a/src/Pipeline/VertexRoutine.hpp b/src/Pipeline/VertexRoutine.hpp
index cb2b0fd..7b73b76 100644
--- a/src/Pipeline/VertexRoutine.hpp
+++ b/src/Pipeline/VertexRoutine.hpp
@@ -50,6 +50,7 @@
 
 		RegisterArray<MAX_VERTEX_INPUTS> v;    // Input registers
 		RegisterArray<MAX_VERTEX_OUTPUTS> o;   // Output registers
+		SpirvRoutine routine;
 
 		const VertexProcessor::State &state;
 		SpirvShader const * const spirvShader;