scons: Use unions to prevent debug flag destruction.

When an object is a field in a union, it's the programmer's
resposibility to destroy it from the union's destructor. We can simply
neglect to do that and avoid having to use new to create the flags.

Also, we can define the flags as inline variables (a c++17 feature), and
then create a constexpr references to them. This lets us refer to debug
flags in constexpr objects, although we can't interact with them at, for
instance, construciton time or we'd lose our own constexpr-ness since
the actual object is not constexpr.

In c++20 we would hypothetically be able to use constexpr with new and
delete, but there may be additional restrictions that would make this
particular use impossible. Also this avoids leaking memory, which, even
though it's intentional, may confuse tools like valgrind.

Also, we need to ensure that all headers are included in some source
file so that they exist in the final executable, so that they show up in
the help, can be enabled/disabled, etc.

Change-Id: Ia43111d938e7af7140b1c17dd68135f426d0a1e9
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/49783
Maintainer: Gabe Black <gabe.black@gmail.com>
Reviewed-by: Jui-min Lee <fcrh@google.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Gabe Black
2021-08-30 22:43:23 -07:00
parent 1b2083fc53
commit 038bf7075a
4 changed files with 72 additions and 121 deletions

View File

@@ -373,34 +373,36 @@ Export('GTest')
# Debug Flags
#
DebugFlagInfo = collections.namedtuple('DebugFlag',
['name', 'desc', 'components', 'fmt'])
debug_flags = set()
def DebugFlagCommon(name, flags, desc, fmt):
if name == "All":
raise AttributeError('The "All" flag name is reserved')
debug_flags = env.get('DEBUG_FLAGS', [])
if any(name == flag.name for flag in debug_flags):
if name in debug_flags:
raise AttributeError(f'Flag {name} already specified')
flag = DebugFlagInfo(name, desc, flags, fmt)
env.Append(DEBUG_FLAGS=[flag])
debug_flags.add(name)
hh_file = Dir(env['BUILDDIR']).Dir('debug').File(f'{name}.hh')
gem5py_env.Command(hh_file,
[ '${GEM5PY}', '${DEBUGFLAGHH_PY}' ],
MakeAction('"${GEM5PY}" "${DEBUGFLAGHH_PY}" "${TARGET}" "${NAME}" ' \
'"${FMT}" "${COMPONENTS}"',
'"${DESC}" "${FMT}" "${COMPONENTS}"',
Transform("TRACING", 0)),
DEBUGFLAGHH_PY=build_tools.File('debugflaghh.py'),
NAME=name, FMT=('True' if fmt else 'False'),
NAME=name, DESC=desc, FMT=('True' if fmt else 'False'),
COMPONENTS=':'.join(flags))
cc_file = Dir(env['BUILDDIR']).Dir('debug').File('%s.cc' % name)
gem5py_env.Command(cc_file,
[ "${GEM5PY}", "${DEBUGFLAGCC_PY}" ],
MakeAction('"${GEM5PY}" "${DEBUGFLAGCC_PY}" "${TARGET}" "${NAME}"',
Transform("TRACING", 0)),
DEBUGFLAGCC_PY=build_tools.File('debugflagcc.py'), NAME=name)
Source(cc_file, add_tags='gem5 trace')
def DebugFlag(name, desc=None, fmt=False):
DebugFlagCommon(name, (), desc, fmt)
def CompoundFlag(name, flags, desc=None):
DebugFlagCommon(name, flags, desc, False)
def DebugFormatFlag(name, desc=None):
DebugFlag(name, desc, True)
@@ -800,25 +802,6 @@ for name,simobj in sorted(sim_objects.items()):
env.Depends(cc_file, depends + extra_deps)
Source(cc_file, add_tags='python')
#
# Handle debug flags
#
# Generate the files for the debug and debug-format flags
flag_args = []
for flag in env.get('DEBUG_FLAGS', []):
components = ":".join(c for c in flag.components)
arg = f'"{flag.name}" "{flag.desc}" "{bool(flag.fmt)}" ' \
f'"{components}"'
flag_args.append(arg)
gem5py_env.Command('debug/flags.cc',
[ "${GEM5PY}", "${DEBUGFLAGCC_PY}" ],
MakeAction('"${GEM5PY}" "${DEBUGFLAGCC_PY}" "${TARGET}" ${FLAGS}',
Transform("TRACING", 0)),
DEBUGFLAGCC_PY=build_tools.File('debugflagcc.py'),
FLAGS=' '.join(flag_args))
Source('debug/flags.cc', add_tags='gem5 trace')
# version tags
tags = \
env.Command('sim/tags.cc', None,