From: Andreas Sandberg Date: Tue, 26 Aug 2014 14:13:45 +0000 (-0400) Subject: base: Replace the internal varargs stuff with C++11 constructs X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=70176fecd1ff04;p=gem5.git base: Replace the internal varargs stuff with C++11 constructs We currently use our own home-baked support for type-safe variadic functions. This is confusing and somewhat limited (e.g., cprintf only supports a limited number of arguments). This changeset converts all uses of our internal varargs support to use C++11 variadic macros. --- diff --git a/src/arch/generic/debugfaults.hh b/src/arch/generic/debugfaults.hh index c42f87c25..fcfdfb9e1 100644 --- a/src/arch/generic/debugfaults.hh +++ b/src/arch/generic/debugfaults.hh @@ -112,8 +112,9 @@ template class M5VarArgsFault : public M5DebugFault { public: - M5VarArgsFault(const std::string &format, CPRINTF_DECLARATION) : - M5DebugFault((DebugFunc)Func, csprintf(format, VARARGS_ALLARGS)) + template + M5VarArgsFault(const std::string &format, const Args &...args) : + M5DebugFault((DebugFunc)Func, csprintf(format, args...)) {} }; diff --git a/src/arch/x86/bios/intelmp.cc b/src/arch/x86/bios/intelmp.cc index 645c51b36..c907a63fe 100644 --- a/src/arch/x86/bios/intelmp.cc +++ b/src/arch/x86/bios/intelmp.cc @@ -92,7 +92,7 @@ writeOutString(PortProxy& proxy, Addr addr, string str, int length) if (str.length() > length) { memcpy(cleanedString, str.c_str(), length); warn("Intel MP configuration table string \"%s\" " - "will be truncated to \"%s\".\n", str, cleanedString); + "will be truncated to \"%s\".\n", str, (char *)&cleanedString); } else { memcpy(cleanedString, str.c_str(), str.length()); memset(cleanedString + str.length(), 0, length - str.length()); diff --git a/src/base/cprintf.hh b/src/base/cprintf.hh index e702fa3a6..94a74728d 100644 --- a/src/base/cprintf.hh +++ b/src/base/cprintf.hh @@ -1,4 +1,5 @@ /* + * Copyright (c) 2014 ARM Limited * Copyright (c) 2002-2006 The Regents of The University of Michigan * All rights reserved. * @@ -27,6 +28,7 @@ * * Authors: Nathan Binkert * Steve Reinhardt + * Andreas Sandberg */ #ifndef __BASE_CPRINTF_HH__ @@ -38,13 +40,9 @@ #include #include "base/cprintf_formats.hh" -#include "base/varargs.hh" namespace cp { -#define CPRINTF_DECLARATION VARARGS_DECLARATION(cp::Print) -#define CPRINTF_DEFINITION VARARGS_DEFINITION(cp::Print) - struct Print { protected: @@ -128,33 +126,42 @@ struct Print } // namespace cp -typedef VarArgs::List CPrintfArgsList; - inline void -ccprintf(std::ostream &stream, const char *format, const CPrintfArgsList &args) +ccprintf(cp::Print &print) { - cp::Print print(stream, format); - args.add_args(print); + print.end_args(); } -inline void -ccprintf(std::ostream &stream, const char *format, CPRINTF_DECLARATION) + +template void +ccprintf(cp::Print &print, const T &value, const Args &...args) +{ + print.add_arg(value); + + ccprintf(print, args...); +} + + +template void +ccprintf(std::ostream &stream, const char *format, const Args &...args) { cp::Print print(stream, format); - VARARGS_ADDARGS(print); + + ccprintf(print, args...); } -inline void -cprintf(const char *format, CPRINTF_DECLARATION) + +template void +cprintf(const char *format, const Args &...args) { - ccprintf(std::cout, format, VARARGS_ALLARGS); + ccprintf(std::cout, format, args...); } -inline std::string -csprintf(const char *format, CPRINTF_DECLARATION) +template std::string +csprintf(const char *format, const Args &...args) { std::stringstream stream; - ccprintf(stream, format, VARARGS_ALLARGS); + ccprintf(stream, format, args...); return stream.str(); } @@ -163,31 +170,22 @@ csprintf(const char *format, CPRINTF_DECLARATION) * time converting const char * to std::string since we don't take * advantage of it. */ -inline void -ccprintf(std::ostream &stream, const std::string &format, - const CPrintfArgsList &args) -{ - ccprintf(stream, format.c_str(), args); -} - -inline void -ccprintf(std::ostream &stream, const std::string &format, CPRINTF_DECLARATION) +template void +ccprintf(std::ostream &stream, const std::string &format, const Args &...args) { - ccprintf(stream, format.c_str(), VARARGS_ALLARGS); + ccprintf(stream, format.c_str(), args...); } -inline void -cprintf(const std::string &format, CPRINTF_DECLARATION) +template void +cprintf(const std::string &format, const Args &...args) { - ccprintf(std::cout, format.c_str(), VARARGS_ALLARGS); + ccprintf(std::cout, format.c_str(), args...); } -inline std::string -csprintf(const std::string &format, CPRINTF_DECLARATION) +template std::string +csprintf(const std::string &format, const Args &...args) { - std::stringstream stream; - ccprintf(stream, format.c_str(), VARARGS_ALLARGS); - return stream.str(); + return csprintf(format.c_str(), args...); } #endif // __CPRINTF_HH__ diff --git a/src/base/misc.cc b/src/base/misc.cc index 1a8b8ff1e..d95c2ff53 100644 --- a/src/base/misc.cc +++ b/src/base/misc.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2014 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2002-2005 The Regents of The University of Michigan * All rights reserved. * @@ -26,10 +38,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Nathan Binkert + * Andreas Sandberg */ #include -#include +#include #include #include "base/cprintf.hh" @@ -38,7 +51,6 @@ #include "base/output.hh" #include "base/trace.hh" #include "base/types.hh" -#include "base/varargs.hh" #include "sim/core.hh" using namespace std; @@ -51,34 +63,32 @@ bool warn_verbose = false; bool info_verbose = false; bool hack_verbose = false; -void -__exit_message(const char *prefix, int code, - const char *func, const char *file, int line, - const char *fmt, CPRINTF_DEFINITION) +static void +newline_if_needed(std::ostream &stream, const char *format) { - CPrintfArgsList args(VARARGS_ALLARGS); + const size_t format_len(strlen(format)); - string format = prefix; - format += ": "; - format += fmt; - switch (format[format.size() - 1]) { + switch (format_len ? format[format_len - 1] : '\0') { case '\n': case '\r': break; default: - format += "\n"; + stream << std::endl; } +} - format += " @ tick %d\n[%s:%s, line %d]\n"; - format += "Memory Usage: %ld KBytes\n"; - - args.push_back(curTick()); - args.push_back(func); - args.push_back(file); - args.push_back(line); - args.push_back(memUsage()); +void +__exit_epilogue(int code, + const char *func, const char *file, int line, + const char *format) +{ + newline_if_needed(std::cerr, format); - ccprintf(cerr, format.c_str(), args); + ccprintf(std::cerr, + " @ tick %d\n" + "[%s:%s, line %d]\n" + "Memory Usage: %ld KBytes\n", + curTick(), func, file, line, memUsage()); if (code < 0) abort(); @@ -87,30 +97,14 @@ __exit_message(const char *prefix, int code, } void -__base_message(std::ostream &stream, const char *prefix, bool verbose, - const char *func, const char *file, int line, - const char *fmt, CPRINTF_DEFINITION) +__base_message_epilogue(std::ostream &stream, bool verbose, + const char *func, const char *file, int line, + const char *format) { - CPrintfArgsList args(VARARGS_ALLARGS); - - string format = prefix; - format += ": "; - format += fmt; - switch (format[format.size() - 1]) { - case '\n': - case '\r': - break; - default: - format += "\n"; - } + newline_if_needed(stream, format); if (verbose) { - format += " @ cycle %d\n[%s:%s, line %d]\n"; - args.push_back(curTick()); - args.push_back(func); - args.push_back(file); - args.push_back(line); + ccprintf(stream, " @ cycle %d\n[%s:%s, line %d]\n", + curTick(), func, file, line); } - - ccprintf(stream, format.c_str(), args); } diff --git a/src/base/misc.hh b/src/base/misc.hh index de44dc3f5..23ecf736b 100644 --- a/src/base/misc.hh +++ b/src/base/misc.hh @@ -39,40 +39,58 @@ * * Authors: Nathan Binkert * Dave Greene + * Andreas Sandberg */ #ifndef __BASE_MISC_HH__ #define __BASE_MISC_HH__ +#include + #include "base/compiler.hh" #include "base/cprintf.hh" -#include "base/varargs.hh" #if defined(__SUNPRO_CC) #define __FUNCTION__ "how to fix me?" #endif +void __exit_epilogue(int code, + const char *func, const char *file, int line, + const char *format) M5_ATTR_NORETURN; + // General exit message, these functions will never return and will // either abort() if code is < 0 or exit with the code if >= 0 -void __exit_message(const char *prefix, int code, - const char *func, const char *file, int line, - const char *format, CPRINTF_DECLARATION) M5_ATTR_NORETURN; +template void +__exit_message(const char *prefix, int code, + const char *func, const char *file, int line, + const char *format, const Args &...args) M5_ATTR_NORETURN; +template void +__exit_message(const char *prefix, int code, + const char *func, const char *file, int line, + const std::string &format, const Args &...args) M5_ATTR_NORETURN; + +template void +__exit_message(const char *prefix, int code, + const char *func, const char *file, int line, + const char *format, const Args &...args) +{ + std::cerr << prefix << ": "; + ccprintf(std::cerr, format, args...); -void __exit_message(const char *prefix, int code, - const char *func, const char *file, int line, - const std::string &format, CPRINTF_DECLARATION) M5_ATTR_NORETURN; + __exit_epilogue(code, func, file, line, format); +} -inline void +template void __exit_message(const char *prefix, int code, - const char *func, const char *file, int line, - const std::string& format, CPRINTF_DEFINITION) + const char *func, const char *file, int line, + const std::string &format, const Args &...args) { __exit_message(prefix, code, func, file, line, format.c_str(), - VARARGS_ALLARGS); + args...); } -#define exit_message(prefix, code, ...) \ - __exit_message(prefix, code, __FUNCTION__, __FILE__, __LINE__, \ +#define exit_message(prefix, code, ...) \ + __exit_message(prefix, code, __FUNCTION__, __FILE__, __LINE__, \ __VA_ARGS__) // @@ -125,17 +143,28 @@ __exit_message(const char *prefix, int code, void +__base_message_epilogue(std::ostream &stream, bool verbose, + const char *func, const char *file, int line, + const char *format); + +template void __base_message(std::ostream &stream, const char *prefix, bool verbose, - const char *func, const char *file, int line, - const char *format, CPRINTF_DECLARATION); + const char *func, const char *file, int line, + const char *format, const Args &...args) +{ + stream << prefix << ": "; + ccprintf(stream, format, args...); + + __base_message_epilogue(stream, verbose, func, file, line, format); +} -inline void +template void __base_message(std::ostream &stream, const char *prefix, bool verbose, - const char *func, const char *file, int line, - const std::string &format, CPRINTF_DECLARATION) + const char *func, const char *file, int line, + const std::string &format, const Args &...args) { __base_message(stream, prefix, verbose, func, file, line, format.c_str(), - VARARGS_ALLARGS); + args...); } #define base_message(stream, prefix, verbose, ...) \ diff --git a/src/base/trace.cc b/src/base/trace.cc index fa55e42a9..00a4c3e6b 100644 --- a/src/base/trace.cc +++ b/src/base/trace.cc @@ -38,7 +38,6 @@ #include "base/output.hh" #include "base/str.hh" #include "base/trace.hh" -#include "base/varargs.hh" using namespace std; @@ -70,59 +69,35 @@ setOutput(const string &filename) ObjectMatch ignore; -void -dprintf(Tick when, const std::string &name, const char *format, - CPRINTF_DEFINITION) + +bool +__dprintf_prologue(Tick when, const std::string &name) { if (!name.empty() && ignore.match(name)) - return; + return false; std::ostream &os = *dprintf_stream; - string fmt = ""; - CPrintfArgsList args(VARARGS_ALLARGS); + if (when != MaxTick) + ccprintf(os, "%7d: ", when); - if (!name.empty()) { - fmt = "%s: " + fmt; - args.push_front(name); - } - - if (when != (Tick)-1) { - fmt = "%7d: " + fmt; - args.push_front(when); - } + if (!name.empty()) + os << name << ": "; - fmt += format; - - ccprintf(os, fmt.c_str(), args); - os.flush(); + return true; } void dump(Tick when, const std::string &name, const void *d, int len) { - if (!name.empty() && ignore.match(name)) - return; - - std::ostream &os = *dprintf_stream; - - string fmt = ""; - CPrintfArgsList args; - - if (!name.empty()) { - fmt = "%s: " + fmt; - args.push_front(name); - } - - if (when != (Tick)-1) { - fmt = "%7d: " + fmt; - args.push_front(when); - } - const char *data = static_cast(d); + std::ostream &os = *dprintf_stream; int c, i, j; + for (i = 0; i < len; i += 16) { - ccprintf(os, fmt, args); + if (!__dprintf_prologue(when, name)) + return; + ccprintf(os, "%08x ", i); c = len - i; if (c > 16) c = 16; diff --git a/src/base/trace.hh b/src/base/trace.hh index eb0ab9dae..3e6e37bd3 100644 --- a/src/base/trace.hh +++ b/src/base/trace.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2014 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2001-2006 The Regents of The University of Michigan * All rights reserved. * @@ -55,8 +67,20 @@ void dumpStatus(); extern ObjectMatch ignore; extern const std::string DefaultName; -void dprintf(Tick when, const std::string &name, const char *format, - CPRINTF_DECLARATION); +bool __dprintf_prologue(Tick when, const std::string &name); + +template void +dprintf(Tick when, const std::string &name, const char *format, + const Args &...args) +{ + if (!__dprintf_prologue(when, name)) + return; + + std::ostream &os(output()); + ccprintf(os, format, args...); + os.flush(); +} + void dump(Tick when, const std::string &name, const void *data, int len); } // namespace Trace diff --git a/src/base/varargs.hh b/src/base/varargs.hh deleted file mode 100644 index 87c98d006..000000000 --- a/src/base/varargs.hh +++ /dev/null @@ -1,308 +0,0 @@ -/* - * Copyright (c) 2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Nathan Binkert - */ - -#ifndef __BASE_VARARGS_HH__ -#define __BASE_VARARGS_HH__ - -#include "base/refcnt.hh" - -#define VARARGS_DECLARATION(receiver) \ - VarArgs::Argument a01 = VarArgs::Null(), \ - VarArgs::Argument a02 = VarArgs::Null(), \ - VarArgs::Argument a03 = VarArgs::Null(), \ - VarArgs::Argument a04 = VarArgs::Null(), \ - VarArgs::Argument a05 = VarArgs::Null(), \ - VarArgs::Argument a06 = VarArgs::Null(), \ - VarArgs::Argument a07 = VarArgs::Null(), \ - VarArgs::Argument a08 = VarArgs::Null(), \ - VarArgs::Argument a09 = VarArgs::Null(), \ - VarArgs::Argument a10 = VarArgs::Null(), \ - VarArgs::Argument a11 = VarArgs::Null(), \ - VarArgs::Argument a12 = VarArgs::Null(), \ - VarArgs::Argument a13 = VarArgs::Null(), \ - VarArgs::Argument a14 = VarArgs::Null(), \ - VarArgs::Argument a15 = VarArgs::Null(), \ - VarArgs::Argument a16 = VarArgs::Null() - -#define VARARGS_DEFINITION(receiver) \ - VarArgs::Argument a01, \ - VarArgs::Argument a02, \ - VarArgs::Argument a03, \ - VarArgs::Argument a04, \ - VarArgs::Argument a05, \ - VarArgs::Argument a06, \ - VarArgs::Argument a07, \ - VarArgs::Argument a08, \ - VarArgs::Argument a09, \ - VarArgs::Argument a10, \ - VarArgs::Argument a11, \ - VarArgs::Argument a12, \ - VarArgs::Argument a13, \ - VarArgs::Argument a14, \ - VarArgs::Argument a15, \ - VarArgs::Argument a16 - -#define VARARGS_ALLARGS \ - a01, a02, a03, a04, a05, a06, a07, a08, \ - a09, a10, a11, a12, a13, a14, a15, a16 - -#define VARARGS_ADDARGS(receiver) do { \ - do { \ - if (!a01) break; \ - a01.add_arg(receiver); \ - if (!a02) break; \ - a02.add_arg(receiver); \ - if (!a03) break; \ - a03.add_arg(receiver); \ - if (!a04) break; \ - a04.add_arg(receiver); \ - if (!a05) break; \ - a05.add_arg(receiver); \ - if (!a06) break; \ - a06.add_arg(receiver); \ - if (!a07) break; \ - a07.add_arg(receiver); \ - if (!a08) break; \ - a08.add_arg(receiver); \ - if (!a09) break; \ - a09.add_arg(receiver); \ - if (!a10) break; \ - a10.add_arg(receiver); \ - if (!a11) break; \ - a11.add_arg(receiver); \ - if (!a12) break; \ - a12.add_arg(receiver); \ - if (!a13) break; \ - a13.add_arg(receiver); \ - if (!a14) break; \ - a14.add_arg(receiver); \ - if (!a15) break; \ - a15.add_arg(receiver); \ - if (!a16) break; \ - a16.add_arg(receiver); \ - } while (0); \ - receiver.end_args(); \ -} while (0) - -namespace VarArgs { - -struct Null {}; - -template -struct Traits -{ - enum { enabled = true }; -}; - -template <> -struct Traits -{ - enum { enabled = false }; -}; - -template -struct Base : public RefCounted -{ - virtual void add_arg(RECV &receiver) const = 0; -}; - -template -struct Any : public Base -{ - const T &argument; - - Any(const T &arg) : argument(arg) {} - - virtual void - add_arg(RECV &receiver) const - { - receiver.add_arg(argument); - } -}; - -template -struct Any : public Base -{ - const T *argument; - - Any(const T *arg) : argument(arg) {} - - virtual void - add_arg(RECV &receiver) const - { - receiver.add_arg(argument); - } -}; - -template -struct Argument : public RefCountingPtr > -{ - typedef RefCountingPtr > Base; - - Argument() { } - Argument(const Null &null) { } - template - Argument(const T& arg) : Base(new Any(arg)) { } - template - Argument(const T* arg) : Base(new Any(arg)) { } - - void - add_arg(RECV &receiver) const - { - if (this->data) - this->data->add_arg(receiver); - } -}; - -template -class List -{ - public: - typedef VarArgs::Argument Argument; - typedef std::list list; - typedef typename list::iterator iterator; - typedef typename list::const_iterator const_iterator; - typedef typename list::size_type size_type; - - protected: - list l; - - public: - List() {} - List(Argument a01, Argument a02, Argument a03, Argument a04, - Argument a05, Argument a06, Argument a07, Argument a08, - Argument a09, Argument a10, Argument a11, Argument a12, - Argument a13, Argument a14, Argument a15, Argument a16) - { - if (!a01) return; - l.push_back(a01); - if (!a02) return; - l.push_back(a02); - if (!a03) return; - l.push_back(a03); - if (!a04) return; - l.push_back(a04); - if (!a05) return; - l.push_back(a05); - if (!a06) return; - l.push_back(a06); - if (!a07) return; - l.push_back(a07); - if (!a08) return; - l.push_back(a08); - if (!a09) return; - l.push_back(a09); - if (!a10) return; - l.push_back(a10); - if (!a11) return; - l.push_back(a11); - if (!a12) return; - l.push_back(a12); - if (!a13) return; - l.push_back(a13); - if (!a14) return; - l.push_back(a14); - if (!a15) return; - l.push_back(a15); - if (!a16) return; - l.push_back(a16); - } - - size_type size() const { return l.size(); } - bool empty() const { return l.empty(); } - - iterator begin() { return l.begin(); } - const_iterator begin() const { return l.begin(); } - - iterator end() { return l.end(); } - const_iterator end() const { return l.end(); } - - void - push_back(const Argument &arg) - { - if (arg) - l.push_back(arg); - } - - void - push_front(const Argument &arg) - { - if (arg) - l.push_front(arg); - } - - template - void - push_back(const T &arg) - { - if (Traits::enabled) - l.push_back(arg); - } - - template - void - push_front(const T &arg) - { - if (Traits::enabled) - l.push_front(arg); - } - - Argument& front() { return l.front(); } - const Argument& front() const { return l.front(); } - Argument& back() { return l.back(); } - const Argument& back() const { return l.back(); } - - void erase(iterator position) { return l.erase(position); } - void erase(iterator first, iterator last) { return l.erase(first, last); } - void clear() { return l.clear(); } - void pop_front() { return l.pop_front(); } - void pop_back() { return l.pop_back(); } - void reverse() { l.reverse(); } - - /* - * Functions specific to variable arguments - */ - void - add_args(RECV &recv) const - { - const_iterator i = l.begin(); - const_iterator end = l.end(); - while (i != end) { - i->add_arg(recv); - ++i; - } - - recv.end_args(); - } -}; - -} // namespace VarArgs - -#endif /* __BASE_VARARGS_HH__ */