TIntermAggregate* ir_grow_declaration(TIntermTyped* declaration, TIntermSymbol *symbol, TIntermTyped *initializer, TParseContext& ctx)
{
	TIntermTyped* added_decl = ir_add_declaration (symbol, initializer, symbol->getLine(), ctx);

	if (declaration->getAsDeclaration()) {
		TIntermAggregate* aggregate = ir_make_aggregate(declaration, declaration->getLine());
		aggregate->setOperator(EOpSequence);
		declaration = aggregate;
	}
	assert (declaration->getAsAggregate());
		
	TIntermAggregate* aggregate = ir_grow_aggregate(declaration, added_decl, added_decl->getLine(), EOpSequence);
	aggregate->setOperator(EOpSequence);
	
	return aggregate;
}
// This is the safe way to change the operator on an aggregate, as it
// does lots of error checking and fixing.  Especially for establishing
// a function call's operation on it's set of parameters.  Sequences
// of instructions are also aggregates, but they just direnctly set
// their operator to EOpSequence.
//
// Returns an aggregate node, which could be the one passed in if
// it was already an aggregate.
TIntermAggregate* ir_set_aggregate_op(TIntermNode* node, TOperator op, TSourceLoc line)
{
   TIntermAggregate* aggNode;

   //
   // Make sure we have an aggregate.  If not turn it into one.
   //
   if (node)
   {
      aggNode = node->getAsAggregate();
      if (aggNode == 0 || aggNode->getOp() != EOpNull)
      {
         //
         // Make an aggregate containing this node.
         //
         aggNode = new TIntermAggregate();
         aggNode->getNodes().push_back(node);
         if (line.line == 0)
            line = node->getLine();
      }
   }
   else
      aggNode = new TIntermAggregate();

   //
   // Set the operator.
   //
   aggNode->setOperator(op);
   if (line.line != 0)
      aggNode->setLine(line);

   return aggNode;
}
TIntermDeclaration* ir_grow_declaration(TIntermDeclaration* declaration, TIntermSymbol *symbol, TIntermTyped *initializer, TInfoSink& infoSink)
{
	TIntermTyped* added_decl = symbol;
	if (initializer)
		added_decl = ir_add_assign(EOpAssign, symbol, initializer, symbol->getLine(), infoSink);
	
	if (declaration->isSingleDeclaration()) {
		TIntermTyped* current = declaration->getDeclaration();
		TIntermAggregate* aggregate = ir_make_aggregate(current, current->getLine());
		aggregate->setOperator(EOpComma);
		declaration->getDeclaration() = aggregate;
	}
		
	TIntermAggregate* aggregate = ir_grow_aggregate(declaration->getDeclaration(), added_decl, added_decl->getLine());
	aggregate->setOperator(EOpComma);
	declaration->getDeclaration() = aggregate;
	
	return declaration;
}
//
// This is to be executed once the final root is put on top by the parsing
// process.
//
bool TIntermediate::postProcess(TIntermNode* root, EShLanguage language)
{
    if (root == 0)
        return true;

    //
    // First, finish off the top level sequence, if any
    //
    TIntermAggregate* aggRoot = root->getAsAggregate();
    if (aggRoot && aggRoot->getOp() == EOpNull)
        aggRoot->setOperator(EOpSequence);

    return true;
}
Exemple #5
0
int C_DECL Hlsl2Glsl_Parse(
	const ShHandle handle,
	const char* shaderString,
	ETargetVersion targetVersion,
	Hlsl2Glsl_ParseCallbacks* callbacks,
	unsigned options)
{
   if (!InitThread())
      return 0;

   if (handle == 0)
      return 0;

   HlslCrossCompiler* compiler = handle;

   GlobalPoolAllocator.push();
   compiler->infoSink.info.erase();
   compiler->infoSink.debug.erase();

   if (!shaderString)
	   return 1;

   TSymbolTable symbolTable(SymbolTables[compiler->getLanguage()]);

   GenerateBuiltInSymbolTable(compiler->infoSink, &symbolTable, compiler->getLanguage());

   TParseContext parseContext(symbolTable, compiler->getLanguage(), targetVersion, options, compiler->infoSink);

   GlobalParseContext = &parseContext;

   setInitialState();

   //
   // Parse the application's shaders.  All the following symbol table
   // work will be throw-away, so push a new allocation scope that can
   // be thrown away, then push a scope for the current shader's globals.
   //
   bool success = true;

   symbolTable.push();
   if (!symbolTable.atGlobalLevel())
      parseContext.infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");


   int ret = PaParseString(const_cast<char*>(shaderString), parseContext, callbacks);
   if (ret)
      success = false;

   if (success && parseContext.treeRoot)
   {
		TIntermAggregate* aggRoot = parseContext.treeRoot->getAsAggregate();
		if (aggRoot && aggRoot->getOp() == EOpNull)
			aggRoot->setOperator(EOpSequence);

		if (options & ETranslateOpIntermediate)
			ir_output_tree(parseContext.treeRoot, parseContext.infoSink);

		compiler->TransformAST (parseContext.treeRoot);
		compiler->ProduceGLSL (parseContext.treeRoot, targetVersion, options);
   }
   else if (!success)
   {
		// only add "X compilation errors" message if somehow there are no other errors whatsoever, yet
		// we still failed. for some reason.
		if (parseContext.infoSink.info.IsEmpty())
		{
			parseContext.infoSink.info.prefix(EPrefixError);
			parseContext.infoSink.info << parseContext.numErrors << " compilation errors.  No code generated.\n\n";
		}
		success = false;
		if (options & ETranslateOpIntermediate)
			ir_output_tree(parseContext.treeRoot, parseContext.infoSink);
   }

	ir_remove_tree(parseContext.treeRoot);

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

   //
   // Throw away all the temporary memory used by the compilation process.
   //
   GlobalPoolAllocator.pop();

   return success ? 1 : 0;
}
int C_DECL Hlsl2Glsl_Parse( const ShHandle handle,
                            const char* shaderString,
                            int options )
{
   if (!InitThread())
      return 0;

   if (handle == 0)
      return 0;

   HlslCrossCompiler* compiler = handle;

   GlobalPoolAllocator.push();
   compiler->infoSink.info.erase();
   compiler->infoSink.debug.erase();

   if (!shaderString)
	   return 1;

   TIntermediate intermediate(compiler->infoSink);
   TSymbolTable symbolTable(SymbolTables[compiler->getLanguage()]);

   GenerateBuiltInSymbolTable(compiler->infoSink, &symbolTable, compiler->getLanguage());

   TParseContext parseContext(symbolTable, intermediate, compiler->getLanguage(), compiler->infoSink);

   GlobalParseContext = &parseContext;

   setInitialState();

   InitPreprocessor();    
   //
   // Parse the application's shaders.  All the following symbol table
   // work will be throw-away, so push a new allocation scope that can
   // be thrown away, then push a scope for the current shader's globals.
   //
   bool success = true;

   symbolTable.push();
   if (!symbolTable.atGlobalLevel())
      parseContext.infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");


   int ret = PaParseString(const_cast<char*>(shaderString), parseContext);
   if (ret)
      success = false;

   if (success && parseContext.treeRoot)
   {
		TIntermAggregate* aggRoot = parseContext.treeRoot->getAsAggregate();
		if (aggRoot && aggRoot->getOp() == EOpNull)
			aggRoot->setOperator(EOpSequence);

		if (options & ETranslateOpIntermediate)
			intermediate.outputTree(parseContext.treeRoot);

		compiler->TransformAST (parseContext.treeRoot);
		compiler->ProduceGLSL (parseContext.treeRoot, (options & ETranslateOpUsePrecision) ? true : false);
   }
   else if (!success)
   {
      parseContext.infoSink.info.prefix(EPrefixError);
      parseContext.infoSink.info << parseContext.numErrors << " compilation errors.  No code generated.\n\n";
      success = false;
	  if (options & ETranslateOpIntermediate)
         intermediate.outputTree(parseContext.treeRoot);
   }

   intermediate.remove(parseContext.treeRoot);

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

   FinalizePreprocessor();
   //
   // Throw away all the temporary memory used by the compilation process.
   //
   GlobalPoolAllocator.pop();

   return success ? 1 : 0;
}