#define __SIM_GUEST_ABI_HH__
#include <functional>
-#include <memory>
-#include <sstream>
-#include <type_traits>
-class ThreadContext;
-
-namespace GuestABI
-{
-
-/*
- * To implement an ABI, a subclass needs to implement a system of
- * specializations of these two templates Result and Argument, and define a
- * "Position" type.
- *
- * The Position type carries information about, for instance, how many
- * integer registers have been consumed gathering earlier arguments. It
- * may contain multiple elements if there are multiple dimensions to track,
- * for instance the number of integer and floating point registers used so far.
- *
- * Result and Argument are class templates instead of function templates so
- * that they can be partially specialized if necessary. C++ doesn't let you
- * partially specialize function templates because that conflicts with
- * template resolution using the function's arguments. Since we already know
- * what type we want and we don't need argument based resolution, we can just
- * wrap the desired functionality in classes and sidestep the problem.
- *
- * Also note that these templates have an "Enabled" parameter to support
- * std::enable_if style conditional specializations.
- */
-
-/*
- * Position may need to be initialized based on the ThreadContext, for instance
- * to find out where the stack pointer is initially.
- */
-template <typename ABI, typename Enabled=void>
-struct PositionInitializer
-{
- static typename ABI::Position
- init(const ThreadContext *tc)
- {
- return typename ABI::Position();
- }
-};
-
-template <typename ABI>
-struct PositionInitializer<ABI, typename std::enable_if<
- std::is_constructible<typename ABI::Position, const ThreadContext *>::value
- >::type>
-{
- static typename ABI::Position
- init(const ThreadContext *tc)
- {
- return typename ABI::Position(tc);
- }
-};
-
-template <typename ABI, typename Ret, typename Enabled=void>
-struct Result
-{
- private:
- /*
- * Store result "ret" into the state accessible through tc.
- *
- * Note that the declaration below is only to document the expected
- * signature and is private so it won't be used by accident.
- * Specializations of this Result class should define their own version
- * of this method which actually does something and is public.
- */
- static void store(ThreadContext *tc, const Ret &ret);
-
- /*
- * Adjust the position of arguments based on the return type, if necessary.
- *
- * This method can be excluded if no adjustment is necessary.
- */
- static void allocate(ThreadContext *tc, typename ABI::Position &position);
-};
-
-/*
- * This partial specialization prevents having to special case 'void' when
- * working with return types.
- */
-template <typename ABI>
-struct Result<ABI, void>
-{};
-
-template <typename ABI, typename Arg, typename Enabled=void>
-struct Argument
-{
- /*
- * Retrieve an argument of type Arg from the state accessible through tc,
- * assuming the state represented by "position" has already been used.
- * Also update position to account for this argument as well.
- *
- * Like Result::store above, the declaration below is only to document
- * the expected method signature.
- */
- static Arg get(ThreadContext *tc, typename ABI::Position &position);
-
- /*
- * Adjust the position of arguments based on the argument type, if
- * necessary.
- *
- * This method can be excluded if no adjustment is necessary.
- */
- static void allocate(ThreadContext *tc, typename ABI::Position &position);
-};
-
-/*
- * This struct template provides a default allocate() method in case the
- * Result or Argument template doesn't provide one. This is the default in
- * cases where the return or argument type doesn't affect where things are
- * stored.
- */
-template <typename ABI, template <class ...> class Role,
- typename Type, typename Enabled=void>
-struct Allocator
-{
- static void
- allocate(ThreadContext *tc, typename ABI::Position &position)
- {}
-};
-
-/*
- * If the return type is void, don't allocate anything.
- */
-template <typename ABI, template <class ...> class Role>
-struct Allocator<ABI, Role, void>
-{
- static void
- allocate(ThreadContext *tc, typename ABI::Position &position)
- {}
-};
-
-/*
- * If the return or argument type isn't void and does affect where things
- * are stored, the ABI can implement an allocate() method for the various
- * argument and/or return types, and this specialization will call into it.
- */
-template <typename ABI, template <class ...> class Role, typename Type>
-struct Allocator<ABI, Role, Type, decltype((void)&Role<ABI, Type>::allocate)>
-{
- static void
- allocate(ThreadContext *tc, typename ABI::Position &position)
- {
- Role<ABI, Type>::allocate(tc, position);
- }
-};
-
-template <typename ABI, typename Ret, typename Enabled=void>
-static void
-allocateResult(ThreadContext *tc, typename ABI::Position &position)
-{
- Allocator<ABI, Result, Ret>::allocate(tc, position);
-}
-
-template <typename ABI>
-static void
-allocateArguments(ThreadContext *tc, typename ABI::Position &position)
-{
- return;
-}
-
-template <typename ABI, typename NextArg, typename ...Args>
-static void
-allocateArguments(ThreadContext *tc, typename ABI::Position &position)
-{
- Allocator<ABI, Argument, NextArg>::allocate(tc, position);
- allocateArguments<ABI, Args...>(tc, position);
-}
-
-template <typename ABI, typename Ret, typename ...Args>
-static void
-allocateSignature(ThreadContext *tc, typename ABI::Position &position)
-{
- allocateResult<ABI, Ret>(tc, position);
- allocateArguments<ABI, Args...>(tc, position);
-}
-
-
-/*
- * These templates implement a variadic argument mechanism for guest ABI
- * functions. A function might be written like this:
- *
- * void
- * func(ThreadContext *tc, VarArgs<Addr, int> varargs)
- * {
- * warn("Address = %#x, int = %d.",
- * varargs.get<Addr>(), varargs.get<int>());
- * }
- *
- * where an object of type VarArgs<...> is its last argument. The types given
- * to the template specify what types the function might need to retrieve from
- * varargs. The varargs object will then have get<> methods for each of those
- * types.
- *
- * Note that each get<> will happen live. If you modify values through the
- * ThreadContext *tc and then run get<>(), you may alter one of your arguments.
- * If you're going to use tc to modify state, it would be a good idea to use
- * get<>() as soon as possible to avoid corrupting the functions arguments.
- */
-
-// A recursive template which defines virtual functions to retrieve each of the
-// requested types. This provides the ABI agnostic interface the function uses.
-template <typename ...Types>
-class VarArgsBase;
-
-template <typename First, typename ...Types>
-class VarArgsBase<First, Types...> : public VarArgsBase<Types...>
-{
- public:
- // The virtual function takes a reference parameter so that the different
- // _getImpl methods can co-exist through overloading.
- virtual void _getImpl(First &) = 0;
-
- // Make sure base class _getImpl-es aren't hidden by this one.
- using VarArgsBase<Types...>::_getImpl;
-};
-
-// The base case of the recursion.
-template <>
-class VarArgsBase<>
-{
- protected:
- // This just gives the "using" statement in the non base case something to
- // refer to.
- void _getImpl();
-};
-
-
-// A recursive template which defines the ABI specific implementation of the
-// interface defined above.
-//
-// The types in Types are consumed one by one, and by
-// the time we get down to the base case we'd have lost track of the complete
-// set we need to know what interface to inherit. The Base parameter keeps
-// track of that through the recursion.
-template <typename ABI, typename Base, typename ...Types>
-class VarArgsImpl;
-
-template <typename ABI, typename Base, typename First, typename ...Types>
-class VarArgsImpl<ABI, Base, First, Types...> :
- public VarArgsImpl<ABI, Base, Types...>
-{
- protected:
- // Bring forward the base class constructor.
- using VarArgsImpl<ABI, Base, Types...>::VarArgsImpl;
- // Make sure base class _getImpl-es don't get hidden by ours.
- using VarArgsImpl<ABI, Base, Types...>::_getImpl;
-
- // Implement a version of _getImple, using the ABI specialized version of
- // the Argument class.
- void
- _getImpl(First &first) override
- {
- first = Argument<ABI, First>::get(this->tc, this->position);
- }
-};
-
-// The base case of the recursion, which inherits from the interface class.
-template <typename ABI, typename Base>
-class VarArgsImpl<ABI, Base> : public Base
-{
- protected:
- // Declare state to pass to the Argument<>::get methods.
- ThreadContext *tc;
- typename ABI::Position position;
-
- // Give the "using" statement in our subclass something to refer to.
- void _getImpl();
-
- public:
- VarArgsImpl(ThreadContext *_tc, const typename ABI::Position &_pos) :
- tc(_tc), position(_pos)
- {}
-};
-
-// A wrapper which provides a nice interface to the virtual functions, and a
-// hook for the Argument template mechanism.
-template <typename ...Types>
-class VarArgs
-{
- private:
- // This points to the implementation which knows how to read arguments
- // based on the ABI being used.
- std::shared_ptr<VarArgsBase<Types...>> _ptr;
-
- public:
- VarArgs(VarArgsBase<Types...> *ptr) : _ptr(ptr) {}
-
- // This template is a friendlier wrapper around the virtual functions the
- // raw interface provides. This version lets you pick a type which it then
- // returns, instead of having to pre-declare a variable to pass in.
- template <typename Arg>
- Arg
- get()
- {
- Arg arg;
- _ptr->_getImpl(arg);
- return arg;
- }
-};
-
-template <typename T>
-struct IsVarArgs : public std::false_type {};
-
-template <typename ...Types>
-struct IsVarArgs<VarArgs<Types...>> : public std::true_type {};
-
-template <typename ...Types>
-std::ostream &
-operator << (std::ostream &os, const VarArgs<Types...> &va)
-{
- os << "...";
- return os;
-}
-
-// The ABI independent hook which tells the GuestABI mechanism what to do with
-// a VarArgs argument. It constructs the underlying implementation which knows
-// about the ABI, and installs it in the VarArgs wrapper to give to the
-// function.
-template <typename ABI, typename ...Types>
-struct Argument<ABI, VarArgs<Types...>>
-{
- static VarArgs<Types...>
- get(ThreadContext *tc, typename ABI::Position &position)
- {
- using Base = VarArgsBase<Types...>;
- using Impl = VarArgsImpl<ABI, Base, Types...>;
- return VarArgs<Types...>(new Impl(tc, position));
- }
-};
-
-
-/*
- * These functions will likely be common among all ABIs and implement the
- * mechanism of gathering arguments, calling the target function, and then
- * storing the result. They might need to be overridden if, for instance,
- * the location of arguments need to be determined in a different order.
- * For example, there might be an ABI which gathers arguments starting
- * from the last in the list instead of the first. This is unlikely but
- * still possible to support by redefining these functions..
- */
-
-// With no arguments to gather, call the target function and store the
-// result.
-template <typename ABI, typename Ret>
-static typename std::enable_if<!std::is_void<Ret>::value, Ret>::type
-callFrom(ThreadContext *tc, typename ABI::Position &position,
- std::function<Ret(ThreadContext *)> target)
-{
- Ret ret = target(tc);
- Result<ABI, Ret>::store(tc, ret);
- return ret;
-}
-
-// With no arguments to gather and nothing to return, call the target function.
-template <typename ABI>
-static void
-callFrom(ThreadContext *tc, typename ABI::Position &position,
- std::function<void(ThreadContext *)> target)
-{
- target(tc);
-}
-
-// Recursively gather arguments for target from tc until we get to the base
-// case above.
-template <typename ABI, typename Ret, typename NextArg, typename ...Args>
-static typename std::enable_if<!std::is_void<Ret>::value, Ret>::type
-callFrom(ThreadContext *tc, typename ABI::Position &position,
- std::function<Ret(ThreadContext *, NextArg, Args...)> target)
-{
- // Extract the next argument from the thread context.
- NextArg next = Argument<ABI, NextArg>::get(tc, position);
-
- // Build a partial function which adds the next argument to the call.
- std::function<Ret(ThreadContext *, Args...)> partial =
- [target,next](ThreadContext *_tc, Args... args) {
- return target(_tc, next, args...);
- };
-
- // Recursively handle any remaining arguments.
- return callFrom<ABI, Ret, Args...>(tc, position, partial);
-}
-
-// Recursively gather arguments for target from tc until we get to the base
-// case above. This version is for functions that don't return anything.
-template <typename ABI, typename NextArg, typename ...Args>
-static void
-callFrom(ThreadContext *tc, typename ABI::Position &position,
- std::function<void(ThreadContext *, NextArg, Args...)> target)
-{
- // Extract the next argument from the thread context.
- NextArg next = Argument<ABI, NextArg>::get(tc, position);
-
- // Build a partial function which adds the next argument to the call.
- std::function<void(ThreadContext *, Args...)> partial =
- [target,next](ThreadContext *_tc, Args... args) {
- target(_tc, next, args...);
- };
-
- // Recursively handle any remaining arguments.
- callFrom<ABI, Args...>(tc, position, partial);
-}
-
-
-
-/*
- * These functions are like the ones above, except they print the arguments
- * a target function would be called with instead of actually calling it.
- */
-
-// With no arguments to print, add the closing parenthesis and return.
-template <typename ABI, typename Ret>
-static void
-dumpArgsFrom(int count, std::ostream &os, ThreadContext *tc,
- typename ABI::Position &position)
-{
- os << ")";
-}
-
-// Recursively gather arguments for target from tc until we get to the base
-// case above, and append those arguments to the string stream being
-// constructed.
-template <typename ABI, typename Ret, typename NextArg, typename ...Args>
-static void
-dumpArgsFrom(int count, std::ostream &os, ThreadContext *tc,
- typename ABI::Position &position)
-{
- // Either open the parenthesis or add a comma, depending on where we are
- // in the argument list.
- os << (count ? ", " : "(");
-
- // Extract the next argument from the thread context.
- NextArg next = Argument<ABI, NextArg>::get(tc, position);
-
- // Add this argument to the list.
- os << next;
-
- // Recursively handle any remaining arguments.
- dumpArgsFrom<ABI, Ret, Args...>(count + 1, os, tc, position);
-}
-
-} // namespace GuestABI
+#include "sim/guest_abi/definition.hh"
+#include "sim/guest_abi/dispatch.hh"
+#include "sim/guest_abi/layout.hh"
+#include "sim/guest_abi/varargs.hh"
+class ThreadContext;
// These functions wrap a simulator level function with the given signature.
// The wrapper takes one argument, a thread context to extract arguments from
{
// Default construct a Position to track consumed resources. Built in
// types will be zero initialized.
- auto position = GuestABI::PositionInitializer<ABI>::init(tc);
+ auto position = GuestABI::initializePosition<ABI>(tc);
GuestABI::allocateSignature<ABI, Ret, Args...>(tc, position);
return GuestABI::callFrom<ABI, Ret, Args...>(tc, position, target);
}
{
// Default construct a Position to track consumed resources. Built in
// types will be zero initialized.
- auto position = GuestABI::PositionInitializer<ABI>::init(tc);
+ auto position = GuestABI::initializePosition<ABI>(tc);
GuestABI::allocateArguments<ABI, Args...>(tc, position);
GuestABI::callFrom<ABI, Args...>(tc, position, target);
}
std::function<Ret(ThreadContext *, Args...)> target=
std::function<Ret(ThreadContext *, Args...)>())
{
- auto position = GuestABI::PositionInitializer<ABI>::init(tc);
+ auto position = GuestABI::initializePosition<ABI>(tc);
std::ostringstream ss;
GuestABI::allocateSignature<ABI, Ret, Args...>(tc, position);
--- /dev/null
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * 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.
+ */
+
+#ifndef __SIM_GUEST_ABI_DEFINITION_HH__
+#define __SIM_GUEST_ABI_DEFINITION_HH__
+
+class ThreadContext;
+
+namespace GuestABI
+{
+
+/*
+ * To implement an ABI, a subclass needs to implement a system of
+ * specializations of these two templates Result and Argument, and define a
+ * "Position" type.
+ *
+ * The Position type carries information about, for instance, how many
+ * integer registers have been consumed gathering earlier arguments. It
+ * may contain multiple elements if there are multiple dimensions to track,
+ * for instance the number of integer and floating point registers used so far.
+ *
+ * Result and Argument are class templates instead of function templates so
+ * that they can be partially specialized if necessary. C++ doesn't let you
+ * partially specialize function templates because that conflicts with
+ * template resolution using the function's arguments. Since we already know
+ * what type we want and we don't need argument based resolution, we can just
+ * wrap the desired functionality in classes and sidestep the problem.
+ *
+ * Also note that these templates have an "Enabled" parameter to support
+ * std::enable_if style conditional specializations.
+ */
+
+template <typename ABI, typename Ret, typename Enabled=void>
+struct Result
+{
+ private:
+ /*
+ * Store result "ret" into the state accessible through tc.
+ *
+ * Note that the declaration below is only to document the expected
+ * signature and is private so it won't be used by accident.
+ * Specializations of this Result class should define their own version
+ * of this method which actually does something and is public.
+ */
+ static void store(ThreadContext *tc, const Ret &ret);
+
+ /*
+ * Adjust the position of arguments based on the return type, if necessary.
+ *
+ * This method can be excluded if no adjustment is necessary.
+ */
+ static void allocate(ThreadContext *tc, typename ABI::Position &position);
+};
+
+/*
+ * This partial specialization prevents having to special case 'void' when
+ * working with return types.
+ */
+template <typename ABI>
+struct Result<ABI, void>
+{};
+
+template <typename ABI, typename Arg, typename Enabled=void>
+struct Argument
+{
+ /*
+ * Retrieve an argument of type Arg from the state accessible through tc,
+ * assuming the state represented by "position" has already been used.
+ * Also update position to account for this argument as well.
+ *
+ * Like Result::store above, the declaration below is only to document
+ * the expected method signature.
+ */
+ static Arg get(ThreadContext *tc, typename ABI::Position &position);
+
+ /*
+ * Adjust the position of arguments based on the argument type, if
+ * necessary.
+ *
+ * This method can be excluded if no adjustment is necessary.
+ */
+ static void allocate(ThreadContext *tc, typename ABI::Position &position);
+};
+
+} // namespace GuestABI
+
+#endif // __SIM_GUEST_ABI_DEFINITION_HH__
--- /dev/null
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * 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.
+ */
+
+#ifndef __SIM_GUEST_ABI_DISPATCH_HH__
+#define __SIM_GUEST_ABI_DISPATCH_HH__
+
+#include <functional>
+#include <sstream>
+#include <type_traits>
+
+#include "sim/guest_abi/definition.hh"
+
+class ThreadContext;
+
+namespace GuestABI
+{
+
+/*
+ * These functions will likely be common among all ABIs and implement the
+ * mechanism of gathering arguments, calling the target function, and then
+ * storing the result. They might need to be overridden if, for instance,
+ * the location of arguments need to be determined in a different order.
+ * For example, there might be an ABI which gathers arguments starting
+ * from the last in the list instead of the first. This is unlikely but
+ * still possible to support by redefining these functions..
+ */
+
+// With no arguments to gather, call the target function and store the
+// result.
+template <typename ABI, typename Ret>
+static typename std::enable_if<!std::is_void<Ret>::value, Ret>::type
+callFrom(ThreadContext *tc, typename ABI::Position &position,
+ std::function<Ret(ThreadContext *)> target)
+{
+ Ret ret = target(tc);
+ Result<ABI, Ret>::store(tc, ret);
+ return ret;
+}
+
+// With no arguments to gather and nothing to return, call the target function.
+template <typename ABI>
+static void
+callFrom(ThreadContext *tc, typename ABI::Position &position,
+ std::function<void(ThreadContext *)> target)
+{
+ target(tc);
+}
+
+// Recursively gather arguments for target from tc until we get to the base
+// case above.
+template <typename ABI, typename Ret, typename NextArg, typename ...Args>
+static typename std::enable_if<!std::is_void<Ret>::value, Ret>::type
+callFrom(ThreadContext *tc, typename ABI::Position &position,
+ std::function<Ret(ThreadContext *, NextArg, Args...)> target)
+{
+ // Extract the next argument from the thread context.
+ NextArg next = Argument<ABI, NextArg>::get(tc, position);
+
+ // Build a partial function which adds the next argument to the call.
+ std::function<Ret(ThreadContext *, Args...)> partial =
+ [target,next](ThreadContext *_tc, Args... args) {
+ return target(_tc, next, args...);
+ };
+
+ // Recursively handle any remaining arguments.
+ return callFrom<ABI, Ret, Args...>(tc, position, partial);
+}
+
+// Recursively gather arguments for target from tc until we get to the base
+// case above. This version is for functions that don't return anything.
+template <typename ABI, typename NextArg, typename ...Args>
+static void
+callFrom(ThreadContext *tc, typename ABI::Position &position,
+ std::function<void(ThreadContext *, NextArg, Args...)> target)
+{
+ // Extract the next argument from the thread context.
+ NextArg next = Argument<ABI, NextArg>::get(tc, position);
+
+ // Build a partial function which adds the next argument to the call.
+ std::function<void(ThreadContext *, Args...)> partial =
+ [target,next](ThreadContext *_tc, Args... args) {
+ target(_tc, next, args...);
+ };
+
+ // Recursively handle any remaining arguments.
+ callFrom<ABI, Args...>(tc, position, partial);
+}
+
+
+
+/*
+ * These functions are like the ones above, except they print the arguments
+ * a target function would be called with instead of actually calling it.
+ */
+
+// With no arguments to print, add the closing parenthesis and return.
+template <typename ABI, typename Ret>
+static void
+dumpArgsFrom(int count, std::ostream &os, ThreadContext *tc,
+ typename ABI::Position &position)
+{
+ os << ")";
+}
+
+// Recursively gather arguments for target from tc until we get to the base
+// case above, and append those arguments to the string stream being
+// constructed.
+template <typename ABI, typename Ret, typename NextArg, typename ...Args>
+static void
+dumpArgsFrom(int count, std::ostream &os, ThreadContext *tc,
+ typename ABI::Position &position)
+{
+ // Either open the parenthesis or add a comma, depending on where we are
+ // in the argument list.
+ os << (count ? ", " : "(");
+
+ // Extract the next argument from the thread context.
+ NextArg next = Argument<ABI, NextArg>::get(tc, position);
+
+ // Add this argument to the list.
+ os << next;
+
+ // Recursively handle any remaining arguments.
+ dumpArgsFrom<ABI, Ret, Args...>(count + 1, os, tc, position);
+}
+
+} // namespace GuestABI
+
+#endif // __SIM_GUEST_ABI_DISPATCH_HH__
--- /dev/null
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * 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.
+ */
+
+#ifndef __SIM_GUEST_ABI_LAYOUT_HH__
+#define __SIM_GUEST_ABI_LAYOUT_HH__
+
+#include <type_traits>
+
+#include "sim/guest_abi/definition.hh"
+
+class ThreadContext;
+
+namespace GuestABI
+{
+
+/*
+ * Position may need to be initialized based on the ThreadContext, for instance
+ * to find out where the stack pointer is initially.
+ */
+template <typename ABI, typename Enabled=void>
+struct PositionInitializer
+{
+ static typename ABI::Position
+ init(const ThreadContext *tc)
+ {
+ return typename ABI::Position();
+ }
+};
+
+template <typename ABI>
+struct PositionInitializer<ABI, typename std::enable_if<
+ std::is_constructible<typename ABI::Position, const ThreadContext *>::value
+ >::type>
+{
+ static typename ABI::Position
+ init(const ThreadContext *tc)
+ {
+ return typename ABI::Position(tc);
+ }
+};
+
+template <typename ABI>
+static typename ABI::Position
+initializePosition(const ThreadContext *tc)
+{
+ return PositionInitializer<ABI>::init(tc);
+}
+
+/*
+ * This struct template provides a default allocate() method in case the
+ * Result or Argument template doesn't provide one. This is the default in
+ * cases where the return or argument type doesn't affect where things are
+ * stored.
+ */
+template <typename ABI, template <class ...> class Role,
+ typename Type, typename Enabled=void>
+struct Allocator
+{
+ static void
+ allocate(ThreadContext *tc, typename ABI::Position &position)
+ {}
+};
+
+/*
+ * If the return or argument type isn't void and does affect where things
+ * are stored, the ABI can implement an allocate() method for the various
+ * argument and/or return types, and this specialization will call into it.
+ */
+template <typename ABI, template <class ...> class Role, typename Type>
+struct Allocator<ABI, Role, Type, decltype((void)&Role<ABI, Type>::allocate)>
+{
+ static void
+ allocate(ThreadContext *tc, typename ABI::Position &position)
+ {
+ Role<ABI, Type>::allocate(tc, position);
+ }
+};
+
+template <typename ABI, typename Ret, typename Enabled=void>
+static void
+allocateResult(ThreadContext *tc, typename ABI::Position &position)
+{
+ Allocator<ABI, Result, Ret>::allocate(tc, position);
+}
+
+template <typename ABI>
+static void
+allocateArguments(ThreadContext *tc, typename ABI::Position &position)
+{
+ return;
+}
+
+template <typename ABI, typename NextArg, typename ...Args>
+static void
+allocateArguments(ThreadContext *tc, typename ABI::Position &position)
+{
+ Allocator<ABI, Argument, NextArg>::allocate(tc, position);
+ allocateArguments<ABI, Args...>(tc, position);
+}
+
+template <typename ABI, typename Ret, typename ...Args>
+static void
+allocateSignature(ThreadContext *tc, typename ABI::Position &position)
+{
+ allocateResult<ABI, Ret>(tc, position);
+ allocateArguments<ABI, Args...>(tc, position);
+}
+
+} // namespace GuestABI
+
+#endif // __SIM_GUEST_ABI_LAYOUT_HH__
--- /dev/null
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * 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.
+ */
+
+#ifndef __SIM_GUEST_ABI_VARARGS_HH__
+#define __SIM_GUEST_ABI_VARRAGS_HH__
+
+#include <memory>
+#include <sstream>
+#include <type_traits>
+
+#include "sim/guest_abi/definition.hh"
+
+class ThreadContext;
+
+namespace GuestABI
+{
+
+/*
+ * These templates implement a variadic argument mechanism for guest ABI
+ * functions. A function might be written like this:
+ *
+ * void
+ * func(ThreadContext *tc, VarArgs<Addr, int> varargs)
+ * {
+ * warn("Address = %#x, int = %d.",
+ * varargs.get<Addr>(), varargs.get<int>());
+ * }
+ *
+ * where an object of type VarArgs<...> is its last argument. The types given
+ * to the template specify what types the function might need to retrieve from
+ * varargs. The varargs object will then have get<> methods for each of those
+ * types.
+ *
+ * Note that each get<> will happen live. If you modify values through the
+ * ThreadContext *tc and then run get<>(), you may alter one of your arguments.
+ * If you're going to use tc to modify state, it would be a good idea to use
+ * get<>() as soon as possible to avoid corrupting the functions arguments.
+ */
+
+// A recursive template which defines virtual functions to retrieve each of the
+// requested types. This provides the ABI agnostic interface the function uses.
+template <typename ...Types>
+class VarArgsBase;
+
+template <typename First, typename ...Types>
+class VarArgsBase<First, Types...> : public VarArgsBase<Types...>
+{
+ public:
+ // The virtual function takes a reference parameter so that the different
+ // _getImpl methods can co-exist through overloading.
+ virtual void _getImpl(First &) = 0;
+
+ // Make sure base class _getImpl-es aren't hidden by this one.
+ using VarArgsBase<Types...>::_getImpl;
+};
+
+// The base case of the recursion.
+template <>
+class VarArgsBase<>
+{
+ protected:
+ // This just gives the "using" statement in the non base case something to
+ // refer to.
+ void _getImpl();
+};
+
+
+// A recursive template which defines the ABI specific implementation of the
+// interface defined above.
+//
+// The types in Types are consumed one by one, and by
+// the time we get down to the base case we'd have lost track of the complete
+// set we need to know what interface to inherit. The Base parameter keeps
+// track of that through the recursion.
+template <typename ABI, typename Base, typename ...Types>
+class VarArgsImpl;
+
+template <typename ABI, typename Base, typename First, typename ...Types>
+class VarArgsImpl<ABI, Base, First, Types...> :
+ public VarArgsImpl<ABI, Base, Types...>
+{
+ protected:
+ // Bring forward the base class constructor.
+ using VarArgsImpl<ABI, Base, Types...>::VarArgsImpl;
+ // Make sure base class _getImpl-es don't get hidden by ours.
+ using VarArgsImpl<ABI, Base, Types...>::_getImpl;
+
+ // Implement a version of _getImple, using the ABI specialized version of
+ // the Argument class.
+ void
+ _getImpl(First &first) override
+ {
+ first = Argument<ABI, First>::get(this->tc, this->position);
+ }
+};
+
+// The base case of the recursion, which inherits from the interface class.
+template <typename ABI, typename Base>
+class VarArgsImpl<ABI, Base> : public Base
+{
+ protected:
+ // Declare state to pass to the Argument<>::get methods.
+ ThreadContext *tc;
+ typename ABI::Position position;
+
+ // Give the "using" statement in our subclass something to refer to.
+ void _getImpl();
+
+ public:
+ VarArgsImpl(ThreadContext *_tc, const typename ABI::Position &_pos) :
+ tc(_tc), position(_pos)
+ {}
+};
+
+// A wrapper which provides a nice interface to the virtual functions, and a
+// hook for the Argument template mechanism.
+template <typename ...Types>
+class VarArgs
+{
+ private:
+ // This points to the implementation which knows how to read arguments
+ // based on the ABI being used.
+ std::shared_ptr<VarArgsBase<Types...>> _ptr;
+
+ public:
+ VarArgs(VarArgsBase<Types...> *ptr) : _ptr(ptr) {}
+
+ // This template is a friendlier wrapper around the virtual functions the
+ // raw interface provides. This version lets you pick a type which it then
+ // returns, instead of having to pre-declare a variable to pass in.
+ template <typename Arg>
+ Arg
+ get()
+ {
+ Arg arg;
+ _ptr->_getImpl(arg);
+ return arg;
+ }
+};
+
+template <typename T>
+struct IsVarArgs : public std::false_type {};
+
+template <typename ...Types>
+struct IsVarArgs<VarArgs<Types...>> : public std::true_type {};
+
+template <typename ...Types>
+std::ostream &
+operator << (std::ostream &os, const VarArgs<Types...> &va)
+{
+ os << "...";
+ return os;
+}
+
+// The ABI independent hook which tells the GuestABI mechanism what to do with
+// a VarArgs argument. It constructs the underlying implementation which knows
+// about the ABI, and installs it in the VarArgs wrapper to give to the
+// function.
+template <typename ABI, typename ...Types>
+struct Argument<ABI, VarArgs<Types...>>
+{
+ static VarArgs<Types...>
+ get(ThreadContext *tc, typename ABI::Position &position)
+ {
+ using Base = VarArgsBase<Types...>;
+ using Impl = VarArgsImpl<ABI, Base, Types...>;
+ return VarArgs<Types...>(new Impl(tc, position));
+ }
+};
+
+} // namespace GuestABI
+
+#endif // __SIM_GUEST_ABI_VARARGS_HH__