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)
{
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. */
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;
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 &);
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)
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))
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));
}
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);
}
}
-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)
/** 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 &);
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 &);
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 &);