#include "../AST.h" #include "../ClassDecl.h" #include "../MethodDecl.h" #include "../compiler.h" #include "../utils.h" #include "CtExternal.h" #include "CtLocal.h" #include "CtObjectDescriptor.h" #include "CtRegistry.h" typedef TreeNode::TypeIter ConstTypeIter; // See "forced.cc" for CtObjectDescriptor::classHeader. CtExternal CtObjectDescriptor::interfaceHeader( "interface_header" ); CtObjectDescriptor::CtObjectDescriptor( ClassDecl &basis ) : CtDescriptor( basis ), _basis( basis ) { assert( basis.category() == Decl::Class ); assert( basis.asType()->isReference() ); } // PR638: we postpone instantiating supertype until this type is fully constructed // because otherwise it may create a cycle (the supertype // may be a template instantiation with this type as an argument) const CtType &CtObjectDescriptor::super() const { if (&_basis == ObjectDecl) return classHeader; else return basis.superClass()->cDescriptorType(); } void CtObjectDescriptor::dependHeaderFields( CtRegistry &depends ) const { depends.add( super() ); depends.add( basis.cType() ); CtDescriptor::dependHeaderFields( depends ); } bool CtObjectDescriptor::defineHeaderFields( ostream &out ) const { CtDescriptor::defineHeaderFields( out ); out << "const struct interface_header **implements;\n" << "void (* const *intf_info)();\n" << super() << " *super;\n" << "size_t size;\n" << "void (*nullifyLocalFields)(" << basis.cType() << "*);\n" << "void (*newInstance)(" << basis.cType() << " *);"; return true; } void CtObjectDescriptor::dependMembers( ClassDecl &ancestor, CtRegistry &depends ) const { // Order doesn't matter here, so the code is structured to // facilitate tail recursion optimization of the method. foriter (superMethod, ancestor.environ()->allProperDecls( Decl::Method ), EnvironIter) if (novel( ancestor, *superMethod )) { bool foundOverride = false; foriter (override, basis.environ()->allProperDecls( Decl::Method ), EnvironIter) if (superMethod->name() == override->name() && superMethod->type()->methodsConflict( override->type() )) { const MethodDecl &method = static_cast< MethodDecl & >(*override); const MethodTypeNode &type = *method.methodType(); depends.add( method.thisType()->cType() ); depends.add( type.returnType()->cType() ); foriter (param, type.paramTypes()->allTypes(), ConstTypeIter) depends.add( (*param)->cType() ); foundOverride = true; break; } assert( foundOverride ); } if (&ancestor != ObjectDecl && ancestor.superClass()) dependMembers( *ancestor.superClass(), depends ); } bool CtObjectDescriptor::defineMembers( ClassDecl &ancestor, ostream &out ) const { bool nonempty = false; // Order matters here, so the tail recursive // ordering used above is not suitable. if (&ancestor != ObjectDecl && ancestor.superClass()) nonempty |= defineMembers( *ancestor.superClass(), out ); foriter (superMethod, ancestor.environ()->allProperDecls( Decl::Method ), EnvironIter) if (novel( ancestor, *superMethod )) { bool foundOverride = false; foriter (override, basis.environ()->allProperDecls( Decl::Method ), EnvironIter) if (superMethod->name() == override->name() && superMethod->type()->methodsConflict( override->type() )) { const MethodDecl &method = static_cast< const MethodDecl & >(*override); const MethodTypeNode &type = *method.methodType(); out << type.returnType()->cType() << ' ' << "(*" << method.cMethodNameDynamic() << ")(" << method.thisType()->cType(); foriter (param, type.paramTypes()->allTypes(), ConstTypeIter) out << ", " << (*param)->cType(); out << ");\n"; foundOverride = true; nonempty = true; break; } assert( foundOverride ); } return true; } bool CtObjectDescriptor::novel( const ClassDecl &container, const Decl &method ) { // Methods that are final at the point of their first introduction // are excluded because they never require dynamic dispatch. return static_cast< ClassDecl * >(method.container()) == &container && !(method.modifiers() & (Common::Static | Common::Final)) && !method.overrides(); } // Local Variables: // c-file-style: "gnu" // End: