1#![recursion_limit = "256"]
5#![feature(rustc_private)]
6#![allow(clippy::arc_with_non_send_sync)]
7#![allow(clippy::borrowed_box)]
8#![allow(clippy::derivable_impls)]
9#![allow(clippy::field_reassign_with_default)]
10#![allow(clippy::manual_map)]
11#![allow(clippy::mem_replace_with_default)]
12#![allow(clippy::useless_format)]
13#![feature(deref_patterns)]
14#![feature(iter_array_chunks)]
15#![feature(iterator_try_collect)]
16#![feature(macro_metavar_expr)]
17#![feature(sized_hierarchy)]
18#![feature(trait_alias)]
19#![feature(type_changing_struct_update)]
20
21extern crate rustc_abi;
22extern crate rustc_apfloat;
23extern crate rustc_ast;
24extern crate rustc_ast_pretty;
25extern crate rustc_attr_ir;
26extern crate rustc_const_eval;
27extern crate rustc_data_structures;
28extern crate rustc_driver;
29extern crate rustc_error_messages;
30extern crate rustc_errors;
31extern crate rustc_hashes;
32extern crate rustc_hir;
33extern crate rustc_hir_analysis;
34extern crate rustc_index;
35extern crate rustc_infer;
36extern crate rustc_interface;
37extern crate rustc_lexer;
38extern crate rustc_middle;
39extern crate rustc_mir_build;
40extern crate rustc_mir_transform;
41extern crate rustc_session;
42extern crate rustc_span;
43extern crate rustc_target;
44extern crate rustc_trait_selection;
45extern crate rustc_type_ir;
46
47#[macro_use]
48extern crate charon_lib;
49
50mod driver;
51#[macro_use]
52pub mod hax;
53#[allow(unused)]
54#[path = "../charon/toolchain.rs"]
55mod toolchain;
56mod translate;
57
58use charon_lib::{export, logger, transform::run_transformation_passes};
59use std::{fmt, panic};
60
61pub enum CharonFailure {
62 CharonError(usize),
64 RustcError,
65 Panic,
66 Serialize,
67}
68
69impl fmt::Display for CharonFailure {
70 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71 match self {
72 CharonFailure::RustcError => write!(f, "Code failed to compile")?,
73 CharonFailure::CharonError(err_count) => write!(
74 f,
75 "Charon failed to translate this code ({err_count} errors)"
76 )?,
77 CharonFailure::Panic => write!(f, "Compilation panicked")?,
78 CharonFailure::Serialize => write!(f, "Could not serialize output file")?,
79 }
80 Ok(())
81 }
82}
83
84fn run_charon() -> Result<usize, CharonFailure> {
86 let Some((mut ctx, options)) = driver::run_rustc_driver()? else {
88 return Ok(0);
90 };
91
92 charon_lib::timing::time("transformation-passes", || {
95 run_transformation_passes(&options, &mut ctx)
96 });
97
98 let error_count = ctx.errors.borrow().error_count;
99
100 let targets = options.targets(&ctx.translated.crate_name);
102 trace!("Targets: {:?}", targets);
103 let crate_name = ctx.translated.crate_name.clone();
104 charon_lib::timing::time("serialize", || {
105 export::CrateData::new(ctx).serialize_to_files(targets)
106 })
107 .map_err(|()| CharonFailure::Serialize)?;
108 charon_lib::timing::report(&crate_name);
109
110 if options.error_on_warnings && error_count != 0 {
111 return Err(CharonFailure::CharonError(error_count));
112 }
113
114 Ok(error_count)
115}
116
117fn main() {
118 logger::initialize_logger();
120
121 let res = panic::catch_unwind(run_charon)
123 .map_err(|_| CharonFailure::Panic)
124 .and_then(|x| x);
125
126 match res {
127 Ok(warn_count) => {
128 if warn_count != 0 {
129 let msg = format!("The extraction generated {} warnings", warn_count);
130 eprintln!("warning: {}", msg);
131 }
132 }
133 Err(err) => {
134 log::error!("{err}");
135 let exit_code = match err {
136 CharonFailure::CharonError(_) | CharonFailure::Serialize => 1,
137 CharonFailure::RustcError => 2,
138 CharonFailure::Panic => 101,
140 };
141 std::process::exit(exit_code);
142 }
143 }
144}