From 6d11ee7d6137117f441951615cd4cde4d59bf968 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sat, 6 Mar 2021 14:04:24 +0200 Subject: [PATCH] Refactor resolution of declarations for MemberAccess Now that expressions have types, there's no need to "return" the members from deeper in the hierarchy anymore. Since member type resolution now depends on the type of the left-hand expression of MemberAccess, variables and expressions need to be resolved in a loop until there's nothing more to resolve. --- source/glsl/compiler.cpp | 24 +++--- source/glsl/compiler.h | 3 + source/glsl/generate.cpp | 169 +++++++++++++++++++++------------------ source/glsl/generate.h | 10 ++- 4 files changed, 112 insertions(+), 94 deletions(-) diff --git a/source/glsl/compiler.cpp b/source/glsl/compiler.cpp index 66a487fb..30a3f08c 100644 --- a/source/glsl/compiler.cpp +++ b/source/glsl/compiler.cpp @@ -241,16 +241,12 @@ void Compiler::generate(Stage &stage, Mode mode) // Initial resolving pass BlockHierarchyResolver().apply(stage); - TypeResolver().apply(stage); - FunctionResolver().apply(stage); - VariableResolver().apply(stage); + resolve(stage); /* All variables local to a stage have been resolved. Resolve non-local variables through interfaces. */ InterfaceGenerator().apply(stage); - TypeResolver().apply(stage); - VariableResolver().apply(stage); - ExpressionResolver().apply(stage); + resolve(stage); FunctionResolver().apply(stage); ConstantSpecializer().apply(stage, (mode==PROGRAM && specialized ? &spec_values : 0)); @@ -258,6 +254,15 @@ void Compiler::generate(Stage &stage, Mode mode) LegacyConverter().apply(stage, features); } +void Compiler::resolve(Stage &stage) +{ + TypeResolver().apply(stage); + // Use the bitwise or to always evaluate both operands + while(VariableResolver().apply(stage) | + ExpressionResolver().apply(stage)) ; + FunctionResolver().apply(stage); +} + bool Compiler::validate(Stage &stage) { TypeValidator().apply(stage); @@ -279,12 +284,7 @@ Compiler::OptimizeResult Compiler::optimize(Stage &stage) bool any_inlined = FunctionInliner().apply(stage); any_inlined |= ExpressionInliner().apply(stage); if(any_inlined) - { - TypeResolver().apply(stage); - VariableResolver().apply(stage); - FunctionResolver().apply(stage); - ExpressionResolver().apply(stage); - } + resolve(stage); /* Removing variables or functions may cause things from the previous stage to become unused. */ diff --git a/source/glsl/compiler.h b/source/glsl/compiler.h index 29561407..9891293a 100644 --- a/source/glsl/compiler.h +++ b/source/glsl/compiler.h @@ -113,6 +113,9 @@ private: variables. */ void generate(Stage &, Mode); + /** Resolves references and expression types. */ + void resolve(Stage &); + bool validate(Stage &); /** Applies optimizations to a stage. The return value indicates which diff --git a/source/glsl/generate.cpp b/source/glsl/generate.cpp index 1c8af82a..610aa390 100644 --- a/source/glsl/generate.cpp +++ b/source/glsl/generate.cpp @@ -218,17 +218,19 @@ void TypeResolver::visit(FunctionDeclaration &func) VariableResolver::VariableResolver(): stage(0), - r_members(0), + r_any_resolved(false), record_target(false), r_self_referencing(false), r_assignment_target(0) { } -void VariableResolver::apply(Stage &s) +bool VariableResolver::apply(Stage &s) { stage = &s; s.interface_blocks.clear(); + r_any_resolved = false; s.content.visit(*this); + return r_any_resolved; } void VariableResolver::enter(Block &block) @@ -238,19 +240,19 @@ void VariableResolver::enter(Block &block) void VariableResolver::visit(VariableReference &var) { - var.declaration = 0; - r_members = 0; + VariableDeclaration *declaration = 0; + /* Look for variable declarations in the block hierarchy first. Interface blocks are always defined in the top level so we can't accidentally skip one. */ - for(Block *block=current_block; (!var.declaration && block); block=block->parent) + for(Block *block=current_block; (!declaration && block); block=block->parent) { map::iterator i = block->variables.find(var.name); if(i!=block->variables.end()) - var.declaration = i->second; + declaration = i->second; } - if(!var.declaration) + if(!declaration) { const map &blocks = stage->interface_blocks; map::const_iterator i = blocks.find("_"+var.name); @@ -263,24 +265,22 @@ void VariableResolver::visit(VariableReference &var) r_iface_ref->line = var.line; r_iface_ref->name = var.name; r_iface_ref->declaration = i->second; - r_members = &i->second->members.variables; } else { // Look for the variable in anonymous interface blocks. - for(i=blocks.begin(); (!var.declaration && i!=blocks.end()); ++i) + for(i=blocks.begin(); (!declaration && i!=blocks.end()); ++i) if(i->second->instance_name.empty()) { map::iterator j = i->second->members.variables.find(var.name); if(j!=i->second->members.variables.end()) - var.declaration = j->second; + declaration = j->second; } } } - if(var.declaration) - if(StructDeclaration *strct = dynamic_cast(var.declaration->type_declaration)) - r_members = &strct->members.variables; + r_any_resolved |= (declaration!=var.declaration); + var.declaration = declaration; if(record_target) { @@ -300,44 +300,44 @@ void VariableResolver::visit(VariableReference &var) void VariableResolver::visit(InterfaceBlockReference &iface) { - iface.declaration = 0; map::iterator i = stage->interface_blocks.find("_"+iface.name); - if(i!=stage->interface_blocks.end()) - { - iface.declaration = i->second; - r_members = &i->second->members.variables; - } + InterfaceBlock *declaration = (i!=stage->interface_blocks.end() ? i->second : 0); + r_any_resolved |= (declaration!=iface.declaration); + iface.declaration = declaration; } void VariableResolver::visit(MemberAccess &memacc) { - r_members = 0; r_iface_ref = 0; memacc.left->visit(*this); - if(r_iface_ref) memacc.left = r_iface_ref; r_iface_ref = 0; - memacc.declaration = 0; - if(r_members) + map *members = 0; + if(StructDeclaration *strct = dynamic_cast(memacc.left->type)) + members = &strct->members.variables; + else if(InterfaceBlockReference *iface_ref = dynamic_cast(memacc.left.get())) { - map::iterator i = r_members->find(memacc.member); - if(i!=r_members->end()) - { - memacc.declaration = i->second; - if(StructDeclaration *strct = dynamic_cast(i->second->type_declaration)) - r_members = &strct->members.variables; - } - else - r_members = 0; + if(iface_ref->declaration) + members = &iface_ref->declaration->members.variables; } + + VariableDeclaration *declaration = 0; + if(members) + { + map::iterator i = members->find(memacc.member); + if(i!=members->end()) + declaration = i->second; + } + + r_any_resolved |= (declaration!=memacc.declaration); + memacc.declaration = declaration; } void VariableResolver::visit(UnaryExpression &unary) { TraversingVisitor::visit(unary); - r_members = 0; r_iface_ref = 0; } @@ -351,17 +351,13 @@ void VariableResolver::visit(BinaryExpression &binary) SetFlag set(record_target, false); binary.right->visit(*this); } - r_members = 0; r_iface_ref = 0; binary.left->visit(*this); if(r_iface_ref) binary.left = r_iface_ref; } else - { TraversingVisitor::visit(binary); - r_members = 0; - } r_iface_ref = 0; } @@ -372,6 +368,7 @@ void VariableResolver::visit(Assignment &assign) SetFlag set(record_target); r_assignment_target = 0; assign.left->visit(*this); + r_any_resolved |= (r_assignment_target!=assign.target_declaration); assign.target_declaration = r_assignment_target; } @@ -379,14 +376,12 @@ void VariableResolver::visit(Assignment &assign) assign.right->visit(*this); assign.self_referencing = (r_self_referencing || assign.oper->token[0]!='='); - r_members = 0; r_iface_ref = 0; } void VariableResolver::visit(FunctionCall &call) { TraversingVisitor::visit(call); - r_members = 0; r_iface_ref = 0; } @@ -412,6 +407,19 @@ void VariableResolver::visit(InterfaceBlock &iface) } +ExpressionResolver::ExpressionResolver(): + stage(0), + r_any_resolved(false) +{ } + +bool ExpressionResolver::apply(Stage &s) +{ + stage = &s; + r_any_resolved = false; + s.content.visit(*this); + return r_any_resolved; +} + bool ExpressionResolver::is_scalar(BasicTypeDeclaration &type) { return (type.kind==BasicTypeDeclaration::INT || type.kind==BasicTypeDeclaration::FLOAT); @@ -505,34 +513,38 @@ bool ExpressionResolver::convert_to_element(RefPtr &expr, BasicTypeD return false; } +void ExpressionResolver::resolve(Expression &expr, TypeDeclaration *type, bool lvalue) +{ + r_any_resolved |= (type!=expr.type || lvalue!=expr.lvalue); + expr.type = type; + expr.lvalue = lvalue; +} + void ExpressionResolver::visit(Literal &literal) { if(literal.value.check_type()) - literal.type = find_type(BasicTypeDeclaration::BOOL, 1); + resolve(literal, find_type(BasicTypeDeclaration::BOOL, 1), false); else if(literal.value.check_type()) - literal.type = find_type(BasicTypeDeclaration::INT, 32); + resolve(literal, find_type(BasicTypeDeclaration::INT, 32), false); else if(literal.value.check_type()) - literal.type = find_type(BasicTypeDeclaration::FLOAT, 32); + resolve(literal, find_type(BasicTypeDeclaration::FLOAT, 32), false); } void ExpressionResolver::visit(ParenthesizedExpression &parexpr) { TraversingVisitor::visit(parexpr); - - parexpr.type = parexpr.expression->type; - parexpr.lvalue = parexpr.expression->lvalue; + resolve(parexpr, parexpr.expression->type, parexpr.expression->lvalue); } void ExpressionResolver::visit(VariableReference &var) { if(var.declaration) - var.type = var.declaration->type_declaration; - var.lvalue = true; + resolve(var, var.declaration->type_declaration, true); } void ExpressionResolver::visit(InterfaceBlockReference &iface) { - iface.lvalue = true; + resolve(iface, 0, true); } void ExpressionResolver::visit(MemberAccess &memacc) @@ -540,8 +552,7 @@ void ExpressionResolver::visit(MemberAccess &memacc) TraversingVisitor::visit(memacc); if(memacc.declaration) - memacc.type = memacc.declaration->type_declaration; - memacc.lvalue = memacc.left->lvalue; + resolve(memacc, memacc.declaration->type_declaration, memacc.left->lvalue); } void ExpressionResolver::visit(UnaryExpression &unary) @@ -555,21 +566,21 @@ void ExpressionResolver::visit(UnaryExpression &unary) char oper = unary.oper->token[0]; if(oper=='!') { - if(basic->kind==BasicTypeDeclaration::BOOL) - unary.type = basic; + if(basic->kind!=BasicTypeDeclaration::BOOL) + return; } else if(oper=='~') { - if(basic->kind==BasicTypeDeclaration::INT) - unary.type = basic; + if(basic->kind!=BasicTypeDeclaration::INT) + return; } else if(oper=='+' || oper=='-') { BasicTypeDeclaration *elem = get_element_type(*basic); - if(elem && is_scalar(*elem)) - unary.type = basic; + if(!elem || !is_scalar(*elem)) + return; } - unary.lvalue = unary.expression->lvalue; + resolve(unary, basic, unary.expression->lvalue); } void ExpressionResolver::visit(BinaryExpression &binary) @@ -583,8 +594,6 @@ void ExpressionResolver::visit(BinaryExpression &binary) if(!basic_left || !basic_right) return; - binary.lvalue = false; - char oper = binary.oper->token[0]; if(oper=='[') { @@ -593,8 +602,7 @@ void ExpressionResolver::visit(BinaryExpression &binary) if((!is_vector_or_matrix(*basic_left) && basic_left->kind!=BasicTypeDeclaration::ARRAY) || basic_right->kind!=BasicTypeDeclaration::INT) return; - binary.type = basic_left->base_type; - binary.lvalue = binary.left->lvalue; + resolve(binary, basic_left->base_type, binary.left->lvalue); return; } else if(basic_left->kind==BasicTypeDeclaration::ARRAY || basic_right->kind==BasicTypeDeclaration::ARRAY) @@ -611,6 +619,7 @@ void ExpressionResolver::visit(BinaryExpression &binary) if(elem_compat==NOT_COMPATIBLE) return; + TypeDeclaration *type = 0; char oper2 = binary.oper->token[1]; if((oper=='<' && oper2!='<') || (oper=='>' && oper2!='>')) { @@ -619,7 +628,7 @@ void ExpressionResolver::visit(BinaryExpression &binary) if(!is_scalar(*elem_left) || !is_scalar(*elem_right) || compat==NOT_COMPATIBLE) return; - binary.type = find_type(BasicTypeDeclaration::BOOL, 1); + type = find_type(BasicTypeDeclaration::BOOL, 1); } else if((oper=='=' || oper=='!') && oper2=='=') { @@ -627,7 +636,7 @@ void ExpressionResolver::visit(BinaryExpression &binary) if(compat==NOT_COMPATIBLE) return; - binary.type = find_type(BasicTypeDeclaration::BOOL, 1); + type = find_type(BasicTypeDeclaration::BOOL, 1); } else if(oper2=='&' || oper2=='|' || oper2=='^') { @@ -635,7 +644,7 @@ void ExpressionResolver::visit(BinaryExpression &binary) if(basic_left->kind!=BasicTypeDeclaration::BOOL || basic_right->kind!=BasicTypeDeclaration::BOOL) return; - binary.type = basic_left; + type = basic_left; } else if((oper=='&' || oper=='|' || oper=='^' || oper=='%') && !oper2) { @@ -643,7 +652,7 @@ void ExpressionResolver::visit(BinaryExpression &binary) if(basic_left->kind!=BasicTypeDeclaration::INT || basic_right->kind!=BasicTypeDeclaration::INT) return; - binary.type = (compat==LEFT_CONVERTIBLE ? basic_right : basic_left); + type = (compat==LEFT_CONVERTIBLE ? basic_right : basic_left); } else if((oper=='<' || oper=='>') && oper2==oper) { @@ -651,7 +660,7 @@ void ExpressionResolver::visit(BinaryExpression &binary) if(basic_left->kind!=BasicTypeDeclaration::INT || basic_right->kind!=BasicTypeDeclaration::INT) return; - binary.type = basic_left; + type = basic_left; } else if(oper=='+' || oper=='-' || oper=='*' || oper=='/') { @@ -674,26 +683,26 @@ void ExpressionResolver::visit(BinaryExpression &binary) BasicTypeDeclaration *elem_result = (elem_compat==LEFT_CONVERTIBLE ? elem_right : elem_left); if(basic_left->kind==BasicTypeDeclaration::VECTOR) - binary.type = find_type(*elem_result, BasicTypeDeclaration::VECTOR, basic_right->size&0xFFFF); + type = find_type(*elem_result, BasicTypeDeclaration::VECTOR, basic_right->size&0xFFFF); else if(basic_right->kind==BasicTypeDeclaration::VECTOR) - binary.type = find_type(*elem_result, BasicTypeDeclaration::VECTOR, basic_left->size>>16); + type = find_type(*elem_result, BasicTypeDeclaration::VECTOR, basic_left->size>>16); else - binary.type = find_type(*elem_result, BasicTypeDeclaration::MATRIX, (basic_left->size&0xFFFF0000)|(basic_right->size&0xFFFF)); + type = find_type(*elem_result, BasicTypeDeclaration::MATRIX, (basic_left->size&0xFFFF0000)|(basic_right->size&0xFFFF)); } else if(compat==NOT_COMPATIBLE) { // Arithmetic between scalars and matrices or vectors is supported. if(is_scalar(*basic_left) && is_vector_or_matrix(*basic_right)) - binary.type = (elem_compat==RIGHT_CONVERTIBLE ? find_type(*elem_left, basic_right->kind, basic_right->size) : basic_right); + type = (elem_compat==RIGHT_CONVERTIBLE ? find_type(*elem_left, basic_right->kind, basic_right->size) : basic_right); else if(is_vector_or_matrix(*basic_left) && is_scalar(*basic_right)) - binary.type = (elem_compat==LEFT_CONVERTIBLE ? find_type(*elem_right, basic_left->kind, basic_left->size) : basic_left); + type = (elem_compat==LEFT_CONVERTIBLE ? find_type(*elem_right, basic_left->kind, basic_left->size) : basic_left); else return; } else if(compat==LEFT_CONVERTIBLE) - binary.type = basic_right; + type = basic_right; else - binary.type = basic_left; + type = basic_left; } else return; @@ -709,28 +718,30 @@ void ExpressionResolver::visit(BinaryExpression &binary) converted = convert_to_element(binary.right, *elem_left); if(!converted) - binary.type = 0; + type = 0; + + resolve(binary, type, false); } void ExpressionResolver::visit(Assignment &assign) { TraversingVisitor::visit(assign); - assign.type = assign.left->type; - assign.lvalue = true; + resolve(assign, assign.left->type, true); } void ExpressionResolver::visit(FunctionCall &call) { TraversingVisitor::visit(call); + TypeDeclaration *type = 0; if(call.declaration) - call.type = call.declaration->return_type_declaration; + type = call.declaration->return_type_declaration; else if(call.constructor) { map::const_iterator i=stage->types.find(call.name); - call.type = (i!=stage->types.end() ? i->second : 0); + type = (i!=stage->types.end() ? i->second : 0); } - call.lvalue = false; + resolve(call, type, false); } void ExpressionResolver::visit(BasicTypeDeclaration &type) diff --git a/source/glsl/generate.h b/source/glsl/generate.h index ddf2b5f6..3d175b42 100644 --- a/source/glsl/generate.h +++ b/source/glsl/generate.h @@ -85,9 +85,9 @@ class VariableResolver: private TraversingVisitor { private: Stage *stage; - std::map *r_members; RefPtr r_iface_ref; std::string block_interface; + bool r_any_resolved; bool record_target; bool r_self_referencing; VariableDeclaration *r_assignment_target; @@ -95,7 +95,7 @@ private: public: VariableResolver(); - void apply(Stage &); + bool apply(Stage &); private: virtual void enter(Block &); @@ -124,9 +124,12 @@ private: Stage *stage; std::vector basic_types; + bool r_any_resolved; public: - void apply(Stage &s) { stage = &s; s.content.visit(*this); } + ExpressionResolver(); + + bool apply(Stage &); private: static bool is_scalar(BasicTypeDeclaration &); @@ -138,6 +141,7 @@ private: BasicTypeDeclaration *find_type(BasicTypeDeclaration &, BasicTypeDeclaration::Kind, unsigned); void convert_to(RefPtr &, BasicTypeDeclaration &); bool convert_to_element(RefPtr &, BasicTypeDeclaration &); + void resolve(Expression &, TypeDeclaration *, bool); virtual void visit(Literal &); virtual void visit(ParenthesizedExpression &); -- 2.43.0