diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2024-11-25 07:01:37 +0100 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-11-25 07:01:37 +0100 | 
| commit | c5230d1148995a30ad5fd56aacffe3576fc0e95f (patch) | |
| tree | fbc57ea3cfab87835428157a3a2fb331315f7e6e /compiler/rustc_codegen_llvm/src/asm.rs | |
| parent | 28fc2ba7142654fa6e654926f96ff913027b200e (diff) | |
| parent | 0178ba2c2547c3677b5624d684a392dccae12abc (diff) | |
| download | rust-c5230d1148995a30ad5fd56aacffe3576fc0e95f.tar.gz rust-c5230d1148995a30ad5fd56aacffe3576fc0e95f.zip | |
Rollup merge of #131523 - nbdd0121:asm, r=compiler-errors
Fix asm goto with outputs and move it to a separate feature gate Tracking issue: #119364 This PR addresses 3 aspects of asm goto with outputs: * Codegen is fixed. My initial implementation has an oversight which cause the output to be only stored in fallthrough path, but not in label blocks. * Outputs can now be used with `options(noreturn)` if a label block is given. * All of this is moved to a new feature gate, because we likely want to stabilise `asm_goto` before asm goto with outputs. `@rustbot` labels: +A-inline-assembly +F-asm
Diffstat (limited to 'compiler/rustc_codegen_llvm/src/asm.rs')
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/asm.rs | 42 | 
1 files changed, 25 insertions, 17 deletions
| diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index bb74dfe1487..07473190d6f 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -342,24 +342,32 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { } attributes::apply_to_callsite(result, llvm::AttributePlace::Function, &{ attrs }); - // Switch to the 'normal' basic block if we did an `invoke` instead of a `call` - if let Some(dest) = dest { - self.switch_to_block(dest); - } + // Write results to outputs. We need to do this for all possible control flow. + // + // Note that `dest` maybe populated with unreachable_block when asm goto with outputs + // is used (because we need to codegen callbr which always needs a destination), so + // here we use the NORETURN option to determine if `dest` should be used. + for block in (if options.contains(InlineAsmOptions::NORETURN) { None } else { Some(dest) }) + .into_iter() + .chain(labels.iter().copied().map(Some)) + { + if let Some(block) = block { + self.switch_to_block(block); + } - // Write results to outputs - for (idx, op) in operands.iter().enumerate() { - if let InlineAsmOperandRef::Out { reg, place: Some(place), .. } - | InlineAsmOperandRef::InOut { reg, out_place: Some(place), .. } = *op - { - let value = if output_types.len() == 1 { - result - } else { - self.extract_value(result, op_idx[&idx] as u64) - }; - let value = - llvm_fixup_output(self, value, reg.reg_class(), &place.layout, instance); - OperandValue::Immediate(value).store(self, place); + for (idx, op) in operands.iter().enumerate() { + if let InlineAsmOperandRef::Out { reg, place: Some(place), .. } + | InlineAsmOperandRef::InOut { reg, out_place: Some(place), .. } = *op + { + let value = if output_types.len() == 1 { + result + } else { + self.extract_value(result, op_idx[&idx] as u64) + }; + let value = + llvm_fixup_output(self, value, reg.reg_class(), &place.layout, instance); + OperandValue::Immediate(value).store(self, place); + } } } } | 
