]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_codegen_gcc/src/allocator.rs
New upstream version 1.70.0+dfsg1
[rustc.git] / compiler / rustc_codegen_gcc / src / allocator.rs
CommitLineData
353b0b11
FG
1#[cfg(feature="master")]
2use gccjit::FnAttribute;
5e7ed085 3use gccjit::{FunctionType, GlobalKind, ToRValue};
c295e0f8
XL
4use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
5use rustc_middle::bug;
6use rustc_middle::ty::TyCtxt;
5e7ed085 7use rustc_session::config::OomStrategy;
c295e0f8
XL
8use rustc_span::symbol::sym;
9
10use crate::GccContext;
11
487cf647 12pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_name: &str, kind: AllocatorKind, alloc_error_handler_kind: AllocatorKind) {
c295e0f8
XL
13 let context = &mods.context;
14 let usize =
15 match tcx.sess.target.pointer_width {
16 16 => context.new_type::<u16>(),
17 32 => context.new_type::<u32>(),
18 64 => context.new_type::<u64>(),
19 tws => bug!("Unsupported target word size for int: {}", tws),
20 };
21 let i8 = context.new_type::<i8>();
22 let i8p = i8.make_pointer();
23 let void = context.new_type::<()>();
24
25 for method in ALLOCATOR_METHODS {
26 let mut types = Vec::with_capacity(method.inputs.len());
27 for ty in method.inputs.iter() {
28 match *ty {
29 AllocatorTy::Layout => {
30 types.push(usize);
31 types.push(usize);
32 }
33 AllocatorTy::Ptr => types.push(i8p),
34 AllocatorTy::Usize => types.push(usize),
35
36 AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"),
37 }
38 }
39 let output = match method.output {
40 AllocatorTy::ResultPtr => Some(i8p),
41 AllocatorTy::Unit => None,
42
43 AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
44 panic!("invalid allocator output")
45 }
46 };
47 let name = format!("__rust_{}", method.name);
48
49 let args: Vec<_> = types.iter().enumerate()
50 .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
51 .collect();
52 let func = context.new_function(None, FunctionType::Exported, output.unwrap_or(void), &args, name, false);
53
54 if tcx.sess.target.options.default_hidden_visibility {
353b0b11
FG
55 #[cfg(feature="master")]
56 func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
c295e0f8
XL
57 }
58 if tcx.sess.must_emit_unwind_tables() {
59 // TODO(antoyo): emit unwind tables.
60 }
61
62 let callee = kind.fn_name(method.name);
63 let args: Vec<_> = types.iter().enumerate()
64 .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
65 .collect();
66 let callee = context.new_function(None, FunctionType::Extern, output.unwrap_or(void), &args, callee, false);
353b0b11
FG
67 #[cfg(feature="master")]
68 callee.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
c295e0f8
XL
69
70 let block = func.new_block("entry");
71
72 let args = args
73 .iter()
74 .enumerate()
75 .map(|(i, _)| func.get_param(i as i32).to_rvalue())
76 .collect::<Vec<_>>();
77 let ret = context.new_call(None, callee, &args);
78 //llvm::LLVMSetTailCall(ret, True);
79 if output.is_some() {
80 block.end_with_return(None, ret);
81 }
82 else {
83 block.end_with_void_return(None);
84 }
85
86 // TODO(@Commeownist): Check if we need to emit some extra debugging info in certain circumstances
87 // as described in https://github.com/rust-lang/rust/commit/77a96ed5646f7c3ee8897693decc4626fe380643
88 }
89
90 let types = [usize, usize];
91 let name = "__rust_alloc_error_handler".to_string();
92 let args: Vec<_> = types.iter().enumerate()
93 .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
94 .collect();
95 let func = context.new_function(None, FunctionType::Exported, void, &args, name, false);
96
353b0b11
FG
97 if tcx.sess.target.default_hidden_visibility {
98 #[cfg(feature="master")]
99 func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
100 }
101
487cf647 102 let callee = alloc_error_handler_kind.fn_name(sym::oom);
c295e0f8
XL
103 let args: Vec<_> = types.iter().enumerate()
104 .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
105 .collect();
106 let callee = context.new_function(None, FunctionType::Extern, void, &args, callee, false);
353b0b11
FG
107 #[cfg(feature="master")]
108 callee.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
c295e0f8
XL
109
110 let block = func.new_block("entry");
111
112 let args = args
113 .iter()
114 .enumerate()
115 .map(|(i, _)| func.get_param(i as i32).to_rvalue())
116 .collect::<Vec<_>>();
117 let _ret = context.new_call(None, callee, &args);
118 //llvm::LLVMSetTailCall(ret, True);
119 block.end_with_void_return(None);
5e7ed085
FG
120
121 let name = OomStrategy::SYMBOL.to_string();
122 let global = context.new_global(None, GlobalKind::Exported, i8, name);
064997fb 123 let value = tcx.sess.opts.unstable_opts.oom.should_panic();
5e7ed085
FG
124 let value = context.new_rvalue_from_int(i8, value as i32);
125 global.global_set_initializer_rvalue(value);
c295e0f8 126}