blob: ba2f07f0ae2d7b839faff3aef577735be41ba1dc [file] [log] [blame]
Marcel Hlopko42abfc82021-08-09 07:03:17 +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
Marcel Hlopko3962d182021-08-18 10:16:41 +00005#include "rs_bindings_from_cc/src_code_gen.h"
Marcel Hlopko42abfc82021-08-09 07:03:17 +00006
Marcel Hlopko42abfc82021-08-09 07:03:17 +00007#include <string>
8
Marcel Hlopko65978eb2022-04-08 07:40:18 -07009#include "common/ffi_types.h"
Lukasz Anforowicz6e8b3a72022-06-02 09:10:01 -070010#include "common/status_macros.h"
Marcel Hlopko42abfc82021-08-09 07:03:17 +000011#include "rs_bindings_from_cc/ir.h"
Lukasz Anforowiczcec7a8a2022-04-27 10:24:51 -070012#include "clang/Format/Format.h"
Lukasz Anforowicz6e8b3a72022-06-02 09:10:01 -070013#include "llvm/Support/Error.h"
Lukasz Anforowiczcec7a8a2022-04-27 10:24:51 -070014#include "llvm/Support/FormatVariadic.h"
15#include "llvm/Support/JSON.h"
Marcel Hlopko42abfc82021-08-09 07:03:17 +000016
Marcel Hlopkof15e8ce2022-04-08 08:46:09 -070017namespace crubit {
Marcel Hlopko42abfc82021-08-09 07:03:17 +000018
Marcel Hlopko45fba972021-08-23 19:52:20 +000019// FFI equivalent of `Bindings`.
20struct FfiBindings {
21 FfiU8SliceBox rs_api;
22 FfiU8SliceBox rs_api_impl;
23};
Marcel Hlopko42abfc82021-08-09 07:03:17 +000024
Marcel Hlopko45fba972021-08-23 19:52:20 +000025// This function is implemented in Rust.
Lukasz Anforowicz54ff3182022-05-06 07:17:58 -070026extern "C" FfiBindings GenerateBindingsImpl(FfiU8Slice json,
Lukasz Anforowiczdd907702022-05-06 09:24:07 -070027 FfiU8Slice crubit_support_path,
Lukasz Anforowiczd7d68f02022-05-26 07:41:02 -070028 FfiU8Slice rustfmt_exe_path,
Lukasz Anforowicz54ff3182022-05-06 07:17:58 -070029 FfiU8Slice rustfmt_config_path);
Marcel Hlopko45fba972021-08-23 19:52:20 +000030
31// Creates `Bindings` instance from copied data from `ffi_bindings`.
Lukasz Anforowicz6e8b3a72022-06-02 09:10:01 -070032static absl::StatusOr<Bindings> MakeBindingsFromFfiBindings(
33 const FfiBindings& ffi_bindings) {
Marcel Hlopko45fba972021-08-23 19:52:20 +000034 Bindings bindings;
35
Marcel Hlopkoe936aac2021-08-24 20:52:27 +000036 const FfiU8SliceBox& rs_api = ffi_bindings.rs_api;
37 const FfiU8SliceBox& rs_api_impl = ffi_bindings.rs_api_impl;
Marcel Hlopko45fba972021-08-23 19:52:20 +000038
39 bindings.rs_api = std::string(rs_api.ptr, rs_api.size);
Michael Forsterf74c1492021-09-17 09:30:10 +000040
41 std::string impl{rs_api_impl.ptr, rs_api_impl.size};
Lukasz Anforowicz6e8b3a72022-06-02 09:10:01 -070042 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 Hlopko45fba972021-08-23 19:52:20 +000053
54 return bindings;
55}
56
57// Deallocates given `ffi_bindings` instance that was created in Rust.
58static void FreeFfiBindings(FfiBindings ffi_bindings) {
59 FreeFfiU8SliceBox(ffi_bindings.rs_api);
60 FreeFfiU8SliceBox(ffi_bindings.rs_api_impl);
61}
62
Lukasz Anforowicz6e8b3a72022-06-02 09:10:01 -070063absl::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 Anforowicz3b4be122022-03-16 00:09:35 +000066 std::string json = llvm::formatv("{0}", ir.ToJson());
Lukasz Anforowicz54ff3182022-05-06 07:17:58 -070067
68 FfiBindings ffi_bindings = GenerateBindingsImpl(
Lukasz Anforowiczdd907702022-05-06 09:24:07 -070069 MakeFfiU8Slice(json), MakeFfiU8Slice(crubit_support_path),
Lukasz Anforowiczd7d68f02022-05-26 07:41:02 -070070 MakeFfiU8Slice(rustfmt_exe_path), MakeFfiU8Slice(rustfmt_config_path));
Lukasz Anforowicz6e8b3a72022-06-02 09:10:01 -070071 CRUBIT_ASSIGN_OR_RETURN(Bindings bindings,
72 MakeBindingsFromFfiBindings(ffi_bindings));
Marcel Hlopko45fba972021-08-23 19:52:20 +000073 FreeFfiBindings(ffi_bindings);
74 return bindings;
Marcel Hlopko42abfc82021-08-09 07:03:17 +000075}
76
Marcel Hlopkof15e8ce2022-04-08 08:46:09 -070077} // namespace crubit