1*e65b2cf2SEugene Zelenko //===-- ThreadPlanCallFunctionUsingABI.cpp ----------------------*- C++ -*-===//
290ff7911SEwan Crawford //
390ff7911SEwan Crawford //                     The LLVM Compiler Infrastructure
490ff7911SEwan Crawford //
590ff7911SEwan Crawford // This file is distributed under the University of Illinois Open Source
690ff7911SEwan Crawford // License. See LICENSE.TXT for details.
790ff7911SEwan Crawford //
890ff7911SEwan Crawford //===----------------------------------------------------------------------===//
990ff7911SEwan Crawford 
1090ff7911SEwan Crawford // C Includes
1190ff7911SEwan Crawford // C++ Includes
1290ff7911SEwan Crawford // Other libraries and framework includes
1390ff7911SEwan Crawford // Project includes
14*e65b2cf2SEugene Zelenko #include "lldb/Target/ThreadPlanCallFunctionUsingABI.h"
1590ff7911SEwan Crawford #include "lldb/Core/Address.h"
1690ff7911SEwan Crawford #include "lldb/Core/Log.h"
1790ff7911SEwan Crawford #include "lldb/Core/Stream.h"
1890ff7911SEwan Crawford #include "lldb/Target/Process.h"
1990ff7911SEwan Crawford #include "lldb/Target/RegisterContext.h"
2090ff7911SEwan Crawford #include "lldb/Target/Target.h"
2190ff7911SEwan Crawford #include "lldb/Target/Thread.h"
2290ff7911SEwan Crawford 
2390ff7911SEwan Crawford using namespace lldb;
2490ff7911SEwan Crawford using namespace lldb_private;
2590ff7911SEwan Crawford 
2690ff7911SEwan Crawford //--------------------------------------------------------------------------------------------
2790ff7911SEwan Crawford // ThreadPlanCallFunctionUsingABI: Plan to call a single function using the ABI instead of JIT
2890ff7911SEwan Crawford //-------------------------------------------------------------------------------------------
2990ff7911SEwan Crawford ThreadPlanCallFunctionUsingABI::ThreadPlanCallFunctionUsingABI (Thread &thread,
3090ff7911SEwan Crawford                                                           const Address &function,
3190ff7911SEwan Crawford                                                           llvm::Type &prototype,
3290ff7911SEwan Crawford                                                           llvm::Type &return_type,
3390ff7911SEwan Crawford                                                           llvm::ArrayRef<ABI::CallArgument> args,
3490ff7911SEwan Crawford                                                           const EvaluateExpressionOptions &options) :
3590ff7911SEwan Crawford      ThreadPlanCallFunction(thread,function,options),
3690ff7911SEwan Crawford      m_return_type(return_type)
3790ff7911SEwan Crawford {
3890ff7911SEwan Crawford     lldb::addr_t start_load_addr = LLDB_INVALID_ADDRESS;
3990ff7911SEwan Crawford     lldb::addr_t function_load_addr = LLDB_INVALID_ADDRESS;
4090ff7911SEwan Crawford     ABI *abi = nullptr;
4190ff7911SEwan Crawford 
4290ff7911SEwan Crawford     if (!ConstructorSetup(thread, abi, start_load_addr, function_load_addr))
4390ff7911SEwan Crawford         return;
4490ff7911SEwan Crawford 
4590ff7911SEwan Crawford     if (!abi->PrepareTrivialCall(thread,
4690ff7911SEwan Crawford         m_function_sp,
4790ff7911SEwan Crawford         function_load_addr,
4890ff7911SEwan Crawford         start_load_addr,
4990ff7911SEwan Crawford         prototype,
5090ff7911SEwan Crawford         args))
5190ff7911SEwan Crawford         return;
5290ff7911SEwan Crawford 
5390ff7911SEwan Crawford     ReportRegisterState("ABI Function call was set up.  Register state was:");
5490ff7911SEwan Crawford 
5590ff7911SEwan Crawford     m_valid = true;
5690ff7911SEwan Crawford }
5790ff7911SEwan Crawford 
58*e65b2cf2SEugene Zelenko ThreadPlanCallFunctionUsingABI::~ThreadPlanCallFunctionUsingABI() = default;
5990ff7911SEwan Crawford 
6090ff7911SEwan Crawford void
6190ff7911SEwan Crawford ThreadPlanCallFunctionUsingABI::GetDescription(Stream *s, DescriptionLevel level)
6290ff7911SEwan Crawford {
6390ff7911SEwan Crawford     if (level == eDescriptionLevelBrief)
6490ff7911SEwan Crawford     {
6590ff7911SEwan Crawford         s->Printf("Function call thread plan using ABI instead of JIT");
6690ff7911SEwan Crawford     }
6790ff7911SEwan Crawford     else
6890ff7911SEwan Crawford     {
6990ff7911SEwan Crawford         TargetSP target_sp(m_thread.CalculateTarget());
7090ff7911SEwan Crawford         s->Printf("Thread plan to call 0x%" PRIx64" using ABI instead of JIT", m_function_addr.GetLoadAddress(target_sp.get()));
7190ff7911SEwan Crawford     }
7290ff7911SEwan Crawford }
7390ff7911SEwan Crawford 
7490ff7911SEwan Crawford void
7590ff7911SEwan Crawford ThreadPlanCallFunctionUsingABI::SetReturnValue()
7690ff7911SEwan Crawford {
7790ff7911SEwan Crawford     ProcessSP process_sp(m_thread.GetProcess());
78*e65b2cf2SEugene Zelenko     const ABI *abi = process_sp ? process_sp->GetABI().get() : nullptr;
7990ff7911SEwan Crawford 
8090ff7911SEwan Crawford     // Ask the abi for the return value
8190ff7911SEwan Crawford     if (abi)
8290ff7911SEwan Crawford     {
8390ff7911SEwan Crawford         const bool persistent = false;
8490ff7911SEwan Crawford         m_return_valobj_sp = abi->GetReturnValueObject(m_thread, m_return_type, persistent);
8590ff7911SEwan Crawford     }
8690ff7911SEwan Crawford }
87