Skip to content

Commit 63c548d

Browse files
authored
Rollup merge of rust-lang#137549 - oli-obk:llvm-ffi, r=davidtwco
Clean up various LLVM FFI things in codegen_llvm cc ```@ZuseZ4``` I touched some autodiff parts The major change of this PR is [bfd88ce](rust-lang@bfd88ce) which makes `CodegenCx` generic just like `GenericBuilder` The other commits mostly took advantage of the new feature of making extern functions safe, but also just used some wrappers that were already there and shrunk unsafe blocks. best reviewed commit-by-commit
2 parents f5a143f + 553828c commit 63c548d

File tree

26 files changed

+335
-367
lines changed

26 files changed

+335
-367
lines changed

compiler/rustc_codegen_gcc/src/abi.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::context::CodegenCx;
1616
use crate::intrinsic::ArgAbiExt;
1717
use crate::type_of::LayoutGccExt;
1818

19-
impl<'a, 'gcc, 'tcx> AbiBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
19+
impl AbiBuilderMethods for Builder<'_, '_, '_> {
2020
fn get_param(&mut self, index: usize) -> Self::Value {
2121
let func = self.current_func();
2222
let param = func.get_param(index as i32);

compiler/rustc_codegen_gcc/src/common.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ pub fn type_is_pointer(typ: Type<'_>) -> bool {
5959
typ.get_pointee().is_some()
6060
}
6161

62-
impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
62+
impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
6363
fn const_null(&self, typ: Type<'gcc>) -> RValue<'gcc> {
6464
if type_is_pointer(typ) { self.context.new_null(typ) } else { self.const_int(typ, 0) }
6565
}
@@ -257,7 +257,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
257257
}
258258
}
259259

260-
fn const_data_from_alloc(&self, alloc: ConstAllocation<'tcx>) -> Self::Value {
260+
fn const_data_from_alloc(&self, alloc: ConstAllocation<'_>) -> Self::Value {
261261
const_alloc_to_gcc(self, alloc)
262262
}
263263

compiler/rustc_codegen_gcc/src/consts.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -302,9 +302,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
302302
}
303303
}
304304

305-
pub fn const_alloc_to_gcc<'gcc, 'tcx>(
306-
cx: &CodegenCx<'gcc, 'tcx>,
307-
alloc: ConstAllocation<'tcx>,
305+
pub fn const_alloc_to_gcc<'gcc>(
306+
cx: &CodegenCx<'gcc, '_>,
307+
alloc: ConstAllocation<'_>,
308308
) -> RValue<'gcc> {
309309
let alloc = alloc.inner();
310310
let mut llvals = Vec::with_capacity(alloc.provenance().ptrs().len() + 1);

compiler/rustc_codegen_gcc/src/type_.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
123123
}
124124
}
125125

126-
impl<'gcc, 'tcx> BaseTypeCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
126+
impl<'gcc, 'tcx> BaseTypeCodegenMethods for CodegenCx<'gcc, 'tcx> {
127127
fn type_i8(&self) -> Type<'gcc> {
128128
self.i8_type
129129
}

compiler/rustc_codegen_llvm/src/abi.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -654,7 +654,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
654654
}
655655
}
656656

657-
impl<'tcx> AbiBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
657+
impl AbiBuilderMethods for Builder<'_, '_, '_> {
658658
fn get_param(&mut self, index: usize) -> Self::Value {
659659
llvm::get_param(self.llfn(), index as c_uint)
660660
}

compiler/rustc_codegen_llvm/src/allocator.rs

+70-86
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,31 @@ use rustc_ast::expand::allocator::{
33
ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE,
44
alloc_error_handler_name, default_fn_name, global_fn_name,
55
};
6+
use rustc_codegen_ssa::traits::BaseTypeCodegenMethods as _;
67
use rustc_middle::bug;
78
use rustc_middle::ty::TyCtxt;
89
use rustc_session::config::{DebugInfo, OomStrategy};
910

10-
use crate::common::AsCCharPtr;
11-
use crate::llvm::{self, Context, False, Module, True, Type};
12-
use crate::{ModuleLlvm, attributes, debuginfo};
11+
use crate::builder::SBuilder;
12+
use crate::declare::declare_simple_fn;
13+
use crate::llvm::{self, False, True, Type};
14+
use crate::{SimpleCx, attributes, debuginfo};
1315

