Googler | 741ed9c | 2021-10-01 08:00:49 +0000 | [diff] [blame] | 1 | // 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 | |
| 7 | #include "devtools/cymbal/common/clang_tool.h" |
| 8 | #include "rs_bindings_from_cc/frontend_action.h" |
| 9 | #include "third_party/absl/container/flat_hash_map.h" |
| 10 | #include "third_party/absl/strings/substitute.h" |
| 11 | |
| 12 | namespace rs_bindings_from_cc { |
| 13 | |
| 14 | static constexpr absl::string_view kVirtualInputPath = |
Michael Forster | 3f323be | 2021-10-11 07:13:28 +0000 | [diff] [blame] | 15 | "ir_from_cc_virtual_input.cc"; |
Googler | 741ed9c | 2021-10-01 08:00:49 +0000 | [diff] [blame] | 16 | |
Michael Forster | 3f323be | 2021-10-11 07:13:28 +0000 | [diff] [blame] | 17 | absl::StatusOr<IR> IrFromCc( |
| 18 | absl::Span<const absl::string_view> header_files_contents, |
| 19 | absl::Span<const absl::string_view> header_names, |
| 20 | absl::Span<const absl::string_view> args) { |
| 21 | std::vector<std::string> headers{header_names.begin(), header_names.end()}; |
Googler | 741ed9c | 2021-10-01 08:00:49 +0000 | [diff] [blame] | 22 | absl::flat_hash_map<std::string, std::string> file_contents; |
| 23 | std::string virtual_input_file_content; |
| 24 | |
| 25 | int counter = 0; |
| 26 | for (const absl::string_view header_content : header_files_contents) { |
| 27 | std::string filename( |
| 28 | absl::Substitute("test/testing_header_$0.h", counter++)); |
| 29 | file_contents.insert({filename, std::string(header_content)}); |
Googler | 741ed9c | 2021-10-01 08:00:49 +0000 | [diff] [blame] | 30 | headers.push_back(std::move(filename)); |
| 31 | } |
| 32 | |
Michael Forster | 3f323be | 2021-10-11 07:13:28 +0000 | [diff] [blame] | 33 | for (const std::string& filename : headers) { |
| 34 | absl::SubstituteAndAppend(&virtual_input_file_content, "#include \"$0\"\n", |
| 35 | filename); |
| 36 | } |
Googler | 741ed9c | 2021-10-01 08:00:49 +0000 | [diff] [blame] | 37 | file_contents.insert( |
| 38 | {std::string(kVirtualInputPath), virtual_input_file_content}); |
| 39 | |
Michael Forster | 3f323be | 2021-10-11 07:13:28 +0000 | [diff] [blame] | 40 | std::vector<std::string> args_as_strings{ |
| 41 | // This includes the path of the binary that we're pretending to be. |
| 42 | // TODO(forster): Find out where to point this. Should we use the |
| 43 | // production crosstool for this? See |
| 44 | // http://google3/devtools/cymbal/common/clang_tool.cc;l=171;rcl=385188113 |
| 45 | "clang", |
| 46 | // We only need the AST. |
| 47 | "-fsyntax-only", |
| 48 | // Parse non-doc comments that are used as documention. |
| 49 | "-fparse-all-comments"}; |
| 50 | args_as_strings.insert(args_as_strings.end(), args.begin(), args.end()); |
Googler | 741ed9c | 2021-10-01 08:00:49 +0000 | [diff] [blame] | 51 | args_as_strings.push_back(std::string(kVirtualInputPath)); |
| 52 | |
Michael Forster | 3f323be | 2021-10-11 07:13:28 +0000 | [diff] [blame] | 53 | if (IR ir; devtools::cymbal::RunToolWithClangFlagsOnCode( |
| 54 | args_as_strings, file_contents, |
| 55 | std::make_unique<FrontendAction>( |
| 56 | std::vector<absl::string_view>(headers.begin(), headers.end()), |
| 57 | ir))) { |
| 58 | return ir; |
| 59 | } else { |
| 60 | return absl::Status(absl::StatusCode::kInvalidArgument, |
| 61 | "Could not compile header contents"); |
| 62 | } |
Googler | 741ed9c | 2021-10-01 08:00:49 +0000 | [diff] [blame] | 63 | } |
| 64 | |
| 65 | } // namespace rs_bindings_from_cc |