1 /************************************************************************ 2 ************************************************************************ 3 FAUST compiler 4 Copyright (C) 2003-2018 GRAME, Centre National de Creation Musicale 5 --------------------------------------------------------------------- 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 ************************************************************************ 20 ************************************************************************/ 21 22 #ifndef _STRUCT_MANAGER_H 23 #define _STRUCT_MANAGER_H 24 25 #include <string> 26 #include <utility> 27 #include <vector> 28 29 #include "instructions.hh" 30 31 // Describe a field memory location in the DSP structure 32 struct MemoryDesc { 33 int fIndex; // Field index 34 int fOffset; // Field offset in bytes in a mixed int/real zone 35 int fIntOffset; // Field offset in bytes in a separated int zone 36 int fRealOffset; // Field offset in bytes in a separated real zone 37 int fSize; // Field size in bytes 38 39 Typed::VarType fType; 40 MemoryDescMemoryDesc41 MemoryDesc() : fIndex(-1), fOffset(-1), fIntOffset(-1), fRealOffset(-1), fSize(-1), fType(Typed::kNoType) {} 42 MemoryDescMemoryDesc43 MemoryDesc(int index, int offset, int size, Typed::VarType type) 44 : fIndex(index), fOffset(offset), fIntOffset(-1), fRealOffset(-1), fSize(size), fType(type) {} 45 MemoryDescMemoryDesc46 MemoryDesc(int index, int offset, int int_offset, int read_offset, int size, Typed::VarType type) 47 : fIndex(index), fOffset(offset), fIntOffset(int_offset), fRealOffset(read_offset), fSize(size), fType(type) {} 48 getTypedMemoryDesc49 Typed* getTyped() 50 { 51 if (fSize > 1) { 52 return InstBuilder::genArrayTyped(InstBuilder::genBasicTyped(fType), fSize); 53 } else { 54 return InstBuilder::genBasicTyped(fType); 55 } 56 } 57 }; 58 59 /* 60 Compute all field info, the DSP size, and separate 'int' and 'real' types 61 */ 62 struct StructInstVisitor : public DispatchVisitor { 63 int fStructIntOffset; // Keep the int offset in bytes 64 int fStructRealOffset; // Keep the real offset in bytes 65 int fFieldIndex; // Keep the field index 66 MemoryDesc fDefault; 67 68 // Vector is used so that field names are ordered in 'getStructType' 69 typedef vector<pair<string, MemoryDesc> > field_table_type; 70 71 field_table_type fFieldTable; // Table: field_name, { index, offset, size, type } 72 StructInstVisitorStructInstVisitor73 StructInstVisitor() : fStructIntOffset(0), fStructRealOffset(0), fFieldIndex(0) {} 74 75 // Check if the field name exists hasFieldStructInstVisitor76 bool hasField(const string& name, Typed::VarType& type) 77 { 78 for (const auto& field : fFieldTable) { 79 if (field.first == name) { 80 type = field.second.fType; 81 return true; 82 } 83 } 84 return false; 85 } 86 87 // Return the offset of a given field in bytes getFieldOffsetStructInstVisitor88 int getFieldOffset(const string& name) 89 { 90 for (const auto& field : fFieldTable) { 91 if (field.first == name) return field.second.fOffset; 92 } 93 std::cerr << "ERROR in getFieldOffset : " << name << std::endl; 94 faustassert(false); 95 return -1; 96 } 97 98 // Return the int offset of a given field in bytes getFieldIntOffsetStructInstVisitor99 int getFieldIntOffset(const string& name) 100 { 101 for (const auto& field : fFieldTable) { 102 if (field.first == name) return field.second.fIntOffset; 103 } 104 std::cerr << "ERROR in getFieldIntOffset : " << name << std::endl; 105 faustassert(false); 106 return -1; 107 } 108 109 // Return the real offset of a given field in bytes getFieldRealOffsetStructInstVisitor110 int getFieldRealOffset(const string& name) 111 { 112 for (const auto& field : fFieldTable) { 113 if (field.first == name) return field.second.fRealOffset; 114 } 115 std::cerr << "ERROR in getFieldRealOffset : " << name << std::endl; 116 faustassert(false); 117 return -1; 118 } 119 120 // Return the index of a given field getFieldIndexStructInstVisitor121 int getFieldIndex(const string& name) 122 { 123 for (const auto& field : fFieldTable) { 124 if (field.first == name) return field.second.fIndex; 125 } 126 std::cerr << "ERROR in getFieldIndex : " << name << std::endl; 127 faustassert(false); 128 return -1; 129 } 130 131 // Return the memory description of a given field getMemoryDescStructInstVisitor132 MemoryDesc& getMemoryDesc(const string& name) 133 { 134 for (auto& field : fFieldTable) { 135 if (field.first == name) return field.second; 136 } 137 std::cerr << "ERROR in getMemoryDesc : " << name << std::endl; 138 faustassert(false); 139 return fDefault; 140 } 141 142 // Return the struct 'int' size in bytes getStructIntSizeStructInstVisitor143 int getStructIntSize() { return fStructIntOffset; } 144 145 // Return the struct 'real' size in bytes getStructRealSizeStructInstVisitor146 int getStructRealSize() { return fStructRealOffset; } 147 148 // Return the struct size in bytes getStructSizeStructInstVisitor149 int getStructSize() { return fStructIntOffset + fStructRealOffset; } 150 getFieldTableStructInstVisitor151 field_table_type& getFieldTable() { return fFieldTable; } 152 153 // Return the struct type getStructTypeStructInstVisitor154 DeclareStructTypeInst* getStructType(const string& name) 155 { 156 vector<NamedTyped*> dsp_type_fields; 157 for (auto& field : fFieldTable) { 158 // std::cout << "getStructType " << field.first << std::endl; 159 dsp_type_fields.push_back(InstBuilder::genNamedTyped(field.first, field.second.getTyped())); 160 } 161 return InstBuilder::genDeclareStructTypeInst(InstBuilder::genStructTyped(name, dsp_type_fields)); 162 } 163 164 // Declarations visitStructInstVisitor165 virtual void visit(DeclareVarInst* inst) 166 { 167 //dump2FIR(inst); 168 string name = inst->fAddress->getName(); 169 Address::AccessType access = inst->fAddress->getAccess(); 170 171 bool is_struct = (access & Address::kStruct) || (access & Address::kStaticStruct); 172 ArrayTyped* array_typed = dynamic_cast<ArrayTyped*>(inst->fType); 173 174 if (array_typed && array_typed->fSize > 1) { 175 if (is_struct) { 176 fFieldTable.push_back(make_pair(name, MemoryDesc(fFieldIndex++, 177 getStructSize(), 178 getStructIntSize(), 179 getStructRealSize(), 180 array_typed->fSize, 181 array_typed->fType->getType()))); 182 if (array_typed->fType->getType() == Typed::kInt32) { 183 fStructIntOffset += array_typed->getSize(); 184 } else { 185 fStructRealOffset += array_typed->getSize(); 186 } 187 } else { 188 // Should never happen... 189 faustassert(false); 190 } 191 } else { 192 if (is_struct) { 193 fFieldTable.push_back(make_pair(name, MemoryDesc(fFieldIndex++, 194 getStructSize(), 195 getStructIntSize(), 196 getStructRealSize(), 197 1, inst->fType->getType()))); 198 if (inst->fType->getType() == Typed::kInt32) { 199 fStructIntOffset += inst->fType->getSize(); 200 } else { 201 fStructRealOffset += inst->fType->getSize(); 202 } 203 } else { 204 // Local variables declared by [var_num, type] pairs 205 faustassert(inst->fValue == nullptr); 206 } 207 } 208 } 209 210 }; 211 212 #endif 213