scons,python: Always generate default create() methods.
We were originally generating default create() methods along side the pybind definitions, but unfortunately those are only included when python support is included. Since the SimObject Param structs are unconditionally provided even if the thing calling their create() methods is not, we need to also unconditionally provide the default create() definitions. We do that by putting them in their own new .cc files. Change-Id: I29d1573d578794b3fe7ec2bc16ef5c8c58e56d0e Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/42589 Maintainer: Gabe Black <gabe.black@gmail.com> Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Jason Lowe-Power <power.jg@gmail.com> Reviewed-by: Earl Ou <shunhsingou@google.com>
This commit is contained in:
@@ -917,7 +917,7 @@ PySource('m5', 'python/m5/info.py')
|
||||
# Create all of the SimObject param headers and enum headers
|
||||
#
|
||||
|
||||
def createSimObjectParamStruct(target, source, env):
|
||||
def createSimObjectParamDecl(target, source, env):
|
||||
assert len(target) == 1 and len(source) == 1
|
||||
|
||||
name = source[0].get_text_contents()
|
||||
@@ -927,6 +927,16 @@ def createSimObjectParamStruct(target, source, env):
|
||||
obj.cxx_param_decl(code)
|
||||
code.write(target[0].abspath)
|
||||
|
||||
def createSimObjectParamDef(target, source, env):
|
||||
assert len(target) == 1 and len(source) == 1
|
||||
|
||||
name = source[0].get_text_contents()
|
||||
obj = sim_objects[name]
|
||||
|
||||
code = code_formatter()
|
||||
obj.cxx_param_def(code)
|
||||
code.write(target[0].abspath)
|
||||
|
||||
def createSimObjectCxxConfig(is_header):
|
||||
def body(target, source, env):
|
||||
assert len(target) == 1 and len(source) == 1
|
||||
@@ -987,9 +997,16 @@ for name,simobj in sorted(sim_objects.items()):
|
||||
hh_file = File('params/%s.hh' % name)
|
||||
params_hh_files.append(hh_file)
|
||||
env.Command(hh_file, Value(name),
|
||||
MakeAction(createSimObjectParamStruct, Transform("SO PARAM")))
|
||||
MakeAction(createSimObjectParamDecl, Transform("SOPARMHH")))
|
||||
env.Depends(hh_file, depends + extra_deps)
|
||||
|
||||
if not getattr(simobj, 'abstract', False) and hasattr(simobj, 'type'):
|
||||
cc_file = File('params/%s.cc' % name)
|
||||
env.Command(cc_file, Value(name),
|
||||
MakeAction(createSimObjectParamDef, Transform("SOPARMCC")))
|
||||
env.Depends(cc_file, depends + extra_deps)
|
||||
Source(cc_file)
|
||||
|
||||
# C++ parameter description files
|
||||
if GetOption('with_cxx_config'):
|
||||
for name,simobj in sorted(sim_objects.items()):
|
||||
|
||||
@@ -368,7 +368,7 @@ def createCxxConfigDirectoryEntryFile(code, name, simobj, is_header):
|
||||
|
||||
if not is_header:
|
||||
code('{')
|
||||
if hasattr(simobj, 'abstract') and simobj.abstract:
|
||||
if getattr(simobj, 'abstract', False):
|
||||
code(' return NULL;')
|
||||
else:
|
||||
code(' return this->create();')
|
||||
@@ -700,6 +700,80 @@ class MetaSimObject(type):
|
||||
def pybind_predecls(cls, code):
|
||||
code('#include "${{cls.cxx_header}}"')
|
||||
|
||||
def cxx_param_def(cls, code):
|
||||
code('''
|
||||
#include <type_traits>
|
||||
|
||||
#include "base/compiler.hh"
|
||||
|
||||
#include "${{cls.cxx_header}}"
|
||||
#include "params/${cls}.hh"
|
||||
|
||||
''')
|
||||
code()
|
||||
code('namespace')
|
||||
code('{')
|
||||
code()
|
||||
# If we can't define a default create() method for this params struct
|
||||
# because the SimObject doesn't have the right constructor, use
|
||||
# template magic to make it so we're actually defining a create method
|
||||
# for this class instead.
|
||||
code('class Dummy${cls}ParamsClass')
|
||||
code('{')
|
||||
code(' public:')
|
||||
code(' ${{cls.cxx_class}} *create() const;')
|
||||
code('};')
|
||||
code()
|
||||
code('template <class CxxClass, class Enable=void>')
|
||||
code('class Dummy${cls}Shunt;')
|
||||
code()
|
||||
# This version directs to the real Params struct and the default
|
||||
# behavior of create if there's an appropriate constructor.
|
||||
code('template <class CxxClass>')
|
||||
code('class Dummy${cls}Shunt<CxxClass, std::enable_if_t<')
|
||||
code(' std::is_constructible<CxxClass,')
|
||||
code(' const ${cls}Params &>::value>>')
|
||||
code('{')
|
||||
code(' public:')
|
||||
code(' using Params = ${cls}Params;')
|
||||
code(' static ${{cls.cxx_class}} *')
|
||||
code(' create(const Params &p)')
|
||||
code(' {')
|
||||
code(' return new CxxClass(p);')
|
||||
code(' }')
|
||||
code('};')
|
||||
code()
|
||||
# This version diverts to the DummyParamsClass and a dummy
|
||||
# implementation of create if the appropriate constructor does not
|
||||
# exist.
|
||||
code('template <class CxxClass>')
|
||||
code('class Dummy${cls}Shunt<CxxClass, std::enable_if_t<')
|
||||
code(' !std::is_constructible<CxxClass,')
|
||||
code(' const ${cls}Params &>::value>>')
|
||||
code('{')
|
||||
code(' public:')
|
||||
code(' using Params = Dummy${cls}ParamsClass;')
|
||||
code(' static ${{cls.cxx_class}} *')
|
||||
code(' create(const Params &p)')
|
||||
code(' {')
|
||||
code(' return nullptr;')
|
||||
code(' }')
|
||||
code('};')
|
||||
code()
|
||||
code('} // anonymous namespace')
|
||||
code()
|
||||
# An implementation of either the real Params struct's create
|
||||
# method, or the Dummy one. Either an implementation is
|
||||
# mandantory since this was shunted off to the dummy class, or
|
||||
# one is optional which will override this weak version.
|
||||
code('M5_VAR_USED ${{cls.cxx_class}} *')
|
||||
code('Dummy${cls}Shunt<${{cls.cxx_class}}>::Params::create() const')
|
||||
code('{')
|
||||
code(' return Dummy${cls}Shunt<${{cls.cxx_class}}>::')
|
||||
code(' create(*this);')
|
||||
code('}')
|
||||
|
||||
|
||||
def pybind_decl(cls, code):
|
||||
py_class_name = cls.pybind_class
|
||||
|
||||
@@ -713,9 +787,6 @@ class MetaSimObject(type):
|
||||
code('''#include "pybind11/pybind11.h"
|
||||
#include "pybind11/stl.h"
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "base/compiler.hh"
|
||||
#include "params/$cls.hh"
|
||||
#include "python/pybind11/core.hh"
|
||||
#include "sim/init.hh"
|
||||
@@ -797,76 +868,6 @@ module_init(py::module_ &m_internal)
|
||||
code()
|
||||
code('static EmbeddedPyBind embed_obj("${0}", module_init, "${1}");',
|
||||
cls, cls._base.type if cls._base else "")
|
||||
if not hasattr(cls, 'abstract') or not cls.abstract:
|
||||
if 'type' in cls.__dict__:
|
||||
code()
|
||||
# This namespace can't *actually* be anonymous, or the compiler
|
||||
# gets upset about having a weak symbol init.
|
||||
code('namespace anonymous_params')
|
||||
code('{')
|
||||
code()
|
||||
# If we can't define a default create() method for this params
|
||||
# struct because the SimObject doesn't have the right
|
||||
# constructor, use template magic to make it so we're actually
|
||||
# defining a create method for this class instead.
|
||||
code('class Dummy${cls}ParamsClass')
|
||||
code('{')
|
||||
code(' public:')
|
||||
code(' ${{cls.cxx_class}} *create() const;')
|
||||
code('};')
|
||||
code()
|
||||
code('template <class CxxClass, class Enable=void>')
|
||||
code('class DummyShunt;')
|
||||
code()
|
||||
# This version directs to the real Params struct and the
|
||||
# default behavior of create if there's an appropriate
|
||||
# constructor.
|
||||
code('template <class CxxClass>')
|
||||
code('class DummyShunt<CxxClass, std::enable_if_t<')
|
||||
code(' std::is_constructible<CxxClass,')
|
||||
code(' const ${cls}Params &>::value>>')
|
||||
code('{')
|
||||
code(' public:')
|
||||
code(' using Params = ${cls}Params;')
|
||||
code(' static ${{cls.cxx_class}} *')
|
||||
code(' create(const Params &p)')
|
||||
code(' {')
|
||||
code(' return new CxxClass(p);')
|
||||
code(' }')
|
||||
code('};')
|
||||
code()
|
||||
# This version diverts to the DummyParamsClass and a dummy
|
||||
# implementation of create if the appropriate constructor does
|
||||
# not exist.
|
||||
code('template <class CxxClass>')
|
||||
code('class DummyShunt<CxxClass, std::enable_if_t<')
|
||||
code(' !std::is_constructible<CxxClass,')
|
||||
code(' const ${cls}Params &>::value>>')
|
||||
code('{')
|
||||
code(' public:')
|
||||
code(' using Params = Dummy${cls}ParamsClass;')
|
||||
code(' static ${{cls.cxx_class}} *')
|
||||
code(' create(const Params &p)')
|
||||
code(' {')
|
||||
code(' return nullptr;')
|
||||
code(' }')
|
||||
code('};')
|
||||
code()
|
||||
code('} // namespace anonymous_params')
|
||||
code()
|
||||
code('using namespace anonymous_params;')
|
||||
code()
|
||||
# A weak implementation of either the real Params struct's
|
||||
# create method, or the Dummy one if we don't want to have
|
||||
# any default implementation. Either an implementation is
|
||||
# mandantory since this was shunted off to the dummy class, or
|
||||
# one is optional which will override this weak version.
|
||||
code('M5_WEAK ${{cls.cxx_class}} *')
|
||||
code('DummyShunt<${{cls.cxx_class}}>::Params::create() const')
|
||||
code('{')
|
||||
code(' return DummyShunt<${{cls.cxx_class}}>::')
|
||||
code(' create(*this);')
|
||||
code('}')
|
||||
|
||||
_warned_about_nested_templates = False
|
||||
|
||||
|
||||
Reference in New Issue
Block a user