1416
pub(crate) unsafe fn codegen(
1517
tcx: TyCtxt<'_>,
16-
module_llvm: &mut ModuleLlvm,
18+
cx: SimpleCx<'_>,
1719
module_name: &str,
1820
kind: AllocatorKind,
1921
alloc_error_handler_kind: AllocatorKind,
2022
) {
21-
let llcx = &*module_llvm.llcx;
22-
let llmod = module_llvm.llmod();
23-
let usize = unsafe {
24-
match tcx.sess.target.pointer_width {
25-
16 => llvm::LLVMInt16TypeInContext(llcx),
26-
32 => llvm::LLVMInt32TypeInContext(llcx),
27-
64 => llvm::LLVMInt64TypeInContext(llcx),
28-
tws => bug!("Unsupported target word size for int: {}", tws),
29-
}
23+
let usize = match tcx.sess.target.pointer_width {
24+
16 => cx.type_i16(),
25+
32 => cx.type_i32(),
26+
64 => cx.type_i64(),
27+
tws => bug!("Unsupported target word size for int: {}", tws),
3028
};
31-
let i8 = unsafe { llvm::LLVMInt8TypeInContext(llcx) };
32-
let i8p = unsafe { llvm::LLVMPointerTypeInContext(llcx, 0) };
29+
let i8 = cx.type_i8();
30+
let i8p = cx.type_ptr();
3331

3432
if kind == AllocatorKind::Default {
3533
for method in ALLOCATOR_METHODS {
@@ -58,15 +56,14 @@ pub(crate) unsafe fn codegen(
5856
let from_name = global_fn_name(method.name);
5957
let to_name = default_fn_name(method.name);
6058

61-
create_wrapper_function(tcx, llcx, llmod, &from_name, &to_name, &args, output, false);
59+
create_wrapper_function(tcx, &cx, &from_name, &to_name, &args, output, false);
6260
}
6361
}
6462

6563
// rust alloc error handler
6664
create_wrapper_function(
6765
tcx,
68-
llcx,
69-
llmod,
66+
&cx,
7067
"__rust_alloc_error_handler",
7168
alloc_error_handler_name(alloc_error_handler_kind),
7269
&[usize, usize], // size, align
@@ -77,99 +74,86 @@ pub(crate) unsafe fn codegen(
7774
unsafe {
7875
// __rust_alloc_error_handler_should_panic
7976
let name = OomStrategy::SYMBOL;
80-
let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_c_char_ptr(), name.len(), i8);
77+
let ll_g = cx.declare_global(name, i8);
8178
llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
8279
let val = tcx.sess.opts.unstable_opts.oom.should_panic();
8380
let llval = llvm::LLVMConstInt(i8, val as u64, False);
8481
llvm::set_initializer(ll_g, llval);
8582

8683
let name = NO_ALLOC_SHIM_IS_UNSTABLE;
87-
let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_c_char_ptr(), name.len(), i8);
84+
let ll_g = cx.declare_global(name, i8);
8885
llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
8986
let llval = llvm::LLVMConstInt(i8, 0, False);
9087
llvm::set_initializer(ll_g, llval);
9188
}
9289

9390
if tcx.sess.opts.debuginfo != DebugInfo::None {
94-
let dbg_cx = debuginfo::CodegenUnitDebugContext::new(llmod);
91+
let dbg_cx = debuginfo::CodegenUnitDebugContext::new(cx.llmod);
9592
debuginfo::metadata::build_compile_unit_di_node(tcx, module_name, &dbg_cx);
9693
dbg_cx.finalize(tcx.sess);
9794
}
9895
}
9996

10097
fn create_wrapper_function(
10198
tcx: TyCtxt<'_>,
102-
llcx: &Context,
103-
llmod: &Module,
99+
cx: &SimpleCx<'_>,
104100
from_name: &str,
105101
to_name: &str,
106102
args: &[&Type],
107103
output: Option<&Type>,
108104
no_return: bool,
109105
) {
110-
unsafe {
111-
let ty = llvm::LLVMFunctionType(
112-
output.unwrap_or_else(|| llvm::LLVMVoidTypeInContext(llcx)),
113-
args.as_ptr(),
114-
args.len() as c_uint,
115-
False,
116-
);
117-
let llfn = llvm::LLVMRustGetOrInsertFunction(
118-
llmod,
119-
from_name.as_c_char_ptr(),
120-
from_name.len(),
121-
ty,
122-
);
123-
let no_return = if no_return {
124-
// -> ! DIFlagNoReturn
125-
let no_return = llvm::AttributeKind::NoReturn.create_attr(llcx);
126-
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[no_return]);
127-
Some(no_return)
128-
} else {
129-
None
130-
};
131-
132-
llvm::set_visibility(llfn, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
133-
134-
if tcx.sess.must_emit_unwind_tables() {
135-
let uwtable =
136-
attributes::uwtable_attr(llcx, tcx.sess.opts.unstable_opts.use_sync_unwind);
137-
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[uwtable]);
138-
}
106+
let ty = cx.type_func(args, output.unwrap_or_else(|| cx.type_void()));
107+
let llfn = declare_simple_fn(
108+
&cx,
109+
from_name,
110+
llvm::CallConv::CCallConv,
111+
llvm::UnnamedAddr::Global,
112+
llvm::Visibility::from_generic(tcx.sess.default_visibility()),
113+
ty,
114+
);
115+
let no_return = if no_return {
116+
// -> ! DIFlagNoReturn
117+
let no_return = llvm::AttributeKind::NoReturn.create_attr(cx.llcx);
118+
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[no_return]);
119+
Some(no_return)
120+
} else {
121+
None
122+
};
139123

140-
let callee =
141-
llvm::LLVMRustGetOrInsertFunction(llmod, to_name.as_c_char_ptr(), to_name.len(), ty);
142-
if let Some(no_return) = no_return {
143-
// -> ! DIFlagNoReturn
144-
attributes::apply_to_llfn(callee, llvm::AttributePlace::Function, &[no_return]);
145-
}
146-
llvm::set_visibility(callee, llvm::Visibility::Hidden);
147-
148-
let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, c"entry".as_ptr());
149-
150-
let llbuilder = llvm::LLVMCreateBuilderInContext(llcx);
151-
llvm::LLVMPositionBuilderAtEnd(llbuilder, llbb);
152-
let args = args
153-
.iter()
154-
.enumerate()
155-
.map(|(i, _)| llvm::LLVMGetParam(llfn, i as c_uint))
156-
.collect::<Vec<_>>();
157-
let ret = llvm::LLVMBuildCallWithOperandBundles(
158-
llbuilder,
159-
ty,
160-
callee,
161-
args.as_ptr(),
162-
args.len() as c_uint,
163-
[].as_ptr(),
164-
0 as c_uint,
165-
c"".as_ptr(),
166-
);
167-
llvm::LLVMSetTailCall(ret, True);
168-
if output.is_some() {
169-
llvm::LLVMBuildRet(llbuilder, ret);
170-
} else {
171-
llvm::LLVMBuildRetVoid(llbuilder);
172-
}
173-
llvm::LLVMDisposeBuilder(llbuilder);
124+
if tcx.sess.must_emit_unwind_tables() {
125+
let uwtable =
126+
attributes::uwtable_attr(cx.llcx, tcx.sess.opts.unstable_opts.use_sync_unwind);
127+
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[uwtable]);
128+
}
129+
130+
let callee = declare_simple_fn(
131+
&cx,
132+
to_name,
133+
llvm::CallConv::CCallConv,
134+
llvm::UnnamedAddr::Global,
135+
llvm::Visibility::Hidden,
136+
ty,
137+
);
138+
if let Some(no_return) = no_return {
139+
// -> ! DIFlagNoReturn
140+
attributes::apply_to_llfn(callee, llvm::AttributePlace::Function, &[no_return]);
141+
}
142+
llvm::set_visibility(callee, llvm::Visibility::Hidden);
143+
144+
let llbb = unsafe { llvm::LLVMAppendBasicBlockInContext(cx.llcx, llfn, c"entry".as_ptr()) };
145+
146+
let mut bx = SBuilder::build(&cx, llbb);
147+
let args = args
148+
.iter()
149+
.enumerate()
150+
.map(|(i, _)| llvm::get_param(llfn, i as c_uint))
151+
.collect::<Vec<_>>();
152+
let ret = bx.call(ty, callee, &args, None);
153+
llvm::LLVMSetTailCall(ret, True);
154+
if output.is_some() {
155+
bx.ret(ret);
156+
} else {
157+
bx.ret_void()
174158
}
175159
}

