180814287SRaphael Isemann //===-- ClangFunctionCaller.cpp -------------------------------------------===//
24dbb271fSSean Callanan //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64dbb271fSSean Callanan //
74dbb271fSSean Callanan //===----------------------------------------------------------------------===//
84dbb271fSSean Callanan
94dbb271fSSean Callanan #include "ClangFunctionCaller.h"
104dbb271fSSean Callanan
114dbb271fSSean Callanan #include "ASTStructExtractor.h"
124dbb271fSSean Callanan #include "ClangExpressionParser.h"
134dbb271fSSean Callanan
144dbb271fSSean Callanan #include "clang/AST/ASTContext.h"
154dbb271fSSean Callanan #include "clang/AST/RecordLayout.h"
164dbb271fSSean Callanan #include "clang/CodeGen/CodeGenAction.h"
174dbb271fSSean Callanan #include "clang/CodeGen/ModuleBuilder.h"
184dbb271fSSean Callanan #include "clang/Frontend/CompilerInstance.h"
194dbb271fSSean Callanan #include "llvm/ADT/StringRef.h"
204dbb271fSSean Callanan #include "llvm/ADT/Triple.h"
214dbb271fSSean Callanan #include "llvm/ExecutionEngine/ExecutionEngine.h"
224dbb271fSSean Callanan #include "llvm/IR/Module.h"
234dbb271fSSean Callanan
248be30215SAlex Langford #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
254dbb271fSSean Callanan #include "lldb/Core/Module.h"
264dbb271fSSean Callanan #include "lldb/Core/ValueObject.h"
274dbb271fSSean Callanan #include "lldb/Core/ValueObjectList.h"
284dbb271fSSean Callanan #include "lldb/Expression/IRExecutionUnit.h"
294dbb271fSSean Callanan #include "lldb/Interpreter/CommandReturnObject.h"
304dbb271fSSean Callanan #include "lldb/Symbol/Function.h"
314dbb271fSSean Callanan #include "lldb/Symbol/Type.h"
324dbb271fSSean Callanan #include "lldb/Target/ExecutionContext.h"
334dbb271fSSean Callanan #include "lldb/Target/Process.h"
344dbb271fSSean Callanan #include "lldb/Target/RegisterContext.h"
354dbb271fSSean Callanan #include "lldb/Target/Target.h"
364dbb271fSSean Callanan #include "lldb/Target/Thread.h"
374dbb271fSSean Callanan #include "lldb/Target/ThreadPlan.h"
384dbb271fSSean Callanan #include "lldb/Target/ThreadPlanCallFunction.h"
39666cc0b2SZachary Turner #include "lldb/Utility/DataExtractor.h"
40*c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h"
416f9e6901SZachary Turner #include "lldb/Utility/Log.h"
42d821c997SPavel Labath #include "lldb/Utility/State.h"
434dbb271fSSean Callanan
444dbb271fSSean Callanan using namespace lldb_private;
454dbb271fSSean Callanan
4652f3a2faSRaphael Isemann char ClangFunctionCaller::ID;
4752f3a2faSRaphael Isemann
484dbb271fSSean Callanan // ClangFunctionCaller constructor
ClangFunctionCaller(ExecutionContextScope & exe_scope,const CompilerType & return_type,const Address & functionAddress,const ValueList & arg_value_list,const char * name)49b9c1b51eSKate Stone ClangFunctionCaller::ClangFunctionCaller(ExecutionContextScope &exe_scope,
504dbb271fSSean Callanan const CompilerType &return_type,
514dbb271fSSean Callanan const Address &functionAddress,
524dbb271fSSean Callanan const ValueList &arg_value_list,
53b9c1b51eSKate Stone const char *name)
54b9c1b51eSKate Stone : FunctionCaller(exe_scope, return_type, functionAddress, arg_value_list,
55b9c1b51eSKate Stone name),
56b9c1b51eSKate Stone m_type_system_helper(*this) {
574dbb271fSSean Callanan m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess());
584dbb271fSSean Callanan // Can't make a ClangFunctionCaller without a process.
594dbb271fSSean Callanan assert(m_jit_process_wp.lock());
604dbb271fSSean Callanan }
614dbb271fSSean Callanan
624dbb271fSSean Callanan // Destructor
63fd2433e1SJonas Devlieghere ClangFunctionCaller::~ClangFunctionCaller() = default;
644dbb271fSSean Callanan
654dbb271fSSean Callanan unsigned
666896b355SJim Ingham
CompileFunction(lldb::ThreadSP thread_to_use_sp,DiagnosticManager & diagnostic_manager)676896b355SJim Ingham ClangFunctionCaller::CompileFunction(lldb::ThreadSP thread_to_use_sp,
68b9c1b51eSKate Stone DiagnosticManager &diagnostic_manager) {
694dbb271fSSean Callanan if (m_compiled)
704dbb271fSSean Callanan return 0;
714dbb271fSSean Callanan
72b9c1b51eSKate Stone // Compilation might call code, make sure to keep on the thread the caller
73b9c1b51eSKate Stone // indicated.
74b9c1b51eSKate Stone ThreadList::ExpressionExecutionThreadPusher execution_thread_pusher(
75b9c1b51eSKate Stone thread_to_use_sp);
766896b355SJim Ingham
77b9c1b51eSKate Stone // FIXME: How does clang tell us there's no return value? We need to handle
78b9c1b51eSKate Stone // that case.
794dbb271fSSean Callanan unsigned num_errors = 0;
804dbb271fSSean Callanan
81b9c1b51eSKate Stone std::string return_type_str(
82b9c1b51eSKate Stone m_function_return_type.GetTypeName().AsCString(""));
834dbb271fSSean Callanan
844dbb271fSSean Callanan // Cons up the function we're going to wrap our call in, then compile it...
854dbb271fSSean Callanan // We declare the function "extern "C"" because the compiler might be in C++
864dbb271fSSean Callanan // mode which would mangle the name and then we couldn't find it again...
874dbb271fSSean Callanan m_wrapper_function_text.clear();
884dbb271fSSean Callanan m_wrapper_function_text.append("extern \"C\" void ");
894dbb271fSSean Callanan m_wrapper_function_text.append(m_wrapper_function_name);
904dbb271fSSean Callanan m_wrapper_function_text.append(" (void *input)\n{\n struct ");
914dbb271fSSean Callanan m_wrapper_function_text.append(m_wrapper_struct_name);
924dbb271fSSean Callanan m_wrapper_function_text.append(" \n {\n");
934dbb271fSSean Callanan m_wrapper_function_text.append(" ");
944dbb271fSSean Callanan m_wrapper_function_text.append(return_type_str);
954dbb271fSSean Callanan m_wrapper_function_text.append(" (*fn_ptr) (");
964dbb271fSSean Callanan
97b9c1b51eSKate Stone // Get the number of arguments. If we have a function type and it is
9805097246SAdrian Prantl // prototyped, trust that, otherwise use the values we were given.
994dbb271fSSean Callanan
100b9c1b51eSKate Stone // FIXME: This will need to be extended to handle Variadic functions. We'll
101b9c1b51eSKate Stone // need
102b9c1b51eSKate Stone // to pull the defined arguments out of the function, then add the types from
10305097246SAdrian Prantl // the arguments list for the variable arguments.
1044dbb271fSSean Callanan
1054dbb271fSSean Callanan uint32_t num_args = UINT32_MAX;
1064dbb271fSSean Callanan bool trust_function = false;
1074dbb271fSSean Callanan // GetArgumentCount returns -1 for an unprototyped function.
1084dbb271fSSean Callanan CompilerType function_clang_type;
109b9c1b51eSKate Stone if (m_function_ptr) {
1104dbb271fSSean Callanan function_clang_type = m_function_ptr->GetCompilerType();
111b9c1b51eSKate Stone if (function_clang_type) {
1124dbb271fSSean Callanan int num_func_args = function_clang_type.GetFunctionArgumentCount();
113b9c1b51eSKate Stone if (num_func_args >= 0) {
1144dbb271fSSean Callanan trust_function = true;
1154dbb271fSSean Callanan num_args = num_func_args;
1164dbb271fSSean Callanan }
1174dbb271fSSean Callanan }
1184dbb271fSSean Callanan }
1194dbb271fSSean Callanan
1204dbb271fSSean Callanan if (num_args == UINT32_MAX)
1214dbb271fSSean Callanan num_args = m_arg_values.GetSize();
1224dbb271fSSean Callanan
123b9c1b51eSKate Stone std::string args_buffer; // This one stores the definition of all the args in
124b9c1b51eSKate Stone // "struct caller".
125b9c1b51eSKate Stone std::string args_list_buffer; // This one stores the argument list called from
126b9c1b51eSKate Stone // the structure.
127b9c1b51eSKate Stone for (size_t i = 0; i < num_args; i++) {
1284dbb271fSSean Callanan std::string type_name;
1294dbb271fSSean Callanan
130b9c1b51eSKate Stone if (trust_function) {
131b9c1b51eSKate Stone type_name = function_clang_type.GetFunctionArgumentTypeAtIndex(i)
132b9c1b51eSKate Stone .GetTypeName()
133b9c1b51eSKate Stone .AsCString("");
134b9c1b51eSKate Stone } else {
135b9c1b51eSKate Stone CompilerType clang_qual_type =
136b9c1b51eSKate Stone m_arg_values.GetValueAtIndex(i)->GetCompilerType();
137b9c1b51eSKate Stone if (clang_qual_type) {
1384dbb271fSSean Callanan type_name = clang_qual_type.GetTypeName().AsCString("");
139b9c1b51eSKate Stone } else {
140b9c1b51eSKate Stone diagnostic_manager.Printf(
141b9c1b51eSKate Stone eDiagnosticSeverityError,
142b9c1b51eSKate Stone "Could not determine type of input value %" PRIu64 ".",
143b9c1b51eSKate Stone (uint64_t)i);
1444dbb271fSSean Callanan return 1;
1454dbb271fSSean Callanan }
1464dbb271fSSean Callanan }
1474dbb271fSSean Callanan
1484dbb271fSSean Callanan m_wrapper_function_text.append(type_name);
1494dbb271fSSean Callanan if (i < num_args - 1)
1504dbb271fSSean Callanan m_wrapper_function_text.append(", ");
1514dbb271fSSean Callanan
1524dbb271fSSean Callanan char arg_buf[32];
1534dbb271fSSean Callanan args_buffer.append(" ");
1544dbb271fSSean Callanan args_buffer.append(type_name);
1554dbb271fSSean Callanan snprintf(arg_buf, 31, "arg_%" PRIu64, (uint64_t)i);
1564dbb271fSSean Callanan args_buffer.push_back(' ');
1574dbb271fSSean Callanan args_buffer.append(arg_buf);
1584dbb271fSSean Callanan args_buffer.append(";\n");
1594dbb271fSSean Callanan
1604dbb271fSSean Callanan args_list_buffer.append("__lldb_fn_data->");
1614dbb271fSSean Callanan args_list_buffer.append(arg_buf);
1624dbb271fSSean Callanan if (i < num_args - 1)
1634dbb271fSSean Callanan args_list_buffer.append(", ");
1644dbb271fSSean Callanan }
165b9c1b51eSKate Stone m_wrapper_function_text.append(
166b9c1b51eSKate Stone ");\n"); // Close off the function calling prototype.
1674dbb271fSSean Callanan
1684dbb271fSSean Callanan m_wrapper_function_text.append(args_buffer);
1694dbb271fSSean Callanan
1704dbb271fSSean Callanan m_wrapper_function_text.append(" ");
1714dbb271fSSean Callanan m_wrapper_function_text.append(return_type_str);
1724dbb271fSSean Callanan m_wrapper_function_text.append(" return_value;");
1734dbb271fSSean Callanan m_wrapper_function_text.append("\n };\n struct ");
1744dbb271fSSean Callanan m_wrapper_function_text.append(m_wrapper_struct_name);
1754dbb271fSSean Callanan m_wrapper_function_text.append("* __lldb_fn_data = (struct ");
1764dbb271fSSean Callanan m_wrapper_function_text.append(m_wrapper_struct_name);
1774dbb271fSSean Callanan m_wrapper_function_text.append(" *) input;\n");
1784dbb271fSSean Callanan
179b9c1b51eSKate Stone m_wrapper_function_text.append(
180b9c1b51eSKate Stone " __lldb_fn_data->return_value = __lldb_fn_data->fn_ptr (");
1814dbb271fSSean Callanan m_wrapper_function_text.append(args_list_buffer);
1824dbb271fSSean Callanan m_wrapper_function_text.append(");\n}\n");
1834dbb271fSSean Callanan
184a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Expressions);
18563e5fb76SJonas Devlieghere LLDB_LOGF(log, "Expression: \n\n%s\n\n", m_wrapper_function_text.c_str());
1864dbb271fSSean Callanan
1874dbb271fSSean Callanan // Okay, now compile this expression
1884dbb271fSSean Callanan
1894dbb271fSSean Callanan lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
190b9c1b51eSKate Stone if (jit_process_sp) {
1914dbb271fSSean Callanan const bool generate_debug_info = true;
19225b486acSRaphael Isemann auto *clang_parser = new ClangExpressionParser(jit_process_sp.get(), *this,
19325b486acSRaphael Isemann generate_debug_info);
19425b486acSRaphael Isemann num_errors = clang_parser->Parse(diagnostic_manager);
19525b486acSRaphael Isemann m_parser.reset(clang_parser);
196b9c1b51eSKate Stone } else {
197e2411fabSZachary Turner diagnostic_manager.PutString(eDiagnosticSeverityError,
198b9c1b51eSKate Stone "no process - unable to inject function");
1994dbb271fSSean Callanan num_errors = 1;
2004dbb271fSSean Callanan }
2014dbb271fSSean Callanan
2024dbb271fSSean Callanan m_compiled = (num_errors == 0);
2034dbb271fSSean Callanan
2044dbb271fSSean Callanan if (!m_compiled)
2054dbb271fSSean Callanan return num_errors;
2064dbb271fSSean Callanan
2074dbb271fSSean Callanan return num_errors;
2084dbb271fSSean Callanan }
2094dbb271fSSean Callanan
2104dbb271fSSean Callanan clang::ASTConsumer *
ASTTransformer(clang::ASTConsumer * passthrough)211b9c1b51eSKate Stone ClangFunctionCaller::ClangFunctionCallerHelper::ASTTransformer(
212b9c1b51eSKate Stone clang::ASTConsumer *passthrough) {
21306412daeSJonas Devlieghere m_struct_extractor = std::make_unique<ASTStructExtractor>(
21406412daeSJonas Devlieghere passthrough, m_owner.GetWrapperStructName(), m_owner);
2154dbb271fSSean Callanan
2164dbb271fSSean Callanan return m_struct_extractor.get();
2174dbb271fSSean Callanan }
218