TypeDeclaration *TypeResolver::get_or_create_array_type(TypeDeclaration &type)
{
- auto i = array_types.find(&type);
+ bool extended_alignment = iface_block;
+ auto key = make_pair(&type, extended_alignment);
+ auto i = array_types.find(key);
if(i!=array_types.end())
return i->second;
array->source = INTERNAL_SOURCE;
array->name = type.name+"[]";
array->kind = BasicTypeDeclaration::ARRAY;
+ array->extended_alignment = extended_alignment;
array->base = type.name;
array->base_type = &type;
stage->content.body.insert(type_insert_point, array);
- array_types[&type] = array;
+ array_types[key] = array;
return array;
}
if(type.kind==BasicTypeDeclaration::ALIAS && type.base_type)
alias_map[&type] = type.base_type;
else if(type.kind==BasicTypeDeclaration::ARRAY && type.base_type)
- array_types[type.base_type] = &type;
+ array_types[make_pair(type.base_type, type.extended_alignment)] = &type;
stage->types.insert(make_pair(type.name, &type));
}
void TypeResolver::visit(StructDeclaration &strct)
{
stage->types.insert(make_pair(strct.name, &strct));
- TraversingVisitor::visit(strct);
+ if(strct.block_name.empty())
+ {
+ SetForScope<VariableDeclaration *> set_iface(iface_block, strct.block_declaration);
+ TraversingVisitor::visit(strct);
+ }
+ else
+ block_member_type_ins_pt = type_insert_point;
}
void TypeResolver::visit(VariableDeclaration &var)
{
resolve_type(var.type_declaration, var.type, var.array);
- if(iface_block && var.interface==iface_block->interface)
- var.interface.clear();
-}
-void TypeResolver::visit(InterfaceBlock &iface)
-{
- if(iface.members)
+ var.block_declaration = 0;
+ if(StructDeclaration *strct = dynamic_cast<StructDeclaration *>(get_ultimate_base_type(var.type_declaration)))
+ if(!strct->block_name.empty())
+ {
+ var.block_declaration = strct;
+ strct->block_declaration = &var;
+ strct->extended_alignment = true;
+
+ SetForScope<NodeList<Statement>::iterator> set_ins_pt(type_insert_point, block_member_type_ins_pt);
+ SetForScope<VariableDeclaration *> set_iface(iface_block, &var);
+ TraversingVisitor::visit(*strct);
+ }
+
+ if(iface_block)
{
- SetForScope<InterfaceBlock *> set_iface(iface_block, &iface);
- iface.members->visit(*this);
-
- StructDeclaration *strct = new StructDeclaration;
- strct->source = INTERNAL_SOURCE;
- strct->name = format("_%s_%s", iface.interface, iface.block_name);
- strct->members.body.splice(strct->members.body.begin(), iface.members->body);
- stage->content.body.insert(type_insert_point, strct);
- stage->types.insert(make_pair(strct->name, strct));
-
- iface.members = 0;
- strct->interface_block = &iface;
- iface.struct_declaration = strct;
+ if(var.interface==iface_block->interface)
+ var.interface.clear();
+ if(StructDeclaration *strct = dynamic_cast<StructDeclaration *>(var.type_declaration))
+ strct->extended_alignment = true;
}
-
- TypeDeclaration *type = iface.struct_declaration;
- if(type && iface.array)
- type = get_or_create_array_type(*type);
- r_any_resolved = (type!=iface.type_declaration);
- iface.type_declaration = type;
}
void TypeResolver::visit(FunctionDeclaration &func)
if(!declaration)
{
- const map<string, InterfaceBlock *> &blocks = stage->interface_blocks;
- auto i = blocks.find(var.name);
- if(i==blocks.end())
- {
- // Look for the variable in anonymous interface blocks.
- for(i=blocks.begin(); i!=blocks.end(); ++i)
- if(i->second->instance_name.empty() && i->second->struct_declaration)
- if(i->second->struct_declaration->members.variables.count(var.name))
- break;
- }
-
- if(i!=blocks.end())
- {
- /* The name refers to either an interface block with an instance name
- or a variable declared inside an anonymous interface block. Prepare
- new syntax tree nodes accordingly. */
- InterfaceBlockReference *iface_ref = new InterfaceBlockReference;
- iface_ref->source = var.source;
- iface_ref->line = var.line;
- iface_ref->declaration = i->second;
-
- if(i->second->instance_name.empty())
+ for(const auto &kvp: stage->interface_blocks)
+ if(kvp.second->name.find(' ')!=string::npos && kvp.second->block_declaration->members.variables.count(var.name))
{
- iface_ref->name = format("%s %s", i->second->interface, i->second->block_name);
+ /* The name refers a member of an anonymous interface block. Prepare
+ new syntax tree nodes accordingly. */
+ VariableReference *iface_ref = new VariableReference;
+ iface_ref->name = kvp.first;
+ iface_ref->source = var.source;
+ iface_ref->line = var.line;
+ iface_ref->declaration = kvp.second;
MemberAccess *memacc = new MemberAccess;
memacc->source = var.source;
memacc->member = var.name;
r_replacement_expr = memacc;
+ break;
}
- else
- {
- iface_ref->name = var.name;
- r_replacement_expr = iface_ref;
- }
- }
}
r_any_resolved |= (declaration!=var.declaration);
check_assignment_target(var.declaration);
}
-void VariableResolver::visit(InterfaceBlockReference &iface)
-{
- auto i = stage->interface_blocks.find(iface.name);
- InterfaceBlock *declaration = (i!=stage->interface_blocks.end() ? i->second : 0);
- r_any_resolved |= (declaration!=iface.declaration);
- iface.declaration = declaration;
-
- check_assignment_target(iface.declaration);
-}
-
void VariableResolver::visit(MemberAccess &memacc)
{
TraversingVisitor::visit(memacc);
auto i = current_block->variables.find(var.name);
VariableDeclaration *existing = 0;
- InterfaceBlock *block = 0;
+ VariableDeclaration *block = 0;
if(i!=current_block->variables.end())
existing = i->second;
else if(!current_block->parent)
{
- const map<string, InterfaceBlock *> &blocks = stage->interface_blocks;
+ const map<string, VariableDeclaration *> &blocks = stage->interface_blocks;
for(auto j=blocks.begin(); j!=blocks.end(); ++j)
- if(j->second->instance_name.empty() && j->second->struct_declaration)
+ if(j->second->name.find(' ')!=string::npos)
{
- map<string, VariableDeclaration *> &block_vars = j->second->struct_declaration->members.variables;
- i = block_vars.find(var.name);
- if(i!=block_vars.end())
+ const map<string, VariableDeclaration *> &block_vars = j->second->block_declaration->members.variables;
+ auto k = block_vars.find(var.name);
+ if(k!=block_vars.end())
{
- existing = i->second;
+ existing = k->second;
block = j->second;
break;
}
}
if(!existing)
+ {
current_block->variables.insert(make_pair(var.name, &var));
- else if(!current_block->parent && (block ? block->interface : existing->interface)==var.interface && existing->type==var.type && existing->array==var.array)
+ if(var.block_declaration)
+ {
+ stage->interface_blocks.insert(make_pair(format("%s %s", var.interface, var.block_declaration->block_name), &var));
+ if(var.name.find(' ')==string::npos)
+ stage->interface_blocks.insert(make_pair(var.name, &var));
+ }
+ }
+ else if(!current_block->parent && (block ? block->interface : existing->interface)==var.interface && existing->array==var.array)
{
if(existing->source==BUILTIN_SOURCE)
{
- redeclare_builtin(*existing, var);
-
- if(block)
+ if(var.block_declaration && existing->block_declaration && var.block_declaration->block_name==existing->block_declaration->block_name)
{
- redeclared_builtins.push_back(block);
- for(const auto &kvp: block->struct_declaration->members.variables)
- redeclared_builtins.push_back(kvp.second);
+ const map<string, VariableDeclaration *> &vars = var.block_declaration->members.variables;
+ const map<string, VariableDeclaration *> &existing_vars = existing->block_declaration->members.variables;
+
+ bool found_all = true;
+ for(const auto &kvp: vars)
+ {
+ auto j = existing_vars.find(kvp.first);
+ if(j!=existing_vars.end() && j->second->type==kvp.second->type && j->second->array==kvp.second->array)
+ redeclare_builtin(*j->second, *kvp.second);
+ else
+ found_all = false;
+ }
+
+ if(found_all)
+ {
+ redeclared_builtins.push_back(existing);
+ nodes_to_remove.insert(&var);
+ // The block struct will be removed during unused type removal
+ //nodes_to_remove.insert(var.block_declaration);
+ }
}
+ else if(!var.block_declaration && !existing->block_declaration && var.type==existing->type)
+ {
+ redeclare_builtin(*existing, var);
- nodes_to_remove.insert(&var);
- r_any_resolved = true;
+ if(block)
+ {
+ /* Cause the block and its members to be marked as not builtin
+ so it will be emitted in output */
+ redeclared_builtins.push_back(block);
+ for(const auto &kvp: block->block_declaration->members.variables)
+ redeclared_builtins.push_back(kvp.second);
+ }
+
+ nodes_to_remove.insert(&var);
+ r_any_resolved = true;
+ }
}
- else if(existing->array && !existing->array_size && !var.layout && !var.init_expression)
+ else if(existing->array && !existing->array_size && var.type==existing->type && !var.layout && !var.init_expression)
{
existing->array_size = var.array_size;
nodes_to_remove.insert(&var);
}
}
-void VariableResolver::visit(InterfaceBlock &iface)
-{
- string key = format("%s %s", iface.interface, iface.block_name);
- auto i = stage->interface_blocks.find(key);
- if(i!=stage->interface_blocks.end())
- {
- if(i->second->source==BUILTIN_SOURCE && iface.struct_declaration && i->second->struct_declaration)
- {
- const map<string, VariableDeclaration *> &vars = iface.struct_declaration->members.variables;
- const map<string, VariableDeclaration *> &existing_vars = i->second->struct_declaration->members.variables;
-
- bool found_all = true;
- for(const auto &kvp: vars)
- {
- auto j = existing_vars.find(kvp.first);
- if(j!=existing_vars.end() && j->second->type==kvp.second->type && j->second->array==kvp.second->array)
- redeclare_builtin(*j->second, *kvp.second);
- else
- found_all = false;
- }
-
- if(found_all)
- {
- redeclared_builtins.push_back(i->second);
- nodes_to_remove.insert(&iface);
- nodes_to_remove.insert(iface.struct_declaration);
- }
- }
- }
- else
- {
- /* Block names can be reused in different interfaces. Prepend the interface
- to the name to avoid conflicts. */
- stage->interface_blocks.insert(make_pair(key, &iface));
- if(!iface.instance_name.empty())
- stage->interface_blocks.insert(make_pair(iface.instance_name, &iface));
- }
-
- TraversingVisitor::visit(iface);
-}
-
bool ExpressionResolver::apply(Stage &s)
{
resolve(var, var.declaration->type_declaration, true);
}
-void ExpressionResolver::visit(InterfaceBlockReference &iface)
-{
- if(iface.declaration)
- resolve(iface, iface.declaration->type_declaration, true);
-}
-
void ExpressionResolver::visit(MemberAccess &memacc)
{
TraversingVisitor::visit(memacc);
{
unsigned column_count = basic->size&0xFFFF;
unsigned row_count = basic->size>>16;
+
+ vector<RefPtr<Expression> > columns;
+ columns.reserve(column_count);
+ bool changed_columns = false;
+
if(call.arguments.size()==1)
{
/* A matrix can be constructed from a single element or another
current_block->body.insert(insert_point, temporary);
// Create expressions to build each column.
- vector<RefPtr<Expression> > columns;
- columns.reserve(column_count);
for(unsigned j=0; j<column_count; ++j)
{
RefPtr<VariableReference> ref = new VariableReference;
truncate_vector(columns.back(), row_count);
}
- call.arguments.resize(column_count);
- copy(columns.begin(), columns.end(), call.arguments.begin());
-
- /* Let VariableResolver process the new nodes and finish
- resolving the constructor on the next pass. */
- r_any_resolved = true;
- return;
+ changed_columns = true;
}
else
return;
{
/* Construct a matrix from individual components in column-major
order. Arguments must align at column boundaries. */
- vector<RefPtr<Expression> > columns;
- columns.reserve(column_count);
-
vector<RefPtr<Expression> > column_args;
column_args.reserve(row_count);
unsigned column_component_count = 0;
else if(column_component_count>row_count)
// Argument alignment mismatch.
return;
+
+ changed_columns = true;
}
}
}
else
return;
+
+ if(changed_columns)
+ {
+ call.arguments.resize(column_count);
+ copy(columns.begin(), columns.end(), call.arguments.begin());
+
+ /* Let VariableResolver process the new nodes and finish
+ resolving the constructor on the next pass. */
+ r_any_resolved = true;
+ return;
+ }
}
else
return;
TraversingVisitor::visit(call);
if(call.declaration)
+ {
+ for(unsigned i=0; i<call.arguments.size(); ++i)
+ {
+ TypeDeclaration *arg_type = call.arguments[i]->type;
+ TypeDeclaration *param_type = call.declaration->parameters[i]->type_declaration;
+ BasicTypeDeclaration *arg_basic = dynamic_cast<BasicTypeDeclaration *>(arg_type);
+ BasicTypeDeclaration *param_basic = dynamic_cast<BasicTypeDeclaration *>(param_type);
+ if(arg_basic && param_basic)
+ {
+ Compatibility compat = get_compatibility(*param_basic, *arg_basic);
+ if(compat==RIGHT_CONVERTIBLE)
+ convert_to(call.arguments[i], *param_basic);
+ }
+ else if(!arg_type || !param_type || arg_type!=param_type)
+ return;
+ }
resolve(call, call.declaration->return_type_declaration, false);
+ }
else if(call.constructor)
visit_constructor(call);
}