]> git.tdb.fi Git - libs/gl.git/commitdiff
Further refactor the resolving process in SL::Compiler
authorMikko Rasa <tdb@tdb.fi>
Sun, 7 Mar 2021 10:58:23 +0000 (12:58 +0200)
committerMikko Rasa <tdb@tdb.fi>
Sun, 7 Mar 2021 13:16:19 +0000 (15:16 +0200)
There's now five different types of resolve operations, many of which
depend on some others.  Better put the logic in one place to keep it
straight.

This also includes some rearrangements to the resolver classes to have
all of them return a boolean indicating if anything was done.

source/glsl/compiler.cpp
source/glsl/compiler.h
source/glsl/generate.cpp
source/glsl/generate.h

index 30a3f08c58a98b34cf10ffc8224540375978c69e..7dbb501c777bd177b53e9ba37229913e5f07fd92 100644 (file)
@@ -240,27 +240,46 @@ void Compiler::generate(Stage &stage, Mode mode)
                inject_block(stage.content, builtins->content);
 
        // Initial resolving pass
-       BlockHierarchyResolver().apply(stage);
        resolve(stage);
 
        /* All variables local to a stage have been resolved.  Resolve non-local
        variables through interfaces. */
        InterfaceGenerator().apply(stage);
-       resolve(stage);
+       resolve(stage, RESOLVE_BLOCKS|RESOLVE_TYPES|RESOLVE_VARIABLES);
 
-       FunctionResolver().apply(stage);
        ConstantSpecializer().apply(stage, (mode==PROGRAM && specialized ? &spec_values : 0));
        if(mode==PROGRAM)
+       {
                LegacyConverter().apply(stage, features);
+               resolve(stage, RESOLVE_VARIABLES|RESOLVE_FUNCTIONS);
+       }
 }
 
-void Compiler::resolve(Stage &stage)
+template<typename T>
+bool Compiler::resolve(Stage &stage, unsigned &flags, unsigned bit)
 {
-       TypeResolver().apply(stage);
-       // Use the bitwise or to always evaluate both operands
-       while(VariableResolver().apply(stage) |
-               ExpressionResolver().apply(stage)) ;
-       FunctionResolver().apply(stage);
+       if(!(flags&bit))
+               return false;
+
+       flags &= ~bit;
+       return T().apply(stage);
+}
+
+void Compiler::resolve(Stage &stage, unsigned flags)
+{
+       while(flags)
+       {
+               if(resolve<BlockHierarchyResolver>(stage, flags, RESOLVE_BLOCKS))
+                       ;
+               else if(resolve<TypeResolver>(stage, flags, RESOLVE_TYPES))
+                       flags |= RESOLVE_VARIABLES|RESOLVE_EXPRESSIONS;
+               else if(resolve<VariableResolver>(stage, flags, RESOLVE_VARIABLES))
+                       flags |= RESOLVE_EXPRESSIONS;
+               else if(resolve<FunctionResolver>(stage, flags, RESOLVE_FUNCTIONS))
+                       flags |= RESOLVE_EXPRESSIONS;
+               else if(resolve<ExpressionResolver>(stage, flags, RESOLVE_EXPRESSIONS))
+                       flags |= RESOLVE_VARIABLES;
+       }
 }
 
 bool Compiler::validate(Stage &stage)
@@ -281,10 +300,17 @@ Compiler::OptimizeResult Compiler::optimize(Stage &stage)
 {
        ConstantConditionEliminator().apply(stage);
 
-       bool any_inlined = FunctionInliner().apply(stage);
-       any_inlined |= ExpressionInliner().apply(stage);
-       if(any_inlined)
-               resolve(stage);
+       bool any_inlined = false;
+       if(FunctionInliner().apply(stage))
+       {
+               resolve(stage, RESOLVE_TYPES|RESOLVE_VARIABLES|RESOLVE_EXPRESSIONS);
+               any_inlined = true;
+       }
+       if(ExpressionInliner().apply(stage))
+       {
+               resolve(stage, RESOLVE_VARIABLES|RESOLVE_EXPRESSIONS);
+               any_inlined = true;
+       }
 
        /* Removing variables or functions may cause things from the previous stage
        to become unused. */
index 9891293af303e5552c1d970977f7ac528c4af6a7..6448ae6cfa6fe962dc5097ffcf2011f835ebbaf9 100644 (file)
@@ -28,6 +28,16 @@ private:
                REDO_PREVIOUS
        };
 
