]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_codegen_gcc/src/declare.rs
New upstream version 1.67.1+dfsg1
[rustc.git] / compiler / rustc_codegen_gcc / src / declare.rs
CommitLineData
c295e0f8
XL
1use gccjit::{Function, FunctionType, GlobalKind, LValue, RValue, Type};
2use rustc_codegen_ssa::traits::BaseTypeMethods;
3use rustc_middle::ty::Ty;
4use rustc_span::Symbol;
5use rustc_target::abi::call::FnAbi;
6
7use crate::abi::FnAbiGccExt;
5e7ed085 8use crate::context::CodegenCx;
c295e0f8
XL
9use crate::intrinsic::llvm;
10
11impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
12 pub fn get_or_insert_global(&self, name: &str, ty: Type<'gcc>, is_tls: bool, link_section: Option<Symbol>) -> LValue<'gcc> {
13 if self.globals.borrow().contains_key(name) {
923072b8 14 let typ = self.globals.borrow()[name].get_type();
c295e0f8
XL
15 let global = self.context.new_global(None, GlobalKind::Imported, typ, name);
16 if is_tls {
17 global.set_tls_model(self.tls_model);
18 }
19 if let Some(link_section) = link_section {
a2a8927a 20 global.set_link_section(link_section.as_str());
c295e0f8
XL
21 }
22 global
23 }
24 else {
5e7ed085 25 self.declare_global(name, ty, GlobalKind::Exported, is_tls, link_section)
c295e0f8
XL
26 }
27 }
28
29 pub fn declare_unnamed_global(&self, ty: Type<'gcc>) -> LValue<'gcc> {
5e7ed085
FG
30 let name = self.generate_local_symbol_name("global");
31 self.context.new_global(None, GlobalKind::Internal, ty, &name)
c295e0f8
XL
32 }
33
34 pub fn declare_global_with_linkage(&self, name: &str, ty: Type<'gcc>, linkage: GlobalKind) -> LValue<'gcc> {
35 let global = self.context.new_global(None, linkage, ty, name);
36 let global_address = global.get_address(None);
37 self.globals.borrow_mut().insert(name.to_string(), global_address);
38 global
39 }
40
41 /*pub fn declare_func(&self, name: &str, return_type: Type<'gcc>, params: &[Type<'gcc>], variadic: bool) -> RValue<'gcc> {
42 self.linkage.set(FunctionType::Exported);
43 let func = declare_raw_fn(self, name, () /*llvm::CCallConv*/, return_type, params, variadic);
44 // FIXME(antoyo): this is a wrong cast. That requires changing the compiler API.
45 unsafe { std::mem::transmute(func) }
46 }*/
47
5e7ed085
FG
48 pub fn declare_global(&self, name: &str, ty: Type<'gcc>, global_kind: GlobalKind, is_tls: bool, link_section: Option<Symbol>) -> LValue<'gcc> {
49 let global = self.context.new_global(None, global_kind, ty, name);
c295e0f8
XL
50 if is_tls {
51 global.set_tls_model(self.tls_model);
52 }
53 if let Some(link_section) = link_section {
a2a8927a 54 global.set_link_section(link_section.as_str());
c295e0f8
XL
55 }
56 let global_address = global.get_address(None);
57 self.globals.borrow_mut().insert(name.to_string(), global_address);
58 global
59 }
60
61 pub fn declare_private_global(&self, name: &str, ty: Type<'gcc>) -> LValue<'gcc> {
62 let global = self.context.new_global(None, GlobalKind::Internal, ty, name);
63 let global_address = global.get_address(None);
64 self.globals.borrow_mut().insert(name.to_string(), global_address);
65 global
66 }
67
487cf647 68 pub fn declare_entry_fn(&self, name: &str, _fn_type: Type<'gcc>, callconv: () /*llvm::CCallConv*/) -> RValue<'gcc> {
c295e0f8
XL
69 // TODO(antoyo): use the fn_type parameter.
70 let const_string = self.context.new_type::<u8>().make_pointer().make_pointer();
71 let return_type = self.type_i32();
72 let variadic = false;
73 self.linkage.set(FunctionType::Exported);
487cf647 74 let func = declare_raw_fn(self, name, callconv, return_type, &[self.type_i32(), const_string], variadic);
c295e0f8
XL
75 // NOTE: it is needed to set the current_func here as well, because get_fn() is not called
76 // for the main function.
77 *self.current_func.borrow_mut() = Some(func);
78 // FIXME(antoyo): this is a wrong cast. That requires changing the compiler API.
79 unsafe { std::mem::transmute(func) }
80 }
81
82 pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> RValue<'gcc> {
5e7ed085 83 let (return_type, params, variadic, on_stack_param_indices) = fn_abi.gcc_type(self);
c295e0f8 84 let func = declare_raw_fn(self, name, () /*fn_abi.llvm_cconv()*/, return_type, &params, variadic);
5e7ed085 85 self.on_stack_function_params.borrow_mut().insert(func, on_stack_param_indices);
c295e0f8
XL
86 // FIXME(antoyo): this is a wrong cast. That requires changing the compiler API.
87 unsafe { std::mem::transmute(func) }
88 }
89
90 pub fn define_global(&self, name: &str, ty: Type<'gcc>, is_tls: bool, link_section: Option<Symbol>) -> LValue<'gcc> {
91 self.get_or_insert_global(name, ty, is_tls, link_section)
92 }
93
94 pub fn get_declared_value(&self, name: &str) -> Option<RValue<'gcc>> {
95 // TODO(antoyo): use a different field than globals, because this seems to return a function?
96 self.globals.borrow().get(name).cloned()
97 }
98}
99
100/// Declare a function.
101///
102/// If there’s a value with the same name already declared, the function will
103/// update the declaration and return existing Value instead.
104fn declare_raw_fn<'gcc>(cx: &CodegenCx<'gcc, '_>, name: &str, _callconv: () /*llvm::CallConv*/, return_type: Type<'gcc>, param_types: &[Type<'gcc>], variadic: bool) -> Function<'gcc> {
105 if name.starts_with("llvm.") {
923072b8
FG
106 let intrinsic = llvm::intrinsic(name, cx);
107 cx.intrinsics.borrow_mut().insert(name.to_string(), intrinsic);
108 return intrinsic;
c295e0f8
XL
109 }
110 let func =
111 if cx.functions.borrow().contains_key(name) {
923072b8 112 cx.functions.borrow()[name]
c295e0f8
XL
113 }
114 else {
115 let params: Vec<_> = param_types.into_iter().enumerate()
116 .map(|(index, param)| cx.context.new_parameter(None, *param, &format!("param{}", index))) // TODO(antoyo): set name.
117 .collect();
118 let func = cx.context.new_function(None, cx.linkage.get(), return_type, &params, mangle_name(name), variadic);
119 cx.functions.borrow_mut().insert(name.to_string(), func);
120 func
121 };
122
123 // TODO(antoyo): set function calling convention.
124 // TODO(antoyo): set unnamed address.
125 // TODO(antoyo): set no red zone function attribute.
126 // TODO(antoyo): set attributes for optimisation.
127 // TODO(antoyo): set attributes for non lazy bind.
128
129 // FIXME(antoyo): invalid cast.
130 func
131}
132
133// FIXME(antoyo): this is a hack because libgccjit currently only supports alpha, num and _.
134// Unsupported characters: `$` and `.`.
135pub fn mangle_name(name: &str) -> String {
136 name.replace(|char: char| {
137 if !char.is_alphanumeric() && char != '_' {
138 debug_assert!("$.".contains(char), "Unsupported char in function name: {}", char);
139 true
140 }
141 else {
142 false
143 }
144 }, "_")
145}