From 360d7bf192200ef585b69eb8f8643b485896ffeb Mon Sep 17 00:00:00 2001 From: Daniel Kroening Date: Sat, 4 Oct 2025 11:49:17 -0700 Subject: [PATCH] Verilog: move code for assignment patterns This moves the code that handles assignment patterns into verilog_typecheckt::assignment_conversion. --- src/verilog/verilog_typecheck.cpp | 98 ++++++++++++++++++++++++++ src/verilog/verilog_typecheck_expr.cpp | 96 ------------------------- 2 files changed, 98 insertions(+), 96 deletions(-) diff --git a/src/verilog/verilog_typecheck.cpp b/src/verilog/verilog_typecheck.cpp index b328b2f37..d95580f67 100644 --- a/src/verilog/verilog_typecheck.cpp +++ b/src/verilog/verilog_typecheck.cpp @@ -41,6 +41,104 @@ void verilog_typecheckt::assignment_conversion( exprt &rhs, const typet &lhs_type) { + // 1800-2017 10.9 + if(rhs.type().id() == ID_verilog_assignment_pattern) + { + DATA_INVARIANT( + rhs.id() == ID_verilog_assignment_pattern, + "verilog_assignment_pattern expression expected"); + if(lhs_type.id() == ID_struct) + { + auto &struct_type = to_struct_type(lhs_type); + auto &components = struct_type.components(); + + if( + !rhs.operands().empty() && + rhs.operands().front().id() == ID_member_initializer) + { + exprt::operandst initializers{components.size(), nil_exprt{}}; + + for(auto &op : rhs.operands()) + { + PRECONDITION(op.id() == ID_member_initializer); + auto member_name = op.get(ID_member_name); + if(!struct_type.has_component(member_name)) + { + throw errort().with_location(op.source_location()) + << "struct does not have a member `" << member_name << "'"; + } + auto nr = struct_type.component_number(member_name); + auto value = to_unary_expr(op).op(); + // rec. call + assignment_conversion(value, components[nr].type()); + initializers[nr] = std::move(value); + } + + // Is every member covered? + for(std::size_t i = 0; i < components.size(); i++) + if(initializers[i].is_nil()) + { + throw errort().with_location(rhs.source_location()) + << "assignment pattern does not assign member `" + << components[i].get_name() << "'"; + } + + rhs = struct_exprt{std::move(initializers), struct_type} + .with_source_location(rhs.source_location()); + } + else + { + if(rhs.operands().size() != components.size()) + { + throw errort().with_location(rhs.source_location()) + << "number of expressions does not match number of struct members"; + } + + for(std::size_t i = 0; i < components.size(); i++) + { + // rec. call + assignment_conversion(rhs.operands()[i], components[i].type()); + } + + // turn into struct expression + rhs.id(ID_struct); + rhs.type() = lhs_type; + } + + return; + } + else if(lhs_type.id() == ID_array) + { + auto &array_type = to_array_type(lhs_type); + auto &element_type = array_type.element_type(); + auto array_size = + numeric_cast_v(to_constant_expr(array_type.size())); + + if(array_size != rhs.operands().size()) + { + throw errort().with_location(rhs.source_location()) + << "number of expressions does not match number of array elements"; + } + + for(std::size_t i = 0; i < array_size; i++) + { + // rec. call + assignment_conversion(rhs.operands()[i], element_type); + } + + // turn into array expression + rhs.id(ID_array); + rhs.type() = lhs_type; + return; + } + else + { + throw errort().with_location(rhs.source_location()) + << "cannot convert assignment pattern to '" << to_string(lhs_type) + << '\''; + } + } + // Implements 1800-2017 10.7 // If the RHS is smaller than the LHS: // * if the RHS is unsigned, it is zero-padded diff --git a/src/verilog/verilog_typecheck_expr.cpp b/src/verilog/verilog_typecheck_expr.cpp index 1c9d3f30e..50be4866d 100644 --- a/src/verilog/verilog_typecheck_expr.cpp +++ b/src/verilog/verilog_typecheck_expr.cpp @@ -2191,102 +2191,6 @@ void verilog_typecheck_exprt::implicit_typecast( return; } } - else if(src_type.id() == ID_verilog_assignment_pattern) - { - DATA_INVARIANT( - expr.id() == ID_verilog_assignment_pattern, - "verilog_assignment_pattern expression expected"); - if(dest_type.id() == ID_struct) - { - auto &struct_type = to_struct_type(dest_type); - auto &components = struct_type.components(); - - if( - !expr.operands().empty() && - expr.operands().front().id() == ID_member_initializer) - { - exprt::operandst initializers{components.size(), nil_exprt{}}; - - for(auto &op : expr.operands()) - { - PRECONDITION(op.id() == ID_member_initializer); - auto member_name = op.get(ID_member_name); - if(!struct_type.has_component(member_name)) - { - throw errort().with_location(op.source_location()) - << "struct does not have a member `" << member_name << "'"; - } - auto nr = struct_type.component_number(member_name); - auto value = to_unary_expr(op).op(); - // rec. call - implicit_typecast(value, components[nr].type()); - initializers[nr] = std::move(value); - } - - // Is every member covered? - for(std::size_t i = 0; i < components.size(); i++) - if(initializers[i].is_nil()) - { - throw errort().with_location(expr.source_location()) - << "assignment pattern does not assign member `" - << components[i].get_name() << "'"; - } - - expr = struct_exprt{std::move(initializers), struct_type} - .with_source_location(expr.source_location()); - } - else - { - if(expr.operands().size() != components.size()) - { - throw errort().with_location(expr.source_location()) - << "number of expressions does not match number of struct members"; - } - - for(std::size_t i = 0; i < components.size(); i++) - { - // rec. call - implicit_typecast(expr.operands()[i], components[i].type()); - } - - // turn into struct expression - expr.id(ID_struct); - expr.type() = dest_type; - } - - return; - } - else if(dest_type.id() == ID_array) - { - auto &array_type = to_array_type(dest_type); - auto &element_type = array_type.element_type(); - auto array_size = - numeric_cast_v(to_constant_expr(array_type.size())); - - if(array_size != expr.operands().size()) - { - throw errort().with_location(expr.source_location()) - << "number of expressions does not match number of array elements"; - } - - for(std::size_t i = 0; i < array_size; i++) - { - // rec. call - implicit_typecast(expr.operands()[i], element_type); - } - - // turn into array expression - expr.id(ID_array); - expr.type() = dest_type; - return; - } - else - { - throw errort().with_location(expr.source_location()) - << "cannot convert assignment pattern to '" << to_string(dest_type) - << '\''; - } - } else if(src_type.id() == ID_verilog_real) { if(