diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2024-03-08 08:19:17 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-08 08:19:17 +0100 |
| commit | d774fbea7c6cff6e929864f2e3fac4ae6cc88b44 (patch) | |
| tree | 139f5b953c9dda84e464dc9fbf715da253e932a4 /compiler/rustc_codegen_gcc/src | |
| parent | 876847bed88666bf7bb25de1a0b4fba170420661 (diff) | |
| parent | 0ee0f290a61c973a014d44ca3f5e3dc165f5e562 (diff) | |
| download | rust-d774fbea7c6cff6e929864f2e3fac4ae6cc88b44.tar.gz rust-d774fbea7c6cff6e929864f2e3fac4ae6cc88b44.zip | |
Rollup merge of #119365 - nbdd0121:asm-goto, r=Amanieu
Add asm goto support to `asm!` Tracking issue: #119364 This PR implements asm-goto support, using the syntax described in "future possibilities" section of [RFC2873](https://rust-lang.github.io/rfcs/2873-inline-asm.html#asm-goto). Currently I have only implemented the `label` part, not the `fallthrough` part (i.e. fallthrough is implicit). This doesn't reduce the expressive though, since you can use label-break to get arbitrary control flow or simply set a value and rely on jump threading optimisation to get the desired control flow. I can add that later if deemed necessary. r? ``@Amanieu`` cc ``@ojeda``
Diffstat (limited to 'compiler/rustc_codegen_gcc/src')
| -rw-r--r-- | compiler/rustc_codegen_gcc/src/asm.rs | 31 |
1 files changed, 28 insertions, 3 deletions
diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index 78e8e32b972..07edd26e27a 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -107,7 +107,7 @@ enum ConstraintOrRegister { impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { - fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, span: &[Span], instance: Instance<'_>, _dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>) { + fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, span: &[Span], instance: Instance<'_>, dest: Option<Self::BasicBlock>, _catch_funclet: Option<(Self::BasicBlock, Option<&Self::Funclet>)>) { if options.contains(InlineAsmOptions::MAY_UNWIND) { self.sess().dcx() .create_err(UnwindingInlineAsm { span: span[0] }) @@ -126,6 +126,10 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { // added to `outputs.len()` let mut inputs = vec![]; + // GCC index of a label equals its position in the array added to + // `outputs.len() + inputs.len()`. + let mut labels = vec![]; + // Clobbers collected from `out("explicit register") _` and `inout("expl_reg") var => _` let mut clobbers = vec![]; @@ -269,6 +273,10 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { // some targets to add a leading underscore (Mach-O). constants_len += self.tcx.symbol_name(Instance::mono(self.tcx, def_id)).name.len(); } + + InlineAsmOperandRef::Label { label } => { + labels.push(label); + } } } @@ -368,6 +376,10 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { InlineAsmOperandRef::Const { .. } => { // processed in the previous pass } + + InlineAsmOperandRef::Label { .. } => { + // processed in the previous pass + } } } @@ -454,6 +466,14 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { InlineAsmOperandRef::Const { ref string } => { template_str.push_str(string); } + + InlineAsmOperandRef::Label { label } => { + let label_gcc_index = labels.iter() + .position(|&l| l == label) + .expect("wrong rust index"); + let gcc_index = label_gcc_index + outputs.len() + inputs.len(); + push_to_template(Some('l'), gcc_index); + } } } } @@ -466,7 +486,12 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { // 4. Generate Extended Asm block let block = self.llbb(); - let extended_asm = block.add_extended_asm(None, &template_str); + let extended_asm = if let Some(dest) = dest { + assert!(!labels.is_empty()); + block.end_with_extended_asm_goto(None, &template_str, &labels, Some(dest)) + } else { + block.add_extended_asm(None, &template_str) + }; for op in &outputs { extended_asm.add_output_operand(None, &op.to_constraint(), op.tmp_var); @@ -494,7 +519,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { if !options.contains(InlineAsmOptions::NOSTACK) { // TODO(@Commeownist): figure out how to align stack } - if options.contains(InlineAsmOptions::NORETURN) { + if dest.is_none() && options.contains(InlineAsmOptions::NORETURN) { let builtin_unreachable = self.context.get_builtin_function("__builtin_unreachable"); let builtin_unreachable: RValue<'gcc> = unsafe { std::mem::transmute(builtin_unreachable) }; self.call(self.type_void(), None, None, builtin_unreachable, &[], None); |
