Changeset fc1a3e2 for src/Validate
- Timestamp:
- Apr 19, 2024, 2:36:52 PM (4 months ago)
- Branches:
- master
- Children:
- ba97ebf
- Parents:
- b9b6efb
- Location:
- src/Validate
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Validate/ForallPointerDecay.hpp
rb9b6efb rfc1a3e2 39 39 /// Expand all traits in an assertion list. 40 40 std::vector<ast::ptr<ast::DeclWithType>> expandAssertions( 41 41 std::vector<ast::ptr<ast::DeclWithType>> const & ); 42 42 43 43 } -
src/Validate/HoistStruct.cpp
rb9b6efb rfc1a3e2 149 149 template<typename InstType> 150 150 InstType const * HoistStructCore::preCollectionInstType( InstType const * type ) { 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 151 if ( !type->base->parent ) return type; 152 if ( type->base->params.empty() ) return type; 153 154 InstType * mut = ast::mutate( type ); 155 ast::AggregateDecl const * parent = 156 commonParent( this->parent, mut->base->parent ); 157 assert( parent ); 158 159 std::vector<ast::ptr<ast::Expr>> args; 160 for ( const ast::ptr<ast::TypeDecl> & param : parent->params ) { 161 args.emplace_back( new ast::TypeExpr( param->location, 162 new ast::TypeInstType( param ) 163 ) ); 164 } 165 spliceBegin( mut->params, args ); 166 return mut; 167 167 } 168 168 -
src/Validate/ImplementEnumFunc.cpp
rb9b6efb rfc1a3e2 8 8 namespace { 9 9 class EnumAttrFuncGenerator { 10 const ast::EnumDecl* decl; 11 const ast::EnumInstType* instType; 12 // const ast::EnumAttrType* attrType; 13 unsigned int functionNesting; 14 ast::Linkage::Spec proto_linkage; 15 16 public: 17 std::list<ast::ptr<ast::Decl>> forwards; 18 std::list<ast::ptr<ast::Decl>> definitions; 19 20 void generateAndAppendFunctions(std::list<ast::ptr<ast::Decl>>&); 21 22 EnumAttrFuncGenerator(const ast::EnumDecl* decl, 23 const ast::EnumInstType* instType, 24 // const ast::EnumAttrType* enumAttrType, 25 unsigned int functionNesting) 26 : decl(decl), 27 instType{instType}, 28 // attrType{enumAttrType}, 29 functionNesting{functionNesting}, 30 proto_linkage{ast::Linkage::Cforall} {} 31 32 void genAttrFunctions(); 33 void genSuccPredPosn(); 34 void genSuccPredDecl(); 35 36 void appendReturnThis(ast::FunctionDecl* decl) { 37 assert(1 <= decl->params.size()); 38 assert(1 == decl->returns.size()); 39 assert(decl->stmts); 40 41 const CodeLocation& location = (decl->stmts->kids.empty()) 42 ? decl->stmts->location 43 : decl->stmts->kids.back()->location; 44 const ast::DeclWithType* thisParam = decl->params.front(); 45 decl->stmts.get_and_mutate()->push_back(new ast::ReturnStmt( 46 location, new ast::VariableExpr(location, thisParam))); 47 } 48 void genAttrStandardFuncs() { 49 ast::FunctionDecl* (EnumAttrFuncGenerator::*standardProtos[4])() 50 const = {&EnumAttrFuncGenerator::genCtorProto, 51 &EnumAttrFuncGenerator::genCopyProto, 52 &EnumAttrFuncGenerator::genDtorProto, 53 &EnumAttrFuncGenerator::genAssignProto}; 54 for (auto& generator : standardProtos) { 55 ast::FunctionDecl* decl = (this->*generator)(); 56 produceForwardDecl(decl); 57 genFuncBody(decl); 58 if (CodeGen::isAssignment(decl->name)) { 59 appendReturnThis(decl); 60 } 61 produceDecl(decl); 62 } 63 } 64 65 private: 66 const CodeLocation& getLocation() const { return decl->location; } 67 68 ast::FunctionDecl* genProto( 69 std::string&& name, std::vector<ast::ptr<ast::DeclWithType>>&& params, 70 std::vector<ast::ptr<ast::DeclWithType>>&& returns) const; 71 72 void produceDecl(const ast::FunctionDecl* decl); 73 void produceForwardDecl(const ast::FunctionDecl* decl); 74 75 const ast::Decl* getDecl() const { return decl; } 76 77 ast::FunctionDecl* genPosnProto() const; 78 ast::FunctionDecl* genLabelProto() const; 79 ast::FunctionDecl* genValueProto() const; 80 ast::FunctionDecl* genSuccProto() const; 81 ast::FunctionDecl* genPredProto() const; 82 83 ast::FunctionDecl* genSuccPosProto() const; 84 ast::FunctionDecl* genPredPosProto() const; 85 86 // --------------------------------------------------- 87 // ast::FunctionDecl* genAttrCtorProto() const; 88 /// Changes the node inside a pointer so that it has the unused attribute. 89 void addUnusedAttribute(ast::ptr<ast::DeclWithType>& declPtr) { 90 ast::DeclWithType* decl = declPtr.get_and_mutate(); 91 decl->attributes.push_back(new ast::Attribute("unused")); 92 } 93 94 ast::ObjectDecl* dstParam() const { 95 return new ast::ObjectDecl(getLocation(), "_dst", 96 new ast::ReferenceType(new ast::EnumAttrType( 97 ast::deepCopy(instType)))); 98 } 99 100 ast::ObjectDecl* srcParam() const { 101 return new ast::ObjectDecl( 102 getLocation(), "_src", 103 new ast::EnumAttrType(ast::deepCopy(instType))); 104 } 105 106 /// E = EnumAttrType<T>` 107 /// `void ?{}(E & _dst)`. 108 ast::FunctionDecl* genCtorProto() const { 109 return genProto("?{}", {dstParam()}, {}); 110 } 111 112 /// void ?{}(E & _dst, E _src)`. 113 ast::FunctionDecl* genCopyProto() const { 114 return genProto("?{}", {dstParam(), srcParam()}, {}); 115 } 116 117 ///`void ^?{}(E & _dst)`. 118 ast::FunctionDecl* genDtorProto() const { 119 // The destructor must be mutex on a concurrent type. 120 return genProto("^?{}", {dstParam()}, {}); 121 } 122 123 /// `E ?{}(E & _dst, E _src)`. 124 ast::FunctionDecl* genAssignProto() const { 125 // Only the name is different, so just reuse the generation function. 126 auto retval = srcParam(); 127 retval->name = "_ret"; 128 return genProto("?=?", {dstParam(), srcParam()}, {retval}); 129 } 130 131 void genFuncBody(ast::FunctionDecl* func) { 132 const CodeLocation& location = func->location; 133 auto& params = func->params; 134 if (InitTweak::isCopyConstructor(func) || 135 InitTweak::isAssignment(func)) { 136 assert(2 == params.size()); 137 auto dstParam = params.front().strict_as<ast::ObjectDecl>(); 138 auto srcParam = params.back().strict_as<ast::ObjectDecl>(); 139 func->stmts = genCopyBody(location, dstParam, srcParam); 140 } else { 141 assert(1 == params.size()); 142 // Default constructor and destructor is empty. 143 func->stmts = new ast::CompoundStmt(location); 144 // Add unused attribute to parameter to silence warnings. 145 addUnusedAttribute(params.front()); 146 147 // Just an extra step to make the forward and declaration match. 148 if (forwards.empty()) return; 149 ast::FunctionDecl* fwd = strict_dynamic_cast<ast::FunctionDecl*>( 150 forwards.back().get_and_mutate()); 151 addUnusedAttribute(fwd->params.front()); 152 } 153 } 154 155 const ast::CompoundStmt* genCopyBody(const CodeLocation& location, 156 const ast::ObjectDecl* dstParam, 157 const ast::ObjectDecl* srcParam) { 158 return new ast::CompoundStmt( 159 location, 160 {new ast::ExprStmt( 161 location, 162 new ast::UntypedExpr( 163 location, new ast::NameExpr(location, "__builtin_memcpy"), 164 { 165 new ast::AddressExpr(location, new ast::VariableExpr( 166 location, dstParam)), 167 new ast::AddressExpr(location, new ast::VariableExpr( 168 location, srcParam)), 169 new ast::SizeofExpr(location, srcParam->type), 170 }))}); 171 } 172 173 void genDtorBody(ast::FunctionDecl* func) { 174 const CodeLocation& location = func->location; 175 auto& params = func->params; 176 assert(1 == params.size()); 177 func->stmts = new ast::CompoundStmt(location); 178 addUnusedAttribute(params.front()); 179 180 // Just an extra step to make the forward and declaration match. 181 if (forwards.empty()) return; 182 ast::FunctionDecl* fwd = strict_dynamic_cast<ast::FunctionDecl*>( 183 forwards.back().get_and_mutate()); 184 addUnusedAttribute(fwd->params.front()); 185 } 186 187 // ast::FunctionDecl* 188 // ---------------------------------------------------- 189 190 ast::FunctionDecl* genSuccPredFunc(bool succ); 191 192 const ast::Init* getAutoInit(const ast::Init* prev) const; 193 194 std::vector<ast::ptr<ast::Init>> genLabelInit() const; 195 196 std::vector<ast::ptr<ast::Init>> genValueInit() const; 197 ast::ObjectDecl* genAttrArrayProto( 198 const ast::EnumAttribute attr, const CodeLocation& location, 199 std::vector<ast::ptr<ast::Init>>& inits) const; 200 void genValueOrLabelBody(ast::FunctionDecl* func, 201 ast::ObjectDecl* arrDecl) const; 202 void genPosnBody(ast::FunctionDecl* func) const; 203 void genAttributesDecls(const ast::EnumAttribute attr); 10 const ast::EnumDecl* decl; 11 const ast::EnumInstType* instType; 12 unsigned int functionNesting; 13 ast::Linkage::Spec proto_linkage; 14 15 public: 16 std::list<ast::ptr<ast::Decl>> forwards; 17 std::list<ast::ptr<ast::Decl>> definitions; 18 19 void generateAndAppendFunctions(std::list<ast::ptr<ast::Decl>>&); 20 21 EnumAttrFuncGenerator( 22 const ast::EnumDecl* decl, 23 const ast::EnumInstType* instType, 24 unsigned int functionNesting ) 25 : decl(decl), 26 instType{instType}, 27 functionNesting{functionNesting}, 28 proto_linkage{ast::Linkage::Cforall} {} 29 30 void genAttrFunctions(); 31 void genSuccPredPosn(); 32 void genSuccPredDecl(); 33 34 void appendReturnThis(ast::FunctionDecl* decl) { 35 assert(1 <= decl->params.size()); 36 assert(1 == decl->returns.size()); 37 assert(decl->stmts); 38 39 const CodeLocation& location = (decl->stmts->kids.empty()) 40 ? decl->stmts->location 41 : decl->stmts->kids.back()->location; 42 const ast::DeclWithType* thisParam = decl->params.front(); 43 decl->stmts.get_and_mutate()->push_back(new ast::ReturnStmt( 44 location, new ast::VariableExpr(location, thisParam))); 45 } 46 void genAttrStandardFuncs() { 47 ast::FunctionDecl* (EnumAttrFuncGenerator::*standardProtos[4])() 48 const = {&EnumAttrFuncGenerator::genCtorProto, 49 &EnumAttrFuncGenerator::genCopyProto, 50 &EnumAttrFuncGenerator::genDtorProto, 51 &EnumAttrFuncGenerator::genAssignProto}; 52 for (auto& generator : standardProtos) { 53 ast::FunctionDecl* decl = (this->*generator)(); 54 produceForwardDecl(decl); 55 genFuncBody(decl); 56 if (CodeGen::isAssignment(decl->name)) { 57 appendReturnThis(decl); 58 } 59 produceDecl(decl); 60 } 61 } 62 63 private: 64 const CodeLocation& getLocation() const { return decl->location; } 65 66 ast::FunctionDecl* genProto( 67 std::string&& name, std::vector<ast::ptr<ast::DeclWithType>>&& params, 68 std::vector<ast::ptr<ast::DeclWithType>>&& returns) const; 69 70 void produceDecl(const ast::FunctionDecl* decl); 71 void produceForwardDecl(const ast::FunctionDecl* decl); 72 73 const ast::Decl* getDecl() const { return decl; } 74 75 ast::FunctionDecl* genPosnProto() const; 76 ast::FunctionDecl* genLabelProto() const; 77 ast::FunctionDecl* genValueProto() const; 78 ast::FunctionDecl* genSuccProto() const; 79 ast::FunctionDecl* genPredProto() const; 80 81 ast::FunctionDecl* genSuccPosProto() const; 82 ast::FunctionDecl* genPredPosProto() const; 83 84 // --------------------------------------------------- 85 // ast::FunctionDecl* genAttrCtorProto() const; 86 /// Changes the node inside a pointer so that it has the unused attribute. 87 void addUnusedAttribute(ast::ptr<ast::DeclWithType>& declPtr) { 88 ast::DeclWithType* decl = declPtr.get_and_mutate(); 89 decl->attributes.push_back(new ast::Attribute("unused")); 90 } 91 92 ast::ObjectDecl* dstParam() const { 93 return new ast::ObjectDecl(getLocation(), "_dst", 94 new ast::ReferenceType(new ast::EnumAttrType( 95 ast::deepCopy(instType)))); 96 } 97 98 ast::ObjectDecl* srcParam() const { 99 return new ast::ObjectDecl( 100 getLocation(), "_src", 101 new ast::EnumAttrType(ast::deepCopy(instType))); 102 } 103 104 /// E = EnumAttrType<T>` 105 /// `void ?{}(E & _dst)`. 106 ast::FunctionDecl* genCtorProto() const { 107 return genProto("?{}", {dstParam()}, {}); 108 } 109 110 /// void ?{}(E & _dst, E _src)`. 111 ast::FunctionDecl* genCopyProto() const { 112 return genProto("?{}", {dstParam(), srcParam()}, {}); 113 } 114 115 ///`void ^?{}(E & _dst)`. 116 ast::FunctionDecl* genDtorProto() const { 117 // The destructor must be mutex on a concurrent type. 118 return genProto("^?{}", {dstParam()}, {}); 119 } 120 121 /// `E ?{}(E & _dst, E _src)`. 122 ast::FunctionDecl* genAssignProto() const { 123 // Only the name is different, so just reuse the generation function. 124 auto retval = srcParam(); 125 retval->name = "_ret"; 126 return genProto("?=?", {dstParam(), srcParam()}, {retval}); 127 } 128 129 void genFuncBody(ast::FunctionDecl* func) { 130 const CodeLocation& location = func->location; 131 auto& params = func->params; 132 if (InitTweak::isCopyConstructor(func) || 133 InitTweak::isAssignment(func)) { 134 assert(2 == params.size()); 135 auto dstParam = params.front().strict_as<ast::ObjectDecl>(); 136 auto srcParam = params.back().strict_as<ast::ObjectDecl>(); 137 func->stmts = genCopyBody(location, dstParam, srcParam); 138 } else { 139 assert(1 == params.size()); 140 // Default constructor and destructor is empty. 141 func->stmts = new ast::CompoundStmt(location); 142 // Add unused attribute to parameter to silence warnings. 143 addUnusedAttribute(params.front()); 144 145 // Just an extra step to make the forward and declaration match. 146 if (forwards.empty()) return; 147 ast::FunctionDecl* fwd = strict_dynamic_cast<ast::FunctionDecl*>( 148 forwards.back().get_and_mutate()); 149 addUnusedAttribute(fwd->params.front()); 150 } 151 } 152 153 const ast::CompoundStmt* genCopyBody( const CodeLocation& location, 154 const ast::ObjectDecl* dstParam, const ast::ObjectDecl* srcParam) { 155 return new ast::CompoundStmt( 156 location, 157 {new ast::ExprStmt( 158 location, 159 new ast::UntypedExpr( 160 location, new ast::NameExpr(location, "__builtin_memcpy"), 161 { 162 new ast::AddressExpr( location, 163 new ast::VariableExpr( location, dstParam ) ), 164 new ast::AddressExpr( location, 165 new ast::VariableExpr( location, srcParam ) ), 166 new ast::SizeofExpr( location, srcParam->type ), 167 }))}); 168 } 169 170 void genDtorBody(ast::FunctionDecl* func) { 171 const CodeLocation& location = func->location; 172 auto& params = func->params; 173 assert(1 == params.size()); 174 func->stmts = new ast::CompoundStmt(location); 175 addUnusedAttribute(params.front()); 176 177 // Just an extra step to make the forward and declaration match. 178 if (forwards.empty()) return; 179 ast::FunctionDecl* fwd = strict_dynamic_cast<ast::FunctionDecl*>( 180 forwards.back().get_and_mutate()); 181 addUnusedAttribute(fwd->params.front()); 182 } 183 184 // ast::FunctionDecl* 185 // ---------------------------------------------------- 186 187 ast::FunctionDecl* genSuccPredFunc(bool succ); 188 189 const ast::Init* getAutoInit(const ast::Init* prev) const; 190 191 std::vector<ast::ptr<ast::Init>> genLabelInit() const; 192 193 std::vector<ast::ptr<ast::Init>> genValueInit() const; 194 ast::ObjectDecl* genAttrArrayProto( 195 const ast::EnumAttribute attr, const CodeLocation& location, 196 std::vector<ast::ptr<ast::Init>>& inits) const; 197 void genValueOrLabelBody( 198 ast::FunctionDecl* func, ast::ObjectDecl* arrDecl) const; 199 void genPosnBody(ast::FunctionDecl* func) const; 200 void genAttributesDecls(const ast::EnumAttribute attr); 204 201 }; 205 202 206 203 std::vector<ast::ptr<ast::Init>> EnumAttrFuncGenerator::genLabelInit() const { 207 208 209 210 211 212 213 214 215 216 204 std::vector<ast::ptr<ast::Init>> inits; 205 for (size_t i = 0; i < decl->members.size(); i++) { 206 ast::ptr<ast::Decl> mem = decl->members.at(i); 207 auto memAsObjectDecl = mem.as<ast::ObjectDecl>(); 208 assert(memAsObjectDecl); 209 inits.emplace_back(new ast::SingleInit( 210 mem->location, 211 ast::ConstantExpr::from_string(mem->location, mem->name))); 212 } 213 return inits; 217 214 } 218 215 219 216 std::vector<ast::ptr<ast::Init>> EnumAttrFuncGenerator::genValueInit() const { 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 217 std::vector<ast::ptr<ast::Init>> inits; 218 for (size_t i = 0; i < decl->members.size(); i++) { 219 ast::ptr<ast::Decl> mem = decl->members.at(i); 220 auto memAsObjectDecl = mem.as<ast::ObjectDecl>(); 221 assert(memAsObjectDecl); 222 if (memAsObjectDecl->init) { 223 inits.emplace_back(memAsObjectDecl->init); 224 } else { 225 const CodeLocation& location = mem->location; 226 if (i == 0) { 227 inits.emplace_back(new ast::SingleInit( 228 location, ast::ConstantExpr::from_int(mem->location, 0))); 229 } else { 230 inits.emplace_back(getAutoInit(inits.at(i - 1))); 231 } 232 } 233 } 234 return inits; 238 235 } 239 236 const ast::Init* EnumAttrFuncGenerator::getAutoInit( 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 237 const ast::Init* prev) const { 238 if (prev == nullptr) { 239 return new ast::SingleInit( 240 getLocation(), ast::ConstantExpr::from_int(getLocation(), 0)); 241 } 242 auto prevInit = dynamic_cast<const ast::SingleInit*>(prev); 243 assert(prevInit); 244 auto prevInitExpr = prevInit->value; 245 if (auto constInit = prevInitExpr.as<ast::ConstantExpr>()) { 246 // Assume no string literal for now 247 return new ast::SingleInit( 248 getLocation(), ast::ConstantExpr::from_int( 249 getLocation(), constInit->intValue() + 1)); 250 } else { 251 auto untypedThisInit = new ast::UntypedExpr( 252 getLocation(), new ast::NameExpr(getLocation(), "?++"), 253 {prevInitExpr}); 254 return new ast::SingleInit(getLocation(), untypedThisInit); 255 } 259 256 } 260 257 261 258 ast::FunctionDecl* EnumAttrFuncGenerator::genProto( 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 259 std::string&& name, std::vector<ast::ptr<ast::DeclWithType>>&& params, 260 std::vector<ast::ptr<ast::DeclWithType>>&& returns) const { 261 ast::FunctionDecl* decl = new ast::FunctionDecl( 262 // Auto-generated routines use the type declaration's location. 263 getLocation(), std::move(name), {}, {}, std::move(params), 264 std::move(returns), 265 // Only a prototype, no body. 266 nullptr, 267 // Use static storage if we are at the top level. 268 (0 < functionNesting) ? ast::Storage::Classes() : ast::Storage::Static, 269 proto_linkage, std::vector<ast::ptr<ast::Attribute>>(), 270 // Auto-generated routines are inline to avoid conflicts. 271 ast::Function::Specs(ast::Function::Inline)); 272 decl->fixUniqueId(); 273 return decl; 277 274 } 278 275 279 276 void EnumAttrFuncGenerator::produceDecl(const ast::FunctionDecl* decl) { 280 281 282 277 assert(nullptr != decl->stmts); 278 279 definitions.push_back(decl); 283 280 } 284 281 285 282 void EnumAttrFuncGenerator::produceForwardDecl(const ast::FunctionDecl* decl) { 286 287 288 289 290 283 if (0 != functionNesting) return; 284 ast::FunctionDecl* fwd = 285 (decl->stmts) ? ast::asForward(decl) : ast::deepCopy(decl); 286 fwd->fixUniqueId(); 287 forwards.push_back(fwd); 291 288 } 292 289 293 290 ast::FunctionDecl* EnumAttrFuncGenerator::genPosnProto() const { 294 295 296 297 298 291 return genProto( 292 "posE", 293 {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))}, 294 {new ast::ObjectDecl(getLocation(), "_ret", 295 new ast::BasicType(ast::BasicKind::UnsignedInt))}); 299 296 } 300 297 301 298 ast::FunctionDecl* EnumAttrFuncGenerator::genLabelProto() const { 302 303 304 305 306 307 299 return genProto( 300 "labelE", 301 {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))}, 302 {new ast::ObjectDecl( 303 getLocation(), "_ret", 304 new ast::PointerType(new ast::BasicType{ast::BasicKind::Char}))}); 308 305 } 309 306 310 307 ast::FunctionDecl* EnumAttrFuncGenerator::genValueProto() const { 311 312 313 314 315 308 return genProto( 309 "valueE", 310 {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))}, 311 {new ast::ObjectDecl(getLocation(), "_ret", 312 ast::deepCopy(decl->base))}); 316 313 } 317 314 318 315 ast::FunctionDecl* EnumAttrFuncGenerator::genSuccProto() const { 319 320 321 322 323 316 return genProto( 317 "succ", 318 {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))}, 319 {new ast::ObjectDecl(getLocation(), "_ret", 320 new ast::EnumInstType(decl))}); 324 321 } 325 322 326 323 ast::FunctionDecl* EnumAttrFuncGenerator::genPredProto() const { 327 328 329 330 331 324 return genProto( 325 "pred", 326 {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))}, 327 {new ast::ObjectDecl(getLocation(), "_ret", 328 new ast::EnumInstType(decl))}); 332 329 } 333 330 334 331 inline ast::EnumAttrType * getPosnType( const ast::EnumDecl * decl ) { 335 332 return new ast::EnumAttrType(new ast::EnumInstType(decl), ast::EnumAttribute::Posn); 336 333 } 337 334 338 335 ast::FunctionDecl* EnumAttrFuncGenerator::genSuccPosProto() const { 339 340 341 342 343 336 return genProto( 337 "_successor_", 338 {new ast::ObjectDecl(getLocation(), "_i", getPosnType(decl))}, 339 {new ast::ObjectDecl(getLocation(), "_ret", getPosnType(decl))} 340 ); 344 341 } 345 342 346 343 ast::FunctionDecl* EnumAttrFuncGenerator::genPredPosProto() const { 347 348 349 350 351 344 return genProto( 345 "_predessor_", 346 {new ast::ObjectDecl(getLocation(), "_i", getPosnType(decl))}, 347 {new ast::ObjectDecl(getLocation(), "_ret", getPosnType(decl))} 348 ); 352 349 } 353 350 354 351 ast::ObjectDecl* EnumAttrFuncGenerator::genAttrArrayProto( 355 const ast::EnumAttribute attr, const CodeLocation& location, 356 std::vector<ast::ptr<ast::Init>>& inits) const { 357 ast::ArrayType* arrT = new ast::ArrayType( 358 attr == ast::EnumAttribute::Value 359 ? decl->base 360 : new ast::PointerType(new ast::BasicType{ast::BasicKind::Char}), 361 ast::ConstantExpr::from_int(decl->location, decl->members.size()), 362 ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim); 363 364 ast::ObjectDecl* objDecl = 365 new ast::ObjectDecl(decl->location, decl->getUnmangeldArrayName(attr), 366 arrT, new ast::ListInit(location, std::move(inits)), 367 ast::Storage::Static, ast::Linkage::AutoGen); 368 369 return objDecl; 352 const ast::EnumAttribute attr, const CodeLocation& location, 353 std::vector<ast::ptr<ast::Init>>& inits) const { 354 ast::ArrayType* arrT = new ast::ArrayType( 355 attr == ast::EnumAttribute::Value 356 ? decl->base 357 : new ast::PointerType(new ast::BasicType{ast::BasicKind::Char}), 358 ast::ConstantExpr::from_int(decl->location, decl->members.size()), 359 ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim); 360 361 ast::ObjectDecl* objDecl = 362 new ast::ObjectDecl( 363 decl->location, decl->getUnmangeldArrayName( attr ), 364 arrT, new ast::ListInit( location, std::move( inits ) ), 365 ast::Storage::Static, ast::Linkage::AutoGen ); 366 367 return objDecl; 370 368 } 371 369 372 370 void EnumAttrFuncGenerator::genValueOrLabelBody( 373 374 375 376 377 378 379 new ast::VariableExpr(func->location, func->params.front()),380 new ast::EnumAttrType(new ast::EnumInstType(decl),381 382 383 371 ast::FunctionDecl* func, ast::ObjectDecl* arrDecl) const { 372 ast::UntypedExpr* untyped = ast::UntypedExpr::createCall( 373 func->location, "?[?]", 374 {new ast::NameExpr(func->location, arrDecl->name), 375 new ast::CastExpr( 376 func->location, 377 new ast::VariableExpr( func->location, func->params.front() ), 378 new ast::EnumAttrType( new ast::EnumInstType(decl), 379 ast::EnumAttribute::Posn))}); 380 func->stmts = new ast::CompoundStmt( 381 func->location, {new ast::ReturnStmt(func->location, untyped)}); 384 382 } 385 383 386 384 void EnumAttrFuncGenerator::genPosnBody(ast::FunctionDecl* func) const { 387 388 389 390 391 392 393 385 auto castExpr = new ast::CastExpr( 386 func->location, 387 new ast::VariableExpr(func->location, func->params.front()), 388 new ast::EnumAttrType(new ast::EnumInstType(decl), 389 ast::EnumAttribute::Posn)); 390 func->stmts = new ast::CompoundStmt( 391 func->location, {new ast::ReturnStmt(func->location, castExpr)}); 394 392 } 395 393 396 394 void EnumAttrFuncGenerator::genAttributesDecls(const ast::EnumAttribute attr) { 397 398 399 400 401 402 403 404 405 ast::FunctionDecl* funcProto = attr == ast::EnumAttribute::Value 406 407 408 409 410 411 412 413 414 415 416 395 if (attr == ast::EnumAttribute::Value || 396 attr == ast::EnumAttribute::Label) { 397 std::vector<ast::ptr<ast::Init>> inits = 398 attr == ast::EnumAttribute::Value ? genValueInit() : genLabelInit(); 399 ast::ObjectDecl* arrayProto = 400 genAttrArrayProto(attr, getLocation(), inits); 401 forwards.push_back(arrayProto); 402 403 ast::FunctionDecl* funcProto = ( attr == ast::EnumAttribute::Value ) 404 ? genValueProto() 405 : genLabelProto(); 406 produceForwardDecl(funcProto); 407 genValueOrLabelBody(funcProto, arrayProto); 408 produceDecl(funcProto); 409 } else { 410 ast::FunctionDecl* funcProto = genPosnProto(); 411 produceForwardDecl(funcProto); 412 genPosnBody(funcProto); 413 produceDecl(funcProto); 414 } 417 415 } 418 416 419 417 ast::FunctionDecl* EnumAttrFuncGenerator::genSuccPredFunc(bool succ) { 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 location, 445 new ast::CastExpr(location, addOneExpr, retType) 446 447 448 449 450 418 ast::FunctionDecl* funcDecl = succ ? genSuccPosProto() : genPredPosProto(); 419 produceForwardDecl(funcDecl); 420 421 const CodeLocation& location = getLocation(); 422 423 auto& params = funcDecl->params; 424 assert(params.size() == 1); 425 auto param = params.front().strict_as<ast::ObjectDecl>(); 426 427 428 auto rets = funcDecl->returns; 429 assert(params.size() == 1); 430 auto ret = rets.front().strict_as<ast::ObjectDecl>(); 431 auto retType = ret->type.strict_as<ast::EnumAttrType>(); 432 433 auto addOneExpr = ast::UntypedExpr::createCall( location, 434 succ? "?+?": "?-?", 435 {new ast::VariableExpr(location, param), 436 ast::ConstantExpr::from_int(location, 1)} 437 ); 438 439 funcDecl->stmts = new ast::CompoundStmt( 440 location, { 441 new ast::ReturnStmt( 442 location, 443 new ast::CastExpr(location, addOneExpr, retType) 444 ) 445 } 446 ); 447 448 return funcDecl; 451 449 } 452 450 453 451 void EnumAttrFuncGenerator::genAttrFunctions() { 454 455 456 457 458 452 if (decl->base) { 453 genAttributesDecls(ast::EnumAttribute::Value); 454 genAttributesDecls(ast::EnumAttribute::Label); 455 genAttributesDecls(ast::EnumAttribute::Posn); 456 } 459 457 } 460 458 461 459 void EnumAttrFuncGenerator::genSuccPredDecl() { 462 463 464 465 466 467 468 460 if (decl->base) { 461 auto succProto = genSuccProto(); 462 auto predProto = genPredProto(); 463 464 produceForwardDecl(succProto); 465 produceForwardDecl(predProto); 466 } 469 467 } 470 468 471 469 void EnumAttrFuncGenerator::genSuccPredPosn() { 472 473 474 475 476 477 478 470 if (decl->base) { 471 ast::FunctionDecl* succ = genSuccPredFunc(true); 472 ast::FunctionDecl* pred = genSuccPredFunc(false); 473 474 produceDecl(succ); 475 produceDecl(pred); 476 } 479 477 } 480 478 481 479 void EnumAttrFuncGenerator::generateAndAppendFunctions( 482 483 484 485 486 487 488 489 490 480 std::list<ast::ptr<ast::Decl>>& decls) { 481 // Generate the functions (they go into forwards and definitions). 482 genAttrStandardFuncs(); 483 genAttrFunctions(); 484 genSuccPredDecl(); 485 genSuccPredPosn(); // Posn 486 // Now export the lists contents. 487 decls.splice(decls.end(), forwards); 488 decls.splice(decls.end(), definitions); 491 489 } 492 490 493 491 // --------------------------------------------------------- 494 492 495 struct ImplementEnumFunc final : public ast::WithDeclsToAdd<>,496 497 498 499 500 501 502 503 493 struct ImplementEnumFunc final : 494 public ast::WithDeclsToAdd<>, public ast::WithShortCircuiting { 495 void previsit(const ast::EnumDecl* enumDecl); 496 void previsit(const ast::FunctionDecl* functionDecl); 497 void postvisit(const ast::FunctionDecl* functionDecl); 498 499 private: 500 // Current level of nested functions. 501 unsigned int functionNesting = 0; 504 502 }; 505 503 506 504 void ImplementEnumFunc::previsit(const ast::EnumDecl* enumDecl) { 507 508 509 510 511 512 513 514 505 if (!enumDecl->body) return; 506 if (!enumDecl->base) return; 507 508 ast::EnumInstType enumInst(enumDecl->name); 509 enumInst.base = enumDecl; 510 511 EnumAttrFuncGenerator gen(enumDecl, &enumInst, functionNesting); 512 gen.generateAndAppendFunctions(declsToAddAfter); 515 513 } 516 514 517 515 void ImplementEnumFunc::previsit(const ast::FunctionDecl*) { 518 516 functionNesting += 1; 519 517 } 520 518 521 519 void ImplementEnumFunc::postvisit(const ast::FunctionDecl*) { 522 523 } 524 525 } 520 functionNesting -= 1; 521 } 522 523 } // namespace 526 524 527 525 void implementEnumFunc(ast::TranslationUnit& translationUnit) { 528 ast::Pass<ImplementEnumFunc>::run(translationUnit); 529 } 530 } // namespace Validate 526 ast::Pass<ImplementEnumFunc>::run(translationUnit); 527 } 528 529 } // namespace Validate
Note: See TracChangeset
for help on using the changeset viewer.