Fix crash caused by missing shader function definition and report the error.

BUG=17956386

Change-Id: I89f243b557b70401052b1f7db237fbc410386f64
Reviewed-on: https://swiftshader-review.googlesource.com/1190
Reviewed-by: Alexis Hétu <sugoi@google.com>
Tested-by: <nicolascapens@google.com>
Reviewed-by: <nicolascapens@google.com>
diff --git a/src/GLES2/compiler/Compiler.cpp b/src/GLES2/compiler/Compiler.cpp
index 7a50274..d1b36c0 100644
--- a/src/GLES2/compiler/Compiler.cpp
+++ b/src/GLES2/compiler/Compiler.cpp
@@ -121,7 +121,7 @@
             intermediate.outputTree(root);
 
         if (success && (compileOptions & SH_OBJECT_CODE))
-            translate(root);
+            success = translate(root);
     }
 
     // Cleanup memory.
diff --git a/src/GLES2/compiler/OutputASM.cpp b/src/GLES2/compiler/OutputASM.cpp
index 4f5b62e..9804781 100644
--- a/src/GLES2/compiler/OutputASM.cpp
+++ b/src/GLES2/compiler/OutputASM.cpp
@@ -670,9 +670,10 @@
 						Instruction *label = emit(sw::Shader::OPCODE_LABEL);

 						label->dst.type = sw::Shader::PARAMETER_LABEL;

 

-						const Function &function = findFunction(name);

-						label->dst.index = function.label;

-						currentFunction = function.label;

+						const Function *function = findFunction(name);

+						ASSERT(function);   // Should have been added during global pass

+						label->dst.index = function->label;

+						currentFunction = function->label;

 					}

 				}

 				else if(emitScope == GLOBAL)

@@ -706,8 +707,15 @@
 				if(node->isUserDefined())

 				{

 					const TString &name = node->getName();

-					const Function &function = findFunction(name);

-					TIntermSequence &arguments = *function.arg;

+					const Function *function = findFunction(name);

+

+					if(!function)

+					{

+						mContext.error(node->getLine(), "function definition not found", name.c_str());

+						return false;

+					}

+

+					TIntermSequence &arguments = *function->arg;

 

 					for(int i = 0; i < argumentCount; i++)

 					{

@@ -723,11 +731,11 @@
 

 					Instruction *call = emit(sw::Shader::OPCODE_CALL);

 					call->dst.type = sw::Shader::PARAMETER_LABEL;

-					call->dst.index = function.label;

+					call->dst.index = function->label;

 

-					if(function.ret && function.ret->getType().getBasicType() != EbtVoid)

+					if(function->ret && function->ret->getType().getBasicType() != EbtVoid)

 					{

-						copy(result, function.ret);

+						copy(result, function->ret);

 					}

 

 					for(int i = 0; i < argumentCount; i++)

@@ -1907,18 +1915,17 @@
 		return -1;

 	}

 

-	const Function &OutputASM::findFunction(const TString &name)

+	const Function *OutputASM::findFunction(const TString &name)

 	{

 		for(unsigned int f = 0; f < functionArray.size(); f++)

 		{

 			if(functionArray[f].name == name)

 			{

-				return functionArray[f];

+				return &functionArray[f];

 			}

 		}

 

-		UNREACHABLE();

-		return functionArray[0];

+		return 0;

 	}

 	

 	int OutputASM::temporaryRegister(TIntermTyped *temporary)

diff --git a/src/GLES2/compiler/OutputASM.h b/src/GLES2/compiler/OutputASM.h
index f47f4ba..082816f 100644
--- a/src/GLES2/compiler/OutputASM.h
+++ b/src/GLES2/compiler/OutputASM.h
@@ -121,7 +121,7 @@
 		int readSwizzle(TIntermTyped *argument, int size);

 		bool trivial(TIntermTyped *expression, int budget);   // Fast to compute and no side effects

 		int cost(TIntermNode *expression, int budget);

-		const Function &findFunction(const TString &name);

+		const Function *findFunction(const TString &name);

 

 		int temporaryRegister(TIntermTyped *temporary);

 		int varyingRegister(TIntermTyped *varying);

diff --git a/src/GLES2/compiler/ShHandle.h b/src/GLES2/compiler/ShHandle.h
index 8294abf..c772582 100644
--- a/src/GLES2/compiler/ShHandle.h
+++ b/src/GLES2/compiler/ShHandle.h
@@ -73,7 +73,7 @@
     // Collect info for all attribs and uniforms.
     void collectAttribsUniforms(TIntermNode *root);
     // Translate to object code.
-    virtual void translate(TIntermNode *root) = 0;
+    virtual bool translate(TIntermNode *root) = 0;
     // Get built-in extensions with default behavior.
     const TExtensionBehavior& getExtensionBehavior() const;
 
diff --git a/src/GLES2/compiler/TranslatorASM.cpp b/src/GLES2/compiler/TranslatorASM.cpp
index bffddf4..8750e0d 100644
--- a/src/GLES2/compiler/TranslatorASM.cpp
+++ b/src/GLES2/compiler/TranslatorASM.cpp
@@ -17,12 +17,14 @@
 {

 }

 

-void TranslatorASM::translate(TIntermNode* root)

+bool TranslatorASM::translate(TIntermNode* root)

 {

     TParseContext& parseContext = *GetGlobalParseContext();

     sh::OutputASM outputASM(parseContext, shaderObject);

 

 	outputASM.output();

+

+	return parseContext.numErrors() == 0;

 }

 

 //

diff --git a/src/GLES2/compiler/TranslatorASM.h b/src/GLES2/compiler/TranslatorASM.h
index f6502dd..26ca89c 100644
--- a/src/GLES2/compiler/TranslatorASM.h
+++ b/src/GLES2/compiler/TranslatorASM.h
@@ -28,7 +28,7 @@
     TranslatorASM(gl::Shader *shaderObject, ShShaderType type, ShShaderSpec spec);

 

 protected:

-    virtual void translate(TIntermNode* root);

+    virtual bool translate(TIntermNode* root);

 

 private:

 	gl::Shader *const shaderObject;