+       enum ResolveFlags
+       {
+               RESOLVE_BLOCKS = 1,
+               RESOLVE_TYPES = 2,
+               RESOLVE_VARIABLES = 4,
+               RESOLVE_EXPRESSIONS = 8,
+               RESOLVE_FUNCTIONS = 16,
+               RESOLVE_ALL = 31
+       };
+
        Features features;
        Module *module;
        std::vector<std::string> imported_names;
@@ -113,8 +123,13 @@ private:
        variables. */
        void generate(Stage &, Mode);
 
-       /** Resolves references and expression types. */
-       void resolve(Stage &);
+       template<typename T>
+       bool resolve(Stage &, unsigned &, unsigned);
+
+       /** Resolves various references between nodes.  Flags can be specified to
+       request resolving particular aspects.  Resolving may ripple into other
+       aspects as necessary. */
+       void resolve(Stage &, unsigned = RESOLVE_ALL);
 
        bool validate(Stage &);
 
index 1e57ed649041cacdfaa58b56fa0a56dee5642dc9..4e225ae520569dab6188666ba1bc7a2c026a5bb2 100644 (file)
@@ -116,31 +116,57 @@ void ConstantSpecializer::visit(VariableDeclaration &var)
 
 void BlockHierarchyResolver::enter(Block &block)
 {
+       r_any_resolved |= (current_block!=block.parent);
        block.parent = current_block;
 }
 
 
 TypeResolver::TypeResolver():
-       stage(0)
+       stage(0),
+       r_any_resolved(false)
 { }
 
-void TypeResolver::apply(Stage &s)
+bool TypeResolver::apply(Stage &s)
 {
        stage = &s;
        s.types.clear();
+       r_any_resolved = false;
        s.content.visit(*this);
+       return r_any_resolved;
+}
+
+TypeDeclaration *TypeResolver::get_or_create_array_type(TypeDeclaration &type)
+{
+       map<TypeDeclaration *, TypeDeclaration *>::iterator i = array_types.find(&type);
+       if(i!=array_types.end())
+               return i->second;
+
+       BasicTypeDeclaration *array = new BasicTypeDeclaration;
+       array->source = BUILTIN_SOURCE;
+       array->name = type.name+"[]";
+       array->kind = BasicTypeDeclaration::ARRAY;
+       array->base = type.name;
+       array->base_type = &type;
+       stage->content.body.insert(type_insert_point, array);
+       array_types[&type] = array;
+       return array;
 }
 
-TypeDeclaration *TypeResolver::resolve_type(const string &name)
+void TypeResolver::resolve_type(TypeDeclaration *&type, const string &name, bool array)
 {
+       TypeDeclaration *resolved = 0;
        map<string, TypeDeclaration *>::iterator i = stage->types.find(name);
        if(i!=stage->types.end())
        {
                map<TypeDeclaration *, TypeDeclaration *>::iterator j = alias_map.find(i->second);
-               return (j!=alias_map.end() ? j->second : i->second);
+               resolved = (j!=alias_map.end() ? j->second : i->second);
        }
-       else
-               return 0;
+
+       if(resolved && array)
+               resolved = get_or_create_array_type(*resolved);
+
+       r_any_resolved |= (resolved!=type);
+       type=resolved;
 }
 
 void TypeResolver::visit(Block &block)
