Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +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 | |
Marcel Hlopko | 3962d18 | 2021-08-18 10:16:41 +0000 | [diff] [blame] | 5 | #include "rs_bindings_from_cc/src_code_gen.h" |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 6 | |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 7 | #include <string> |
| 8 | |
Marcel Hlopko | 65978eb | 2022-04-08 07:40:18 -0700 | [diff] [blame] | 9 | #include "common/ffi_types.h" |
Lukasz Anforowicz | 6e8b3a7 | 2022-06-02 09:10:01 -0700 | [diff] [blame] | 10 | #include "common/status_macros.h" |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 11 | #include "rs_bindings_from_cc/ir.h" |
Lukasz Anforowicz | cec7a8a | 2022-04-27 10:24:51 -0700 | [diff] [blame] | 12 | #include "clang/Format/Format.h" |
Lukasz Anforowicz | 6e8b3a7 | 2022-06-02 09:10:01 -0700 | [diff] [blame] | 13 | #include "llvm/Support/Error.h" |
Lukasz Anforowicz | cec7a8a | 2022-04-27 10:24:51 -0700 | [diff] [blame] | 14 | #include "llvm/Support/FormatVariadic.h" |
| 15 | #include "llvm/Support/JSON.h" |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 16 | |
Marcel Hlopko | f15e8ce | 2022-04-08 08:46:09 -0700 | [diff] [blame] | 17 | namespace crubit { |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 18 | |
Marcel Hlopko | 45fba97 | 2021-08-23 19:52:20 +0000 | [diff] [blame] | 19 | // FFI equivalent of `Bindings`. |
| 20 | struct FfiBindings { |
| 21 | FfiU8SliceBox rs_api; |
| 22 | FfiU8SliceBox rs_api_impl; |
| 23 | }; |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 24 | |
Marcel Hlopko | 45fba97 | 2021-08-23 19:52:20 +0000 | [diff] [blame] | 25 | // This function is implemented in Rust. |
Lukasz Anforowicz | 54ff318 | 2022-05-06 07:17:58 -0700 | [diff] [blame] | 26 | extern "C" FfiBindings GenerateBindingsImpl(FfiU8Slice json, |
Lukasz Anforowicz | dd90770 | 2022-05-06 09:24:07 -0700 | [diff] [blame] | 27 | FfiU8Slice crubit_support_path, |
Lukasz Anforowicz | d7d68f0 | 2022-05-26 07:41:02 -0700 | [diff] [blame] | 28 | FfiU8Slice rustfmt_exe_path, |
Lukasz Anforowicz | 54ff318 | 2022-05-06 07:17:58 -0700 | [diff] [blame] | 29 | FfiU8Slice rustfmt_config_path); |
Marcel Hlopko | 45fba97 | 2021-08-23 19:52:20 +0000 | [diff] [blame] | 30 | |
| 31 | // Creates `Bindings` instance from copied data from `ffi_bindings`. |
Lukasz Anforowicz | 6e8b3a7 | 2022-06-02 09:10:01 -0700 | [diff] [blame] | 32 | static absl::StatusOr<Bindings> MakeBindingsFromFfiBindings( |
| 33 | const FfiBindings& ffi_bindings) { |
Marcel Hlopko | 45fba97 | 2021-08-23 19:52:20 +0000 | [diff] [blame] | 34 | Bindings bindings; |
| 35 | |
Marcel Hlopko | e936aac | 2021-08-24 20:52:27 +0000 | [diff] [blame] | 36 | const FfiU8SliceBox& rs_api = ffi_bindings.rs_api; |
| 37 | const FfiU8SliceBox& rs_api_impl = ffi_bindings.rs_api_impl; |
Marcel Hlopko | 45fba97 | 2021-08-23 19:52:20 +0000 | [diff] [blame] | 38 | |
| 39 | bindings.rs_api = std::string(rs_api.ptr, rs_api.size); |
Michael Forster | f74c149 | 2021-09-17 09:30:10 +0000 | [diff] [blame] | 40 | |
| 41 | std::string impl{rs_api_impl.ptr, rs_api_impl.size}; |
Lukasz Anforowicz | 6e8b3a7 | 2022-06-02 09:10:01 -0700 | [diff] [blame] | 42 | llvm::Expected<std::string> maybe_formatted = |
| 43 | clang::tooling::applyAllReplacements( |
| 44 | impl, |
| 45 | clang::format::reformat( |
| 46 | clang::format::getGoogleStyle(clang::format::FormatStyle::LK_Cpp), |
| 47 | impl, clang::tooling::Range(0, impl.size()), "<stdin>")); |
| 48 | if (llvm::Error error = maybe_formatted.takeError()) { |
| 49 | return absl::InternalError(absl::StrCat("Failed to format rs_api_impl: ", |
| 50 | toString(std::move(error)))); |
| 51 | } |
| 52 | bindings.rs_api_impl = *maybe_formatted; |
Marcel Hlopko | 45fba97 | 2021-08-23 19:52:20 +0000 | [diff] [blame] | 53 | |
| 54 | return bindings; |
| 55 | } |
| 56 | |
| 57 | // Deallocates given `ffi_bindings` instance that was created in Rust. |
| 58 | static void FreeFfiBindings(FfiBindings ffi_bindings) { |
| 59 | FreeFfiU8SliceBox(ffi_bindings.rs_api); |
| 60 | FreeFfiU8SliceBox(ffi_bindings.rs_api_impl); |
| 61 | } |
| 62 | |
Lukasz Anforowicz | 6e8b3a7 | 2022-06-02 09:10:01 -0700 | [diff] [blame] | 63 | absl::StatusOr<Bindings> GenerateBindings( |
| 64 | const IR& ir, absl::string_view crubit_support_path, |
| 65 | absl::string_view rustfmt_exe_path, absl::string_view rustfmt_config_path) { |
Lukasz Anforowicz | 3b4be12 | 2022-03-16 00:09:35 +0000 | [diff] [blame] | 66 | std::string json = llvm::formatv("{0}", ir.ToJson()); |
Lukasz Anforowicz | 54ff318 | 2022-05-06 07:17:58 -0700 | [diff] [blame] | 67 | |
| 68 | FfiBindings ffi_bindings = GenerateBindingsImpl( |
Lukasz Anforowicz | dd90770 | 2022-05-06 09:24:07 -0700 | [diff] [blame] | 69 | MakeFfiU8Slice(json), MakeFfiU8Slice(crubit_support_path), |
Lukasz Anforowicz | d7d68f0 | 2022-05-26 07:41:02 -0700 | [diff] [blame] | 70 | MakeFfiU8Slice(rustfmt_exe_path), MakeFfiU8Slice(rustfmt_config_path)); |
Lukasz Anforowicz | 6e8b3a7 | 2022-06-02 09:10:01 -0700 | [diff] [blame] | 71 | CRUBIT_ASSIGN_OR_RETURN(Bindings bindings, |
| 72 | MakeBindingsFromFfiBindings(ffi_bindings)); |
Marcel Hlopko | 45fba97 | 2021-08-23 19:52:20 +0000 | [diff] [blame] | 73 | FreeFfiBindings(ffi_bindings); |
| 74 | return bindings; |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 75 | } |
| 76 | |
Marcel Hlopko | f15e8ce | 2022-04-08 08:46:09 -0700 | [diff] [blame] | 77 | } // namespace crubit |