19f2f44ceSEd Maste //===-- ThreadPlanCallFunctionUsingABI.cpp ----------------------*- C++ -*-===//
2b91a7dfcSDimitry Andric //
3b91a7dfcSDimitry Andric //                     The LLVM Compiler Infrastructure
4b91a7dfcSDimitry Andric //
5b91a7dfcSDimitry Andric // This file is distributed under the University of Illinois Open Source
6b91a7dfcSDimitry Andric // License. See LICENSE.TXT for details.
7b91a7dfcSDimitry Andric //
8b91a7dfcSDimitry Andric //===----------------------------------------------------------------------===//
9b91a7dfcSDimitry Andric 
109f2f44ceSEd Maste #include "lldb/Target/ThreadPlanCallFunctionUsingABI.h"
11b91a7dfcSDimitry Andric #include "lldb/Core/Address.h"
12b91a7dfcSDimitry Andric #include "lldb/Target/Process.h"
13b91a7dfcSDimitry Andric #include "lldb/Target/RegisterContext.h"
14b91a7dfcSDimitry Andric #include "lldb/Target/Target.h"
15b91a7dfcSDimitry Andric #include "lldb/Target/Thread.h"
16f678e45dSDimitry Andric #include "lldb/Utility/Log.h"
17f678e45dSDimitry Andric #include "lldb/Utility/Stream.h"
18b91a7dfcSDimitry Andric 
19b91a7dfcSDimitry Andric using namespace lldb;
20b91a7dfcSDimitry Andric using namespace lldb_private;
21b91a7dfcSDimitry Andric 
22b91a7dfcSDimitry Andric //--------------------------------------------------------------------------------------------
23435933ddSDimitry Andric // ThreadPlanCallFunctionUsingABI: Plan to call a single function using the ABI
24435933ddSDimitry Andric // instead of JIT
25b91a7dfcSDimitry Andric //-------------------------------------------------------------------------------------------
ThreadPlanCallFunctionUsingABI(Thread & thread,const Address & function,llvm::Type & prototype,llvm::Type & return_type,llvm::ArrayRef<ABI::CallArgument> args,const EvaluateExpressionOptions & options)26435933ddSDimitry Andric ThreadPlanCallFunctionUsingABI::ThreadPlanCallFunctionUsingABI(
27435933ddSDimitry Andric     Thread &thread, const Address &function, llvm::Type &prototype,
28435933ddSDimitry Andric     llvm::Type &return_type, llvm::ArrayRef<ABI::CallArgument> args,
29435933ddSDimitry Andric     const EvaluateExpressionOptions &options)
30435933ddSDimitry Andric     : ThreadPlanCallFunction(thread, function, options),
31435933ddSDimitry Andric       m_return_type(return_type) {
32b91a7dfcSDimitry Andric   lldb::addr_t start_load_addr = LLDB_INVALID_ADDRESS;
33b91a7dfcSDimitry Andric   lldb::addr_t function_load_addr = LLDB_INVALID_ADDRESS;
34b91a7dfcSDimitry Andric   ABI *abi = nullptr;
35b91a7dfcSDimitry Andric 
36b91a7dfcSDimitry Andric   if (!ConstructorSetup(thread, abi, start_load_addr, function_load_addr))
37b91a7dfcSDimitry Andric     return;
38b91a7dfcSDimitry Andric 
39435933ddSDimitry Andric   if (!abi->PrepareTrivialCall(thread, m_function_sp, function_load_addr,
40435933ddSDimitry Andric                                start_load_addr, prototype, args))
41b91a7dfcSDimitry Andric     return;
42b91a7dfcSDimitry Andric 
43b91a7dfcSDimitry Andric   ReportRegisterState("ABI Function call was set up.  Register state was:");
44b91a7dfcSDimitry Andric 
45b91a7dfcSDimitry Andric   m_valid = true;
46b91a7dfcSDimitry Andric }
47b91a7dfcSDimitry Andric 
489f2f44ceSEd Maste ThreadPlanCallFunctionUsingABI::~ThreadPlanCallFunctionUsingABI() = default;
49b91a7dfcSDimitry Andric 
GetDescription(Stream * s,DescriptionLevel level)50435933ddSDimitry Andric void ThreadPlanCallFunctionUsingABI::GetDescription(Stream *s,
51435933ddSDimitry Andric                                                     DescriptionLevel level) {
52435933ddSDimitry Andric   if (level == eDescriptionLevelBrief) {
53b91a7dfcSDimitry Andric     s->Printf("Function call thread plan using ABI instead of JIT");
54435933ddSDimitry Andric   } else {
55b91a7dfcSDimitry Andric     TargetSP target_sp(m_thread.CalculateTarget());
56435933ddSDimitry Andric     s->Printf("Thread plan to call 0x%" PRIx64 " using ABI instead of JIT",
57435933ddSDimitry Andric               m_function_addr.GetLoadAddress(target_sp.get()));
58b91a7dfcSDimitry Andric   }
59b91a7dfcSDimitry Andric }
60b91a7dfcSDimitry Andric 
SetReturnValue()61435933ddSDimitry Andric void ThreadPlanCallFunctionUsingABI::SetReturnValue() {
62b91a7dfcSDimitry Andric   ProcessSP process_sp(m_thread.GetProcess());
639f2f44ceSEd Maste   const ABI *abi = process_sp ? process_sp->GetABI().get() : nullptr;
64b91a7dfcSDimitry Andric 
65b91a7dfcSDimitry Andric   // Ask the abi for the return value
66435933ddSDimitry Andric   if (abi) {
67b91a7dfcSDimitry Andric     const bool persistent = false;
68435933ddSDimitry Andric     m_return_valobj_sp =
69435933ddSDimitry Andric         abi->GetReturnValueObject(m_thread, m_return_type, persistent);
70b91a7dfcSDimitry Andric   }
71b91a7dfcSDimitry Andric }
72