compiler/rustc_codegen_llvm/src/asm.rs

+47-51
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use std::assert_matches::assert_matches;
22

3-
use libc::{c_char, c_uint};
43
use rustc_abi::{BackendRepr, Float, Integer, Primitive, Scalar};
54
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
65
use rustc_codegen_ssa::mir::operand::OperandValue;
@@ -483,12 +482,13 @@ pub(crate) fn inline_asm_call<'ll>(
483482

484483
debug!("Asm Output Type: {:?}", output);
485484
let fty = bx.cx.type_func(&argtys, output);
486-
unsafe {
487-
// Ask LLVM to verify that the constraints are well-formed.
488-
let constraints_ok = llvm::LLVMRustInlineAsmVerify(fty, cons.as_c_char_ptr(), cons.len());
489-
debug!("constraint verification result: {:?}", constraints_ok);
490-
if constraints_ok {
491-
let v = llvm::LLVMRustInlineAsm(
485+
// Ask LLVM to verify that the constraints are well-formed.
486+
let constraints_ok =
487+
unsafe { llvm::LLVMRustInlineAsmVerify(fty, cons.as_c_char_ptr(), cons.len()) };
488+
debug!("constraint verification result: {:?}", constraints_ok);
489+
if constraints_ok {
490+
let v = unsafe {
491+
llvm::LLVMRustInlineAsm(
492492
fty,
493493
asm.as_c_char_ptr(),
494494
asm.len(),
@@ -498,54 +498,50 @@ pub(crate) fn inline_asm_call<'ll>(
498498
alignstack,
499499
dia,
500500
can_throw,
501-
);
502-
503-
let call = if !labels.is_empty() {
504-
assert!(catch_funclet.is_none());
505-
bx.callbr(fty, None, None, v, inputs, dest.unwrap(), labels, None, None)
506-
} else if let Some((catch, funclet)) = catch_funclet {
507-
bx.invoke(fty, None, None, v, inputs, dest.unwrap(), catch, funclet, None)
508-
} else {
509-
bx.call(fty, None, None, v, inputs, None, None)
510-
};
501+
)
502+
};
511503

512-
// Store mark in a metadata node so we can map LLVM errors
513-
// back to source locations. See #17552.
514-
let key = "srcloc";
515-
let kind = llvm::LLVMGetMDKindIDInContext(
516-
bx.llcx,
517-
key.as_ptr().cast::<c_char>(),
518-
key.len() as c_uint,
519-
);
504+
let call = if !labels.is_empty() {
505+
assert!(catch_funclet.is_none());
506+
bx.callbr(fty, None, None, v, inputs, dest.unwrap(), labels, None, None)
507+
} else if let Some((catch, funclet)) = catch_funclet {
508+
bx.invoke(fty, None, None, v, inputs, dest.unwrap(), catch, funclet, None)
509+
} else {
510+
bx.call(fty, None, None, v, inputs, None, None)
511+
};
520512

521-
// `srcloc` contains one 64-bit integer for each line of assembly code,
522-
// where the lower 32 bits hold the lo byte position and the upper 32 bits
523-
// hold the hi byte position.
524-
let mut srcloc = vec![];
525-
if dia == llvm::AsmDialect::Intel && line_spans.len() > 1 {
526-
// LLVM inserts an extra line to add the ".intel_syntax", so add
527-
// a dummy srcloc entry for it.
528-
//
529-
// Don't do this if we only have 1 line span since that may be
530-
// due to the asm template string coming from a macro. LLVM will
531-
// default to the first srcloc for lines that don't have an
532-
// associated srcloc.
533-
srcloc.push(llvm::LLVMValueAsMetadata(bx.const_u64(0)));
534-
}
535-
srcloc.extend(line_spans.iter().map(|span| {
536-
llvm::LLVMValueAsMetadata(bx.const_u64(
537-
u64::from(span.lo().to_u32()) | (u64::from(span.hi().to_u32()) << 32),
538-
))
539-
}));
540-
let md = llvm::LLVMMDNodeInContext2(bx.llcx, srcloc.as_ptr(), srcloc.len());
541-
let md = llvm::LLVMMetadataAsValue(&bx.llcx, md);
542-
llvm::LLVMSetMetadata(call, kind, md);
513+
// Store mark in a metadata node so we can map LLVM errors
514+
// back to source locations. See #17552.
515+
let key = "srcloc";
516+
let kind = bx.get_md_kind_id(key);
543517

544-
Some(call)
545-
} else {
546-
// LLVM has detected an issue with our constraints, bail out
547-
None
518+
// `srcloc` contains one 64-bit integer for each line of assembly code,
519+
// where the lower 32 bits hold the lo byte position and the upper 32 bits
520+
// hold the hi byte position.
521+
let mut srcloc = vec![];
522+
if dia == llvm::AsmDialect::Intel && line_spans.len() > 1 {
523+
// LLVM inserts an extra line to add the ".intel_syntax", so add
524+
// a dummy srcloc entry for it.
525+
//
526+
// Don't do this if we only have 1 line span since that may be
527+
// due to the asm template string coming from a macro. LLVM will
528+
// default to the first srcloc for lines that don't have an
529+
// associated srcloc.
530+
srcloc.push(llvm::LLVMValueAsMetadata(bx.const_u64(0)));
548531
}
532+
srcloc.extend(line_spans.iter().map(|span| {
533+
llvm::LLVMValueAsMetadata(
534+
bx.const_u64(u64::from(span.lo().to_u32()) | (u64::from(span.hi().to_u32()) << 32)),
535+
)
536+
}));
537+
let md = unsafe { llvm::LLVMMDNodeInContext2(bx.llcx, srcloc.as_ptr(), srcloc.len()) };
538+
let md = bx.get_metadata_value(md);
539+
llvm::LLVMSetMetadata(call, kind, md);
540+
541+
Some(call)
542+
} else {
543+
// LLVM has detected an issue with our constraints, bail out
544+
None
549545
}
550546
}
551547

0 commit comments

Comments
 (0)