Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign uprustc_codegen_llvm: traitification of LLVM-specific CodegenCx and Builder methods #55627
Conversation
rust-highfive
assigned
pnkfelix
Nov 2, 2018
This comment has been minimized.
This comment has been minimized.
|
r? @pnkfelix (rust_highfive has picked a reviewer for you, use r? to override) |
rust-highfive
added
the
S-waiting-on-review
label
Nov 2, 2018
sunfishcode
referenced this pull request
Nov 2, 2018
Closed
rustc_codegen_llvm: traitification of LLVM-specific CodegenCx and Builder methods #54012
This comment was marked as outdated.
This comment was marked as outdated.
|
|
sunfishcode
force-pushed the
sunfishcode:cg-llvm-gen
branch
from
6538a47
to
cffad3f
Nov 2, 2018
This comment has been minimized.
This comment has been minimized.
|
r? @eddyb |
rust-highfive
assigned
eddyb
and unassigned
pnkfelix
Nov 2, 2018
This comment was marked as outdated.
This comment was marked as outdated.
|
|
This comment has been minimized.
This comment has been minimized.
|
Thanks for fixing the bug ! It was a silly mistake from my part... |
eddyb
referenced this pull request
Nov 3, 2018
Merged
rustc_target: pass contexts by reference, not value. #55665
added a commit
that referenced
this pull request
Nov 4, 2018
eddyb
requested changes
Nov 4, 2018
First batch of comments (my browser hates me already!)
| fn store_fn_arg( | ||
| &mut self, | ||
| ty: &ArgType<'tcx, Ty<'tcx>>, | ||
| idx: &mut usize, dst: PlaceRef<'tcx, <Self::CodegenCx as Backend<'ll>>::Value> |
This comment has been minimized.
This comment has been minimized.
| bx: &mut Builder<'a, 'll, 'tcx, &'ll Value>, | ||
| idx: &mut usize, | ||
| dst: PlaceRef<'tcx, &'ll Value> | ||
| ) { |
This comment has been minimized.
This comment has been minimized.
eddyb
Nov 4, 2018
Member
I think this is a LLVM-ism, does Cranelift support getting at the function params from a builder? What I'd do instead is also pass a slice of values, alongside the index.
| @@ -104,29 +106,29 @@ impl ArgAttributesExt for ArgAttributes { | |||
| } | |||
|
|
|||
| pub trait LlvmType { | |||
| fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type; | |||
| fn llvm_type(&self, cx: &CodegenCx<'ll, '_, &'ll Value>) -> &'ll Type; | |||
This comment has been minimized.
This comment has been minimized.
eddyb
Nov 4, 2018
Member
Maybe have a crate-wide type-alias so that we can continue to write CodegenCx<'ll, '_> instead of CodegenCx<'ll, '_, &'ll Value> in rustc_codegen_llvm?
| &mut self, | ||
| ty: &FnType<'tcx, Ty<'tcx>>, | ||
| callsite: <Self::CodegenCx as Backend<'ll>>::Value | ||
| ) { |
This comment has been minimized.
This comment has been minimized.
eddyb
Nov 4, 2018
Member
Hmm, I think it might be better if instead of the "apply attrs" LLVM-ism, the call/invoke methods of Builder took an FnType and internally called the LLVM-only apply_attrs_callsite.
| } | ||
| fn fn_type_of_instance(&self, instance: &Instance<'tcx>) -> FnType<'tcx, Ty<'tcx>> { | ||
| FnType::of_instance(&self, instance) | ||
| } |
This comment has been minimized.
This comment has been minimized.
eddyb
Nov 4, 2018
Member
Do any of these depend on anything LLVM-specific? IMO these could be moved into rustc_codegen_ssa or even rustc itself!
| inputs: &[&'ll Value], output: &'ll Type, | ||
| volatile: bool, alignstack: bool, | ||
| dia: AsmDialect) -> Option<&'ll Value> { | ||
| fn inline_asm_call(&mut self, asm: *const c_char, cons: *const c_char, |
This comment has been minimized.
This comment has been minimized.
eddyb
Nov 4, 2018
Member
For this to be a safe Rust function, btw, *const c_char needs to be replaced with &CStr.
| cmp, | ||
| src, | ||
| AtomicOrdering::from_generic(order), | ||
| AtomicOrdering::from_generic(failure_order), |
This comment has been minimized.
This comment has been minimized.
eddyb
Nov 4, 2018
Member
This makes me think From should be implemented instead. Then, the LLVM-specific AtomicOrdering do not need to be imported, removing rustc_codegen_ssa::common:: noise in the signature and we can just do order.into() and whatnot.
| /// If LLVM lifetime intrinsic support is disabled (i.e. optimizations | ||
| /// off) or `ptr` is zero-sized, then no-op (does not call `emit`). | ||
| fn call_lifetime_intrinsic(&self, intrinsic: &str, ptr: &'ll Value, size: Size) { | ||
| fn call_lifetime_intrinsic(&mut self, intrinsic: &str, ptr: &'ll Value, size: Size) { |
This comment has been minimized.
This comment has been minimized.
eddyb
Nov 4, 2018
Member
This probably needs to be generalized to storage_{live,dead} (which is what the MIR contains).
| &self.cx | ||
| } | ||
|
|
||
| fn delete_basic_block(&mut self, bb: &'ll BasicBlock) { |
This comment has been minimized.
This comment has been minimized.
eddyb
Nov 4, 2018
Member
This is unsafe! The trait method should be marked as such. Maybe we can find a way to avoid doing it at all.
| } | ||
|
|
||
| fn do_not_inline(&mut self, llret: &'ll Value) { | ||
| llvm::Attribute::NoInline.apply_callsite(llvm::AttributePlace::Function, llret); |
This comment has been minimized.
This comment has been minimized.
eddyb
Nov 4, 2018
Member
Applying attributes via the return value is a LLVM-ism, we should clean it up.
eddyb
requested changes
Nov 4, 2018
Second round of comments, got through rustc_codegen_llvm and rustc_codegen_ssa::back, things seems pretty good so far!
| @@ -57,9 +53,9 @@ pub fn get_fn( | |||
|
|
|||
| // Create a fn pointer with the substituted signature. | |||
| let fn_ptr_ty = tcx.mk_fn_ptr(sig); | |||
| let llptrty = cx.layout_of(fn_ptr_ty).llvm_type(cx); | |||
| let llptrty = cx.backend_type(&cx.layout_of(fn_ptr_ty)); | |||
This comment has been minimized.
This comment has been minimized.
eddyb
Nov 4, 2018
Member
Any reason this can't be a method in an extension trait on TyLayout still?
That is, I'd prefer to write cx.layout_of(fn_ptr_ty).codegen_type(cx).
OTOH, another thing we can do is remove the & there.
TyLayout is a "cheap" type, a pair of references IIRC, by design!
| Funclet { | ||
| cleanuppad, | ||
| operand: OperandBundleDef::new("funclet", &[cleanuppad]), | ||
| impl<'ll, 'tcx : 'll> ConstMethods<'ll, 'tcx> for CodegenCx<'ll, 'tcx, &'ll Value> { |
This comment has been minimized.
This comment has been minimized.
| match span { | ||
| Some(span) => tcx.sess.span_fatal(span, &msg[..]), | ||
| None => tcx.sess.fatal(&msg[..]), | ||
| fn scalar_to_backend( |
This comment has been minimized.
This comment has been minimized.
| unsafe { | ||
| let bitcast = llvm::LLVMConstPointerCast(new_g, self.val_ty(old_g)); | ||
| llvm::LLVMReplaceAllUsesWith(old_g, bitcast); | ||
| llvm::LLVMDeleteGlobal(old_g); |
This comment has been minimized.
This comment has been minimized.
eddyb
Nov 4, 2018
Member
This seems like would require this method to be marked as unsafe (as references to old_g might still be around, outside of the LLVM module itself).
| use syntax::symbol::LocalInternedString; | ||
| use abi::Abi; | ||
|
|
||
| /// There is one `CodegenCx` per compilation unit. Each one has its own LLVM | ||
| /// `llvm::Context` so that several compilation units may be optimized in parallel. | ||
| /// All other LLVM data structures in the `CodegenCx` are tied to that `llvm::Context`. | ||
| pub struct CodegenCx<'a, 'tcx: 'a> { | ||
| pub tcx: TyCtxt<'a, 'tcx, 'tcx>, | ||
| pub struct CodegenCx<'ll, 'tcx: 'll, V> { |
This comment has been minimized.
This comment has been minimized.
| impl<'a, 'll: 'a, 'tcx: 'll> DerivedTypeMethods<'a, 'll, 'tcx> for CodegenCx<'ll, 'tcx, &'ll Value> | ||
| {} | ||
|
|
||
| impl LayoutTypeMethods<'ll, 'tcx> for CodegenCx<'ll, 'tcx, &'ll Value> { |
This comment has been minimized.
This comment has been minimized.
eddyb
Nov 4, 2018
Member
These should be inverted - that is, implemented on TyLayout, in rustc_codegen_ssa. I guess you still need this trait, hmm.
| { | ||
| fn new_block<'b>( | ||
| cx: &'a Self::CodegenCx, | ||
| llfn: <Self::CodegenCx as Backend<'ll>>::Value, |
This comment has been minimized.
This comment has been minimized.
eddyb
Nov 4, 2018
Member
I think you could have Value in a trait that's only associated types, and is implemented for builders to point to their backend's associated types.
|
|
||
| /// Additional resources used by optimize_and_codegen (not module specific) | ||
| #[derive(Clone)] | ||
| pub struct CodegenContext<B : WriteBackendMethods> { |
This comment has been minimized.
This comment has been minimized.
eddyb
Nov 4, 2018
Member
This reminds me the name Codegen in the context of the "back" module, is suboptimal.
Including in "optimize_and_codegen". I think we could call this step "emitting machine code/a binary", so maybe optimize_and_emit? OptimizeAndEmitContext is not great, but more descriptive.
cc @michaelwoerister @rkruppe @alexcrichton
Also, : should be : .
| self.obj_is_bitcode = sess.target.target.options.obj_is_bitcode || | ||
| sess.opts.debugging_opts.cross_lang_lto.enabled(); | ||
| let embed_bitcode = sess.target.target.options.embed_bitcode || | ||
| sess.opts.debugging_opts.embed_bitcode; |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
eddyb
Nov 4, 2018
Member
Maybe rename bitcode to ir, to generalize? or llvm_bc, to make it clear it's LLVM-specific.
| let mut note = prog.stderr.clone(); | ||
| note.extend_from_slice(&prog.stdout); | ||
|
|
||
| handler.struct_err(&format!("linking with `{}` failed: {}", |
This comment has been minimized.
This comment has been minimized.
eddyb
Nov 4, 2018
Member
Maybe someone should search for llvm (case-insensitive) in rustc_codegen_ssa.
This comment has been minimized.
This comment has been minimized.
|
There's a general issue, that |
eddyb
requested changes
Nov 5, 2018
Third batch, and that's all the comments for now! Let me know if I can help resolve everything.
| // option. This file may not be copied, modified, or distributed | ||
| // except according to those terms. | ||
|
|
||
| //! Codegen the completed AST to the LLVM IR. |
This comment has been minimized.
This comment has been minimized.
eddyb
Nov 5, 2018
Member
Outdated comment - could even be removed, base ended up as a dumping ground (and common similarly), they should be properly redistributed around IMO.
This comment has been minimized.
This comment has been minimized.
|
|
||
|
|
||
| pub struct StatRecorder<'a, 'll: 'a, 'tcx: 'll, Cx: 'a + CodegenMethods<'a, 'll, 'tcx>> | ||
| where &'a Cx : LayoutOf<Ty = Ty<'tcx>, TyLayout = TyLayout<'tcx>> + HasTyCtxt<'tcx> |
This comment has been minimized.
This comment has been minimized.
eddyb
Nov 5, 2018
Member
So, &'a Cx : LayoutOf + HasTyCtxt bounds should not longer be needed, since my PR landed.
Also, we either need to 1. avoid putting bounds on structs 2. enable the implied bounds feature to avoid writing the bounds anywhere else. cc @nikomatsakis
This comment has been minimized.
This comment has been minimized.
eddyb
Nov 5, 2018
Member
Also, are any of these "stats" useful anymore? It feels like any new infrastructure should be designed with MIR in mind...
| } | ||
| } | ||
|
|
||
| pub fn bin_op_to_fcmp_predicate(op: hir::BinOpKind) -> RealPredicate { |
This comment has been minimized.
This comment has been minimized.
eddyb
Nov 5, 2018
Member
IMO Real in the type name should be changed to Float. I have no idea why LLVM chose that (wrong) name in the first place.
|
|
||
| pub fn compare_simd_types<'a, 'll:'a, 'tcx:'ll, Bx : BuilderMethods<'a, 'll, 'tcx>>( | ||
| bx: &mut Bx, | ||
| lhs: <Bx::CodegenCx as Backend<'ll>>::Value, |
This comment has been minimized.
This comment has been minimized.
eddyb
Nov 5, 2018
Member
As I mentioned earlier, I think it would be cleaner if builders implemented the same trait holding associated types, so this was just Bx::Value.
Also, I'm seeing 'll in this crate - that shouldn't be needed!
After all, we're abstracting over types like &'ll Value - so the parametrization should only exist in rustc_codegen_llvm.
| backend: B, | ||
| tcx: TyCtxt<'ll, 'tcx, 'tcx>, | ||
| rx: mpsc::Receiver<Box<dyn Any + Send>> | ||
| ) -> OngoingCodegen<B> { |
This comment has been minimized.
This comment has been minimized.
| @@ -21,6 +21,7 @@ | |||
| #![feature(custom_attribute)] | |||
| #![feature(nll)] | |||
| #![allow(unused_attributes)] | |||
| #![allow(dead_code)] | |||
This comment has been minimized.
This comment has been minimized.
| bb: mir::BasicBlock, | ||
| terminator: &mir::Terminator<'tcx>) | ||
| { | ||
| fn codegen_terminator<Bx: BuilderMethods<'a, 'll, 'tcx>>( |
This comment has been minimized.
This comment has been minimized.
eddyb
Nov 5, 2018
Member
Could we, instead, make Bx an associated type on Cx? That would get rid of some of the explicit parametrization.
| @@ -329,25 +347,25 @@ impl FunctionCx<'a, 'll, 'tcx> { | |||
| // NOTE: Unlike binops, negation doesn't have its own | |||
| // checked operation, just a comparison with the minimum | |||
| // value, so we have to check for the assert message. | |||
| if !bx.cx.check_overflow { | |||
| if !bx.cx().check_overflow() { | |||
This comment has been minimized.
This comment has been minimized.
eddyb
Nov 5, 2018
Member
I think this should be on an extension trait on TyCtxt in rustc_codegen_ssa.
| @@ -159,48 +169,67 @@ impl OperandRef<'ll, 'tcx> { | |||
|
|
|||
| /// If this operand is a `Pair`, we return an aggregate with the two values. | |||
| /// For other cases, see `immediate`. | |||
| pub fn immediate_or_packed_pair(self, bx: &Builder<'a, 'll, 'tcx>) -> &'ll Value { | |||
| pub fn immediate_or_packed_pair<Bx: BuilderMethods<'a, 'll, 'tcx>>( | |||
This comment has been minimized.
This comment has been minimized.
eddyb
Nov 5, 2018
Member
These packing methods should be relegated to the backend.
AFAIK, Cranelift uses multiple returns instead of packing two values into one.
| )); | ||
| ll_t_in_const | ||
| ); | ||
| base::call_assume(&mut bx, cmp); |
This comment has been minimized.
This comment has been minimized.
denismerigoux
force-pushed the
sunfishcode:cg-llvm-gen
branch
from
cffad3f
to
1764f2c
Nov 5, 2018
This comment has been minimized.
This comment has been minimized.
|
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
This comment has been minimized.
This comment has been minimized.
|
|
denismerigoux
force-pushed the
sunfishcode:cg-llvm-gen
branch
from
1764f2c
to
09235bb
Nov 6, 2018
This comment has been minimized.
This comment has been minimized.
|
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
eddyb
referenced this pull request
Nov 7, 2018
Closed
Move cg_llvm::rpath and parts of cg_llvm::back::link to rustc_codegen_utils #55725
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
|
@sunfishcode Can you take a look at fixing the merge conflicts and resolving the CI failure here? |
Mark-Simulacrum
added
S-waiting-on-author
and removed
S-waiting-on-review
labels
Nov 15, 2018
This comment has been minimized.
This comment has been minimized.
|
@Mark-Simulacrum I'm rebasing it and getting close to finishing. |
irinagpopa
and others
added some commits
Aug 2, 2018
nikomatsakis
approved these changes
Nov 16, 2018
Looks like everything I found wound up getting moot later. r=me.
| @@ -740,7 +740,7 @@ fn link_natively(sess: &Session, | |||
| // with some thread pool working in the background. It seems that no one | |||
| // currently knows a fix for this so in the meantime we're left with this... | |||
| info!("{:?}", &cmd); | |||
| let retry_on_segfault = env::var("RUSTC_RETRY_LINKER_ON_SEGFAULT").is_ok(); | |||
| let retry_on_segfault = env::var("RUSTc_RETRY_LINKER_ON_SEGFAULT").is_ok(); | |||
This comment has been minimized.
This comment has been minimized.
| @@ -393,9 +395,12 @@ pub struct CodegenContext { | |||
| time_graph: Option<TimeGraph>, | |||
| // The assembler command if no_integrated_as option is enabled, None otherwise | |||
| assembler_cmd: Option<Arc<AssemblerCommand>>, | |||
| // This field is used to give a lifetime parameter to the struct so that it can implement | |||
| // the Backend trait. | |||
| phantom: PhantomData<&'ll ()> | |||
This comment has been minimized.
This comment has been minimized.
nikomatsakis
Nov 16, 2018
Contributor
This seems ok but I usually find these sorts of things to indicate some other "mis-alignment". This 'll lifetime -- what does it logically represent here? Is there some resource we could take a reference to instead? Should it maybe be moved to the Backend trait?
Anyway, not a blocking concern, but I do feel like the "semantic meaning" of this lifetime is unclear to me.
This comment has been minimized.
This comment has been minimized.
|
@bors r+ |
This comment has been minimized.
This comment has been minimized.
|
|
bors
added
S-waiting-on-bors
and removed
S-waiting-on-author
labels
Nov 16, 2018
This comment has been minimized.
This comment has been minimized.
added a commit
that referenced
this pull request
Nov 17, 2018
This comment has been minimized.
This comment has been minimized.
|
|
bors
added
S-waiting-on-review
and removed
S-waiting-on-bors
labels
Nov 17, 2018
This comment has been minimized.
This comment has been minimized.
|
@alexcrichton @retep998 Is this spurious, or a real failure? @bors retry (just in case) |
bors
added
S-waiting-on-bors
and removed
S-waiting-on-review
labels
Nov 17, 2018
This comment has been minimized.
This comment has been minimized.
added a commit
that referenced
this pull request
Nov 17, 2018
This comment has been minimized.
This comment has been minimized.
|
|
sunfishcode commentedNov 2, 2018
•
edited by eddyb
This PR is the continuation of #54012 and earlier PRs, in the grand plan of #45274 to allow for multiple codegen backends.
High-level summary: interpose a set of traits between Rust's codegen logic and the LLVM APIs, allowing another backend to implement the traits and share most of the codegen logic. These traits are currently somewhat LLVM-specific, but once this refactoring is in place, they can evolve to be more general.
See this README for a writeup on the current trait organization.