blob: 4f2be3f447c72db9c2d796ba0eec3981a82698ad [file] [log] [blame]
Googler741ed9c2021-10-01 08:00:49 +00001// Part of the Crubit project, under the Apache License v2.0 with LLVM
2// Exceptions. See /LICENSE for license information.
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
5#include "rs_bindings_from_cc/ir_from_cc.h"
6
Marcel Hlopko20f4ce42021-11-02 08:20:00 +00007#include <memory>
8#include <string>
9#include <utility>
10#include <vector>
11
Lukasz Anforowiczcec7a8a2022-04-27 10:24:51 -070012#include "absl/container/flat_hash_map.h"
13#include "absl/status/status.h"
14#include "absl/status/statusor.h"
15#include "absl/strings/string_view.h"
16#include "absl/strings/substitute.h"
17#include "absl/types/span.h"
Marco Polettic61bcc42022-04-08 12:54:30 -070018#include "common/check.h"
Marcel Hlopko3b254b32022-03-09 14:10:49 +000019#include "rs_bindings_from_cc/bazel_types.h"
20#include "rs_bindings_from_cc/frontend_action.h"
Marcel Hlopko3b254b32022-03-09 14:10:49 +000021#include "rs_bindings_from_cc/ir.h"
Lukasz Anforowiczcec7a8a2022-04-27 10:24:51 -070022#include "clang/Frontend/FrontendAction.h"
23#include "clang/Tooling/Tooling.h"
Googler741ed9c2021-10-01 08:00:49 +000024
Marcel Hlopkof15e8ce2022-04-08 08:46:09 -070025namespace crubit {
Googler741ed9c2021-10-01 08:00:49 +000026
Marcel Hlopko7aa38a72021-11-11 07:39:51 +000027static constexpr absl::string_view kVirtualHeaderPath =
28 "ir_from_cc_virtual_header.h";
Googler741ed9c2021-10-01 08:00:49 +000029static constexpr absl::string_view kVirtualInputPath =
Michael Forster3f323be2021-10-11 07:13:28 +000030 "ir_from_cc_virtual_input.cc";
Googler741ed9c2021-10-01 08:00:49 +000031
Michael Forster3f323be2021-10-11 07:13:28 +000032absl::StatusOr<IR> IrFromCc(
Googler6c3de122022-03-28 11:40:41 +000033 const absl::string_view extra_source_code, const BazelLabel current_target,
Marcel Hlopko7aa38a72021-11-11 07:39:51 +000034 absl::Span<const HeaderName> public_headers,
35 absl::flat_hash_map<const HeaderName, const std::string>
36 virtual_headers_contents,
Googler6c3de122022-03-28 11:40:41 +000037 absl::flat_hash_map<const HeaderName, const BazelLabel> headers_to_targets,
Marcel Hlopko2ee23912022-05-09 06:13:55 -070038 absl::Span<const absl::string_view> args,
39 absl::Span<const std::string> extra_instantiations) {
Lukasz Anforowicz34ad7f72022-03-17 16:05:28 +000040 // Caller should verify that the inputs are not empty.
Marcel Hlopko2ee23912022-05-09 06:13:55 -070041 // TODO(b/440066049): Generate a source file for requested instantiations once
42 // cl/430823388 is submitted.
43 CRUBIT_CHECK(!extra_source_code.empty() || !public_headers.empty() ||
44 !extra_instantiations.empty());
45 CRUBIT_CHECK(!extra_source_code.empty() || !headers_to_targets.empty() ||
46 !extra_instantiations.empty());
Lukasz Anforowicz34ad7f72022-03-17 16:05:28 +000047
Googler7ea9fbb2022-03-11 02:56:03 +000048 std::vector<HeaderName> entrypoint_headers(public_headers.begin(),
49 public_headers.end());
Rosica Dejanovska5fc4caf2022-01-31 13:54:32 +000050 clang::tooling::FileContentMappings file_contents;
Googler741ed9c2021-10-01 08:00:49 +000051
Marcel Hlopko7aa38a72021-11-11 07:39:51 +000052 for (auto const& name_and_content : virtual_headers_contents) {
Rosica Dejanovska5fc4caf2022-01-31 13:54:32 +000053 file_contents.push_back({std::string(name_and_content.first.IncludePath()),
54 name_and_content.second});
Marcel Hlopko7aa38a72021-11-11 07:39:51 +000055 }
56 if (!extra_source_code.empty()) {
Rosica Dejanovska5fc4caf2022-01-31 13:54:32 +000057 file_contents.push_back(
Marcel Hlopko7aa38a72021-11-11 07:39:51 +000058 {std::string(kVirtualHeaderPath), std::string(extra_source_code)});
59 HeaderName header_name = HeaderName(std::string(kVirtualHeaderPath));
60 entrypoint_headers.push_back(header_name);
61 headers_to_targets.insert({header_name, current_target});
Googler741ed9c2021-10-01 08:00:49 +000062 }
63
Marcel Hlopko7aa38a72021-11-11 07:39:51 +000064 std::string virtual_input_file_content;
65 for (const HeaderName& header_name : entrypoint_headers) {
Michael Forster3f323be2021-10-11 07:13:28 +000066 absl::SubstituteAndAppend(&virtual_input_file_content, "#include \"$0\"\n",
Marcel Hlopko7aa38a72021-11-11 07:39:51 +000067 header_name.IncludePath());
Michael Forster3f323be2021-10-11 07:13:28 +000068 }
Googler741ed9c2021-10-01 08:00:49 +000069
Michael Forster3f323be2021-10-11 07:13:28 +000070 std::vector<std::string> args_as_strings{
Rosica Dejanovska5fc4caf2022-01-31 13:54:32 +000071 // Parse non-doc comments that are used as documention
Michael Forster3f323be2021-10-11 07:13:28 +000072 "-fparse-all-comments"};
73 args_as_strings.insert(args_as_strings.end(), args.begin(), args.end());
Googler741ed9c2021-10-01 08:00:49 +000074
Michael Forster64217b42022-04-22 05:48:54 -070075 if (Invocation invocation(current_target, entrypoint_headers,
76 headers_to_targets);
Rosica Dejanovska5fc4caf2022-01-31 13:54:32 +000077 clang::tooling::runToolOnCodeWithArgs(
78 std::make_unique<FrontendAction>(invocation),
79 virtual_input_file_content, args_as_strings, kVirtualInputPath,
80 "rs_bindings_from_cc",
81 std::make_shared<clang::PCHContainerOperations>(), file_contents)) {
Michael Forstera49d2e62022-01-28 07:26:40 +000082 return invocation.ir_;
Michael Forster3f323be2021-10-11 07:13:28 +000083 } else {
84 return absl::Status(absl::StatusCode::kInvalidArgument,
85 "Could not compile header contents");
86 }
Googler741ed9c2021-10-01 08:00:49 +000087}
88
Marcel Hlopkof15e8ce2022-04-08 08:46:09 -070089} // namespace crubit