// 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.

#include "Compiler.h"

#include "AnalyzeCallDepth.h"
#include "Initialize.h"
#include "InitializeParseContext.h"
#include "InitializeGlobals.h"
#include "ParseHelper.h"
#include "ValidateLimitations.h"

namespace
{
class TScopedPoolAllocator {
public:
	TScopedPoolAllocator(TPoolAllocator* allocator, bool pushPop)
		: mAllocator(allocator), mPushPopAllocator(pushPop)
	{
		if (mPushPopAllocator) mAllocator->push();
		SetGlobalPoolAllocator(mAllocator);
	}
	~TScopedPoolAllocator()
	{
		SetGlobalPoolAllocator(nullptr);
		if (mPushPopAllocator) mAllocator->pop();
	}

private:
	TPoolAllocator* mAllocator;
	bool mPushPopAllocator;
};
}  // namespace

//
// Initialize built-in resources with minimum expected values.
//
ShBuiltInResources::ShBuiltInResources()
{
	// Constants.
	MaxVertexAttribs = 8;
	MaxVertexUniformVectors = 128;
	MaxVaryingVectors = 8;
	MaxVertexTextureImageUnits = 0;
	MaxCombinedTextureImageUnits = 8;
	MaxTextureImageUnits = 8;
	MaxFragmentUniformVectors = 16;
	MaxDrawBuffers = 1;
	MaxVertexOutputVectors = 16;
	MaxFragmentInputVectors = 15;
	MinProgramTexelOffset = -8;
	MaxProgramTexelOffset = 7;

	// Extensions.
	OES_standard_derivatives = 0;
	OES_fragment_precision_high = 0;
	OES_EGL_image_external = 0;

	MaxCallStackDepth = UINT_MAX;
}

TCompiler::TCompiler(GLenum type)
	: shaderType(type),
	  maxCallStackDepth(UINT_MAX)
{
	allocator.push();
	SetGlobalPoolAllocator(&allocator);
}

TCompiler::~TCompiler()
{
	SetGlobalPoolAllocator(nullptr);
	allocator.popAll();
}

bool TCompiler::Init(const ShBuiltInResources& resources)
{
	shaderVersion = 100;
	maxCallStackDepth = resources.MaxCallStackDepth;
	TScopedPoolAllocator scopedAlloc(&allocator, false);

	// Generate built-in symbol table.
	if (!InitBuiltInSymbolTable(resources))
		return false;
	InitExtensionBehavior(resources, extensionBehavior);

	return true;
}

bool TCompiler::compile(const char* const shaderStrings[],
                        const int numStrings,
                        int compileOptions)
{
	TScopedPoolAllocator scopedAlloc(&allocator, true);
	clearResults();

	if (numStrings == 0)
		return true;

	// First string is path of source file if flag is set. The actual source follows.
	const char* sourcePath = nullptr;
	int firstSource = 0;
	if (compileOptions & SH_SOURCE_PATH)
	{
		sourcePath = shaderStrings[0];
		++firstSource;
	}

	TIntermediate intermediate(infoSink);
	TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
	                           shaderType, compileOptions, true,
	                           sourcePath, infoSink);
	SetGlobalParseContext(&parseContext);

	// We preserve symbols at the built-in level from compile-to-compile.
	// Start pushing the user-defined symbols at global level.
	symbolTable.push();
	if (!symbolTable.atGlobalLevel())
		infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");

	// Parse shader.
	bool success =
		(PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], nullptr, &parseContext) == 0) &&
		(parseContext.getTreeRoot() != nullptr);

	shaderVersion = parseContext.getShaderVersion();

	if (success) {
		TIntermNode* root = parseContext.getTreeRoot();
		success = intermediate.postProcess(root);

		if (success)
			success = validateCallDepth(root, infoSink);

		if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING))
			success = validateLimitations(root);

		if (success && (compileOptions & SH_INTERMEDIATE_TREE))
			intermediate.outputTree(root);

		if (success && (compileOptions & SH_OBJECT_CODE))
			success = translate(root);
	}

	// Ensure symbol table is returned to the built-in level,
	// throwing away all but the built-ins.
	while (!symbolTable.atBuiltInLevel())
		symbolTable.pop();

	return success;
}

bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
{
	assert(symbolTable.isEmpty());
	symbolTable.push();   // COMMON_BUILTINS
	symbolTable.push();   // ESSL1_BUILTINS
	symbolTable.push();   // ESSL3_BUILTINS

	TPublicType integer;
	integer.type = EbtInt;
	integer.primarySize = 1;
	integer.secondarySize = 1;
	integer.array = false;

	TPublicType floatingPoint;
	floatingPoint.type = EbtFloat;
	floatingPoint.primarySize = 1;
	floatingPoint.secondarySize = 1;
	floatingPoint.array = false;

	switch(shaderType)
	{
	case GL_FRAGMENT_SHADER:
		symbolTable.setDefaultPrecision(integer, EbpMedium);
		break;
	case GL_VERTEX_SHADER:
		symbolTable.setDefaultPrecision(integer, EbpHigh);
		symbolTable.setDefaultPrecision(floatingPoint, EbpHigh);
		break;
	default: assert(false && "Language not supported");
	}

	InsertBuiltInFunctions(shaderType, resources, symbolTable);

	IdentifyBuiltIns(shaderType, resources, symbolTable);

	return true;
}

void TCompiler::clearResults()
{
	infoSink.info.erase();
	infoSink.obj.erase();
	infoSink.debug.erase();
}

bool TCompiler::validateCallDepth(TIntermNode *root, TInfoSink &infoSink)
{
	AnalyzeCallDepth validator(root);

	unsigned int depth = validator.analyzeCallDepth();

	if(depth == 0)
	{
		infoSink.info.prefix(EPrefixError);
		infoSink.info << "Missing main()";
		return false;
	}
	else if(depth == UINT_MAX)
	{
		infoSink.info.prefix(EPrefixError);
		infoSink.info << "Function recursion detected";
		return false;
	}
	else if(depth > maxCallStackDepth)
	{
		infoSink.info.prefix(EPrefixError);
		infoSink.info << "Function call stack too deep";
		return false;
	}

	return true;
}

bool TCompiler::validateLimitations(TIntermNode* root) {
	ValidateLimitations validate(shaderType, infoSink.info);
	root->traverse(&validate);
	return validate.numErrors() == 0;
}

const TExtensionBehavior& TCompiler::getExtensionBehavior() const
{
	return extensionBehavior;
}

bool InitCompilerGlobals()
{
	if(!InitializePoolIndex())
	{
		assert(0 && "InitCompilerGlobals(): Failed to initalize global pool");
		return false;
	}

	if(!InitializeParseContextIndex())
	{
		assert(0 && "InitCompilerGlobals(): Failed to initalize parse context");
		return false;
	}

	return true;
}

void FreeCompilerGlobals()
{
	FreeParseContextIndex();
	FreePoolIndex();
}
