// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
//
// 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.

#ifndef _COMPILER_INCLUDED_
#define _COMPILER_INCLUDED_

#include "ExtensionBehavior.h"
#include "InfoSink.h"
#include "SymbolTable.h"

enum ShCompileOptions
{
  SH_VALIDATE                = 0,
  SH_VALIDATE_LOOP_INDEXING  = 0x0001,
  SH_INTERMEDIATE_TREE       = 0x0002,
  SH_OBJECT_CODE             = 0x0004,
  SH_ATTRIBUTES_UNIFORMS     = 0x0008,
  SH_LINE_DIRECTIVES         = 0x0010,
  SH_SOURCE_PATH             = 0x0020
};

//
// Implementation dependent built-in resources (constants and extensions).
// The names for these resources has been obtained by stripping gl_/GL_.
//
struct ShBuiltInResources
{
	ShBuiltInResources();

	// Constants.
	int MaxVertexAttribs;
	int MaxVertexUniformVectors;
	int MaxVaryingVectors;
	int MaxVertexTextureImageUnits;
	int MaxCombinedTextureImageUnits;
	int MaxTextureImageUnits;
	int MaxFragmentUniformVectors;
	int MaxDrawBuffers;
	int MaxVertexOutputVectors;
	int MaxFragmentInputVectors;
	int MinProgramTexelOffset;
	int MaxProgramTexelOffset;

	// Extensions.
	// Set to 1 to enable the extension, else 0.
	int OES_standard_derivatives;
	int OES_fragment_precision_high;
	int OES_EGL_image_external;
	int EXT_draw_buffers;

	unsigned int MaxCallStackDepth;
};

typedef unsigned int GLenum;
#define GL_FRAGMENT_SHADER                0x8B30
#define GL_VERTEX_SHADER                  0x8B31

//
// The base class for the machine dependent compiler to derive from
// for managing object code from the compile.
//
class TCompiler
{
public:
	TCompiler(GLenum shaderType);
	virtual ~TCompiler();
	virtual TCompiler* getAsCompiler() { return this; }

	bool Init(const ShBuiltInResources& resources);
	bool compile(const char* const shaderStrings[],
	             const int numStrings,
	             int compileOptions);

	// Get results of the last compilation.
	int getShaderVersion() const { return shaderVersion; }
	TInfoSink& getInfoSink() { return infoSink; }

protected:
	GLenum getShaderType() const { return shaderType; }
	// Initialize symbol-table with built-in symbols.
	bool InitBuiltInSymbolTable(const ShBuiltInResources& resources);
	// Clears the results from the previous compilation.
	void clearResults();
	// Return true if function recursion is detected or call depth exceeded.
	bool validateCallDepth(TIntermNode *root, TInfoSink &infoSink);
	// Returns true if the given shader does not exceed the minimum
	// functionality mandated in GLSL 1.0 spec Appendix A.
	bool validateLimitations(TIntermNode *root);
	// Translate to object code.
	virtual bool translate(TIntermNode *root) = 0;
	// Get built-in extensions with default behavior.
	const TExtensionBehavior& getExtensionBehavior() const;

private:
	GLenum shaderType;

	unsigned int maxCallStackDepth;

	// Built-in symbol table for the given language, spec, and resources.
	// It is preserved from compile-to-compile.
	TSymbolTable symbolTable;
	// Built-in extensions with default behavior.
	TExtensionBehavior extensionBehavior;

	// Results of compilation.
	int shaderVersion;
	TInfoSink infoSink;  // Output sink.

	// Memory allocator. Allocates and tracks memory required by the compiler.
	// Deallocates all memory when compiler is destructed.
	TPoolAllocator allocator;
};

bool InitCompilerGlobals();
void FreeCompilerGlobals();

#endif // _COMPILER_INCLUDED_
