It's not used yet, but will be required for creating SPIR-V modules.
namespace GL {
namespace SL {
+StructOrganizer::StructOrganizer():
+ offset(-1)
+{ }
+
+void StructOrganizer::visit(StructDeclaration &strct)
+{
+ SetForScope<int> set_offset(offset, 0);
+ TraversingVisitor::visit(strct);
+}
+
+void StructOrganizer::visit(VariableDeclaration &var)
+{
+ if(offset>=0)
+ {
+ int *layout_offset = 0;
+ if(var.layout)
+ {
+ vector<Layout::Qualifier> &qualifiers = var.layout->qualifiers;
+ for(vector<Layout::Qualifier>::iterator i=qualifiers.begin(); i!=qualifiers.end(); ++i)
+ if(i->name=="offset" && i->has_value)
+ {
+ layout_offset = &i->value;
+ if(i->value>=offset)
+ offset = i->value;
+ break;
+ }
+ }
+
+ MemoryRequirementsCalculator::Result mem_reqs = MemoryRequirementsCalculator().apply(var);
+ offset += mem_reqs.alignment-1;
+ offset -= offset%mem_reqs.alignment;
+
+ if(layout_offset)
+ *layout_offset = offset;
+ else
+ {
+ if(!var.layout)
+ var.layout = new Layout;
+
+ Layout::Qualifier qual;
+ qual.name = "offset";
+ qual.has_value = true;
+ qual.value = offset;
+ var.layout->qualifiers.push_back(qual);
+ }
+
+ offset += mem_reqs.size;
+ }
+}
+
+
void LocationAllocator::apply(Module &module, const Features &features)
{
for(list<Stage>::iterator i=module.stages.begin(); i!=module.stages.end(); ++i)
namespace GL {
namespace SL {
+/** Assigns offset layout qualifiers to struct members. */
+class StructOrganizer: private TraversingVisitor
+{
+private:
+ int offset;
+
+public:
+ StructOrganizer();
+
+ void apply(Stage &s) { s.content.visit(*this); }
+
+private:
+ virtual void visit(StructDeclaration &);
+ virtual void visit(VariableDeclaration &);
+};
+
/** Assigns location and binding layout qualifiers to interface variables and
blocks. */
class LocationAllocator: private TraversingVisitor
}
+void MemoryRequirementsCalculator::visit(BasicTypeDeclaration &basic)
+{
+ if(basic.kind==BasicTypeDeclaration::BOOL)
+ {
+ r_size = 1;
+ r_alignment = 1;
+ }
+ else if(basic.kind==BasicTypeDeclaration::INT || basic.kind==BasicTypeDeclaration::FLOAT)
+ {
+ r_size = basic.size/8;
+ r_alignment = r_size;
+ }
+ else if(basic.kind==BasicTypeDeclaration::VECTOR || basic.kind==BasicTypeDeclaration::MATRIX)
+ {
+ basic.base_type->visit(*this);
+ unsigned n_elem = basic.size&0xFFFF;
+ r_size *= n_elem;
+ if(basic.kind==BasicTypeDeclaration::VECTOR)
+ r_alignment *= (n_elem==3 ? 4 : n_elem);
+ }
+ else if(basic.kind==BasicTypeDeclaration::ARRAY)
+ basic.base_type->visit(*this);
+}
+
+void MemoryRequirementsCalculator::visit(StructDeclaration &strct)
+{
+ unsigned total = 0;
+ unsigned max_align = 1;
+ for(NodeList<Statement>::iterator i=strct.members.body.begin(); i!=strct.members.body.end(); ++i)
+ {
+ r_size = 0;
+ r_alignment = 1;
+ r_offset = -1;
+ (*i)->visit(*this);
+ if(r_offset)
+ total = r_offset;
+ total += r_alignment-1;
+ total -= total%r_alignment;
+ total += r_size;
+ max_align = max(max_align, r_alignment);
+ }
+ r_size = total;
+ r_alignment = max_align;
+}
+
+void MemoryRequirementsCalculator::visit(VariableDeclaration &var)
+{
+ if(var.layout)
+ {
+ const vector<Layout::Qualifier> qualifiers = var.layout->qualifiers;
+ for(vector<Layout::Qualifier>::const_iterator i=qualifiers.begin(); (r_offset<0 && i!=qualifiers.end()); ++i)
+ if(i->name=="offset")
+ r_offset = i->value;
+ }
+
+ if(var.type_declaration)
+ var.type_declaration->visit(*this);
+ if(var.array)
+ if(const Literal *literal = dynamic_cast<const Literal *>(var.array_size.get()))
+ if(literal->value.check_type<int>())
+ r_size += r_alignment*(literal->value.value<int>()-1);
+}
+
+
set<Node *> DependencyCollector::apply(FunctionDeclaration &func)
{
func.visit(*this);
virtual void visit(VariableDeclaration &);
};
+/** Determines the size and alignment of a variable, in bytes. */
+class MemoryRequirementsCalculator: private NodeVisitor
+{
+public:
+ struct Result
+ {
+ unsigned size;
+ unsigned alignment;
+
+ Result(unsigned s, unsigned a): size(s), alignment(a) { }
+ };
+private:
+ unsigned r_size;
+ unsigned r_alignment;
+ int r_offset;
+
+public:
+ Result apply(VariableDeclaration &v) { v.visit(*this); return Result(r_size, r_alignment); }
+
+private:
+ virtual void visit(BasicTypeDeclaration &);
+ virtual void visit(StructDeclaration &);
+ virtual void visit(VariableDeclaration &);
+};
+
/** Collects dependencies of a function. This includes global variables,
interface blocks, other functions and types. */
class DependencyCollector: private TraversingVisitor