@@ -155,7 +181,7 @@ void TypeResolver::visit(Block &block)
 
 void TypeResolver::visit(BasicTypeDeclaration &type)
 {
-       type.base_type = resolve_type(type.base);
+       resolve_type(type.base_type, type.base, false);
 
        if(type.kind==BasicTypeDeclaration::VECTOR && type.base_type)
                if(BasicTypeDeclaration *basic_base = dynamic_cast<BasicTypeDeclaration *>(type.base_type))
@@ -175,7 +201,7 @@ void TypeResolver::visit(BasicTypeDeclaration &type)
 
 void TypeResolver::visit(ImageTypeDeclaration &type)
 {
-       type.base_type = resolve_type(type.base);
+       resolve_type(type.base_type, type.base, false);
        stage->types.insert(make_pair(type.name, &type));
 }
 
@@ -187,31 +213,12 @@ void TypeResolver::visit(StructDeclaration &strct)
 
 void TypeResolver::visit(VariableDeclaration &var)
 {
-       TypeDeclaration *type = resolve_type(var.type);
-       if(var.array && type)
-       {
-               map<TypeDeclaration *, TypeDeclaration *>::iterator i = array_types.find(type);
-               if(i==array_types.end())
-               {
-                       BasicTypeDeclaration *array = new BasicTypeDeclaration;
-                       array->source = BUILTIN_SOURCE;
-                       array->name = type->name+"[]";
-                       array->kind = BasicTypeDeclaration::ARRAY;
-                       array->base = type->name;
-                       array->base_type = type;
-                       stage->content.body.insert(type_insert_point, array);
-                       array->visit(*this);
-                       type = array;
-               }
-               else
-                       type = i->second;
-       }
-       var.type_declaration = type;
+       resolve_type(var.type_declaration, var.type, var.array);
 }
 
 void TypeResolver::visit(FunctionDeclaration &func)
 {
-       func.return_type_declaration = resolve_type(func.return_type);
+       resolve_type(func.return_type_declaration, func.return_type, false);
        TraversingVisitor::visit(func);
 }
 
@@ -799,11 +806,13 @@ void ExpressionResolver::visit(VariableDeclaration &var)
 }
 
 
-void FunctionResolver::apply(Stage &s)
+bool FunctionResolver::apply(Stage &s)
 {
        stage = &s;
        s.functions.clear();
+       r_any_resolved = false;
        s.content.visit(*this);
+       return r_any_resolved;
 }
 
 void FunctionResolver::visit(FunctionCall &call)
index 54e39f39aa0679088ea7d18dd98192c32645f07c..a728e99ced3a8bccd24aaa89de94cbbddee09664 100644 (file)
@@ -48,8 +48,13 @@ private:
 /** Forms links between nested blocks in the syntax tree. */
 class BlockHierarchyResolver: private TraversingVisitor
 {
+private:
+       bool r_any_resolved;
+
 public:
-       void apply(Stage &s) { s.content.visit(*this); }
+       BlockHierarchyResolver(): r_any_resolved(false) { }
+
+       bool apply(Stage &s) { r_any_resolved = false; s.content.visit(*this); return r_any_resolved; }
 
 private:
        virtual void enter(Block &);
@@ -63,14 +68,16 @@ private:
        std::map<TypeDeclaration *, TypeDeclaration *> alias_map;
        std::map<TypeDeclaration *, TypeDeclaration *> array_types;
        NodeList<Statement>::iterator type_insert_point;
+       bool r_any_resolved;
 
 public:
        TypeResolver();
 
-       void apply(Stage &);
+       bool apply(Stage &);
 
 private:
-       TypeDeclaration *resolve_type(const std::string &);
+       TypeDeclaration *get_or_create_array_type(TypeDeclaration &);
+       void resolve_type(TypeDeclaration *&, const std::string &, bool);
        virtual void visit(Block &);
        virtual void visit(BasicTypeDeclaration &);
        virtual void visit(ImageTypeDeclaration &);
@@ -164,9 +171,10 @@ class FunctionResolver: private TraversingVisitor
 private:
        Stage *stage;
        std::map<std::string, std::vector<FunctionDeclaration *> > declarations;
+       bool r_any_resolved;
 
 public:
-       void apply(Stage &);
+       bool apply(Stage &);
 
 private:
        virtual void visit(FunctionCall &);