xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
15ffd83dbSDimitry Andric //===-- ClangFunctionCaller.cpp -------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "ClangFunctionCaller.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "ASTStructExtractor.h"
120b57cec5SDimitry Andric #include "ClangExpressionParser.h"
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
150b57cec5SDimitry Andric #include "clang/AST/RecordLayout.h"
160b57cec5SDimitry Andric #include "clang/CodeGen/CodeGenAction.h"
170b57cec5SDimitry Andric #include "clang/CodeGen/ModuleBuilder.h"
180b57cec5SDimitry Andric #include "clang/Frontend/CompilerInstance.h"
190b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
200b57cec5SDimitry Andric #include "llvm/ExecutionEngine/ExecutionEngine.h"
210b57cec5SDimitry Andric #include "llvm/IR/Module.h"
2206c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
230b57cec5SDimitry Andric 
245ffd83dbSDimitry Andric #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
250b57cec5SDimitry Andric #include "lldb/Core/Module.h"
260b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h"
270b57cec5SDimitry Andric #include "lldb/Core/ValueObjectList.h"
280b57cec5SDimitry Andric #include "lldb/Expression/IRExecutionUnit.h"
290b57cec5SDimitry Andric #include "lldb/Interpreter/CommandReturnObject.h"
300b57cec5SDimitry Andric #include "lldb/Symbol/Function.h"
310b57cec5SDimitry Andric #include "lldb/Symbol/Type.h"
320b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h"
330b57cec5SDimitry Andric #include "lldb/Target/Process.h"
340b57cec5SDimitry Andric #include "lldb/Target/RegisterContext.h"
350b57cec5SDimitry Andric #include "lldb/Target/Target.h"
360b57cec5SDimitry Andric #include "lldb/Target/Thread.h"
370b57cec5SDimitry Andric #include "lldb/Target/ThreadPlan.h"
380b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanCallFunction.h"
390b57cec5SDimitry Andric #include "lldb/Utility/DataExtractor.h"
4081ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
410b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
420b57cec5SDimitry Andric #include "lldb/Utility/State.h"
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric using namespace lldb_private;
450b57cec5SDimitry Andric 
46480093f4SDimitry Andric char ClangFunctionCaller::ID;
47480093f4SDimitry Andric 
480b57cec5SDimitry Andric // ClangFunctionCaller constructor
490b57cec5SDimitry Andric ClangFunctionCaller::ClangFunctionCaller(ExecutionContextScope &exe_scope,
500b57cec5SDimitry Andric                                          const CompilerType &return_type,
510b57cec5SDimitry Andric                                          const Address &functionAddress,
520b57cec5SDimitry Andric                                          const ValueList &arg_value_list,
530b57cec5SDimitry Andric                                          const char *name)
540b57cec5SDimitry Andric     : FunctionCaller(exe_scope, return_type, functionAddress, arg_value_list,
550b57cec5SDimitry Andric                      name),
560b57cec5SDimitry Andric       m_type_system_helper(*this) {
570b57cec5SDimitry Andric   m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess());
580b57cec5SDimitry Andric   // Can't make a ClangFunctionCaller without a process.
590b57cec5SDimitry Andric   assert(m_jit_process_wp.lock());
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric // Destructor
63fe6060f1SDimitry Andric ClangFunctionCaller::~ClangFunctionCaller() = default;
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric unsigned
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric ClangFunctionCaller::CompileFunction(lldb::ThreadSP thread_to_use_sp,
680b57cec5SDimitry Andric                                      DiagnosticManager &diagnostic_manager) {
690b57cec5SDimitry Andric   if (m_compiled)
700b57cec5SDimitry Andric     return 0;
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric   // Compilation might call code, make sure to keep on the thread the caller
730b57cec5SDimitry Andric   // indicated.
740b57cec5SDimitry Andric   ThreadList::ExpressionExecutionThreadPusher execution_thread_pusher(
750b57cec5SDimitry Andric       thread_to_use_sp);
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric   // FIXME: How does clang tell us there's no return value?  We need to handle
780b57cec5SDimitry Andric   // that case.
790b57cec5SDimitry Andric   unsigned num_errors = 0;
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric   std::string return_type_str(
820b57cec5SDimitry Andric       m_function_return_type.GetTypeName().AsCString(""));
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric   // Cons up the function we're going to wrap our call in, then compile it...
850b57cec5SDimitry Andric   // We declare the function "extern "C"" because the compiler might be in C++
860b57cec5SDimitry Andric   // mode which would mangle the name and then we couldn't find it again...
870b57cec5SDimitry Andric   m_wrapper_function_text.clear();
880b57cec5SDimitry Andric   m_wrapper_function_text.append("extern \"C\" void ");
890b57cec5SDimitry Andric   m_wrapper_function_text.append(m_wrapper_function_name);
900b57cec5SDimitry Andric   m_wrapper_function_text.append(" (void *input)\n{\n    struct ");
910b57cec5SDimitry Andric   m_wrapper_function_text.append(m_wrapper_struct_name);
920b57cec5SDimitry Andric   m_wrapper_function_text.append(" \n  {\n");
930b57cec5SDimitry Andric   m_wrapper_function_text.append("    ");
940b57cec5SDimitry Andric   m_wrapper_function_text.append(return_type_str);
950b57cec5SDimitry Andric   m_wrapper_function_text.append(" (*fn_ptr) (");
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric   // Get the number of arguments.  If we have a function type and it is
980b57cec5SDimitry Andric   // prototyped, trust that, otherwise use the values we were given.
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric   // FIXME: This will need to be extended to handle Variadic functions.  We'll
1010b57cec5SDimitry Andric   // need
1020b57cec5SDimitry Andric   // to pull the defined arguments out of the function, then add the types from
1030b57cec5SDimitry Andric   // the arguments list for the variable arguments.
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   uint32_t num_args = UINT32_MAX;
1060b57cec5SDimitry Andric   bool trust_function = false;
1070b57cec5SDimitry Andric   // GetArgumentCount returns -1 for an unprototyped function.
1080b57cec5SDimitry Andric   CompilerType function_clang_type;
1090b57cec5SDimitry Andric   if (m_function_ptr) {
1100b57cec5SDimitry Andric     function_clang_type = m_function_ptr->GetCompilerType();
1110b57cec5SDimitry Andric     if (function_clang_type) {
1120b57cec5SDimitry Andric       int num_func_args = function_clang_type.GetFunctionArgumentCount();
1130b57cec5SDimitry Andric       if (num_func_args >= 0) {
1140b57cec5SDimitry Andric         trust_function = true;
1150b57cec5SDimitry Andric         num_args = num_func_args;
1160b57cec5SDimitry Andric       }
1170b57cec5SDimitry Andric     }
1180b57cec5SDimitry Andric   }
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric   if (num_args == UINT32_MAX)
1210b57cec5SDimitry Andric     num_args = m_arg_values.GetSize();
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric   std::string args_buffer; // This one stores the definition of all the args in
1240b57cec5SDimitry Andric                            // "struct caller".
1250b57cec5SDimitry Andric   std::string args_list_buffer; // This one stores the argument list called from
1260b57cec5SDimitry Andric                                 // the structure.
1270b57cec5SDimitry Andric   for (size_t i = 0; i < num_args; i++) {
1280b57cec5SDimitry Andric     std::string type_name;
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric     if (trust_function) {
1310b57cec5SDimitry Andric       type_name = function_clang_type.GetFunctionArgumentTypeAtIndex(i)
1320b57cec5SDimitry Andric                       .GetTypeName()
1330b57cec5SDimitry Andric                       .AsCString("");
1340b57cec5SDimitry Andric     } else {
1350b57cec5SDimitry Andric       CompilerType clang_qual_type =
1360b57cec5SDimitry Andric           m_arg_values.GetValueAtIndex(i)->GetCompilerType();
1370b57cec5SDimitry Andric       if (clang_qual_type) {
1380b57cec5SDimitry Andric         type_name = clang_qual_type.GetTypeName().AsCString("");
1390b57cec5SDimitry Andric       } else {
1400b57cec5SDimitry Andric         diagnostic_manager.Printf(
141*0fca6ea1SDimitry Andric             lldb::eSeverityError,
1420b57cec5SDimitry Andric             "Could not determine type of input value %" PRIu64 ".",
1430b57cec5SDimitry Andric             (uint64_t)i);
1440b57cec5SDimitry Andric         return 1;
1450b57cec5SDimitry Andric       }
1460b57cec5SDimitry Andric     }
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric     m_wrapper_function_text.append(type_name);
1490b57cec5SDimitry Andric     if (i < num_args - 1)
1500b57cec5SDimitry Andric       m_wrapper_function_text.append(", ");
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric     char arg_buf[32];
1530b57cec5SDimitry Andric     args_buffer.append("    ");
1540b57cec5SDimitry Andric     args_buffer.append(type_name);
1550b57cec5SDimitry Andric     snprintf(arg_buf, 31, "arg_%" PRIu64, (uint64_t)i);
1560b57cec5SDimitry Andric     args_buffer.push_back(' ');
1570b57cec5SDimitry Andric     args_buffer.append(arg_buf);
1580b57cec5SDimitry Andric     args_buffer.append(";\n");
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric     args_list_buffer.append("__lldb_fn_data->");
1610b57cec5SDimitry Andric     args_list_buffer.append(arg_buf);
1620b57cec5SDimitry Andric     if (i < num_args - 1)
1630b57cec5SDimitry Andric       args_list_buffer.append(", ");
1640b57cec5SDimitry Andric   }
1650b57cec5SDimitry Andric   m_wrapper_function_text.append(
1660b57cec5SDimitry Andric       ");\n"); // Close off the function calling prototype.
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   m_wrapper_function_text.append(args_buffer);
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric   m_wrapper_function_text.append("    ");
1710b57cec5SDimitry Andric   m_wrapper_function_text.append(return_type_str);
1720b57cec5SDimitry Andric   m_wrapper_function_text.append(" return_value;");
1730b57cec5SDimitry Andric   m_wrapper_function_text.append("\n  };\n  struct ");
1740b57cec5SDimitry Andric   m_wrapper_function_text.append(m_wrapper_struct_name);
1750b57cec5SDimitry Andric   m_wrapper_function_text.append("* __lldb_fn_data = (struct ");
1760b57cec5SDimitry Andric   m_wrapper_function_text.append(m_wrapper_struct_name);
1770b57cec5SDimitry Andric   m_wrapper_function_text.append(" *) input;\n");
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric   m_wrapper_function_text.append(
1800b57cec5SDimitry Andric       "  __lldb_fn_data->return_value = __lldb_fn_data->fn_ptr (");
1810b57cec5SDimitry Andric   m_wrapper_function_text.append(args_list_buffer);
1820b57cec5SDimitry Andric   m_wrapper_function_text.append(");\n}\n");
1830b57cec5SDimitry Andric 
18481ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Expressions);
1859dba64beSDimitry Andric   LLDB_LOGF(log, "Expression: \n\n%s\n\n", m_wrapper_function_text.c_str());
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric   // Okay, now compile this expression
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
1900b57cec5SDimitry Andric   if (jit_process_sp) {
1910b57cec5SDimitry Andric     const bool generate_debug_info = true;
192480093f4SDimitry Andric     auto *clang_parser = new ClangExpressionParser(jit_process_sp.get(), *this,
193480093f4SDimitry Andric                                                    generate_debug_info);
194480093f4SDimitry Andric     num_errors = clang_parser->Parse(diagnostic_manager);
195480093f4SDimitry Andric     m_parser.reset(clang_parser);
1960b57cec5SDimitry Andric   } else {
197*0fca6ea1SDimitry Andric     diagnostic_manager.PutString(lldb::eSeverityError,
1980b57cec5SDimitry Andric                                  "no process - unable to inject function");
1990b57cec5SDimitry Andric     num_errors = 1;
2000b57cec5SDimitry Andric   }
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric   m_compiled = (num_errors == 0);
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric   if (!m_compiled)
2050b57cec5SDimitry Andric     return num_errors;
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric   return num_errors;
2080b57cec5SDimitry Andric }
2090b57cec5SDimitry Andric 
21006c3fb27SDimitry Andric char ClangFunctionCaller::ClangFunctionCallerHelper::ID;
21106c3fb27SDimitry Andric 
2120b57cec5SDimitry Andric clang::ASTConsumer *
2130b57cec5SDimitry Andric ClangFunctionCaller::ClangFunctionCallerHelper::ASTTransformer(
2140b57cec5SDimitry Andric     clang::ASTConsumer *passthrough) {
2155ffd83dbSDimitry Andric   m_struct_extractor = std::make_unique<ASTStructExtractor>(
2165ffd83dbSDimitry Andric       passthrough, m_owner.GetWrapperStructName(), m_owner);
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric   return m_struct_extractor.get();
2190b57cec5SDimitry Andric }
220