diff options
| author | Gary Guo <gary@garyguo.net> | 2024-10-11 00:23:32 +0100 |
|---|---|---|
| committer | Gary Guo <gary@garyguo.net> | 2024-11-24 14:18:10 +0000 |
| commit | b8df869ebb9219b98ca798aacb16c9be3f84496b (patch) | |
| tree | 387e3bf6c0ba767d6e9ec9e463925a5f91b9de98 /compiler/rustc_codegen_llvm/src/asm.rs | |
| parent | f5d18576856ef45d1e47de79889ae7db9d1afa29 (diff) | |
| download | rust-b8df869ebb9219b98ca798aacb16c9be3f84496b.tar.gz rust-b8df869ebb9219b98ca798aacb16c9be3f84496b.zip | |
Fix asm goto with outputs
When outputs are used together with labels, they are considered to be written for all destinations, not only when falling through.
Diffstat (limited to 'compiler/rustc_codegen_llvm/src/asm.rs')
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/asm.rs | 35 |
1 files changed, 18 insertions, 17 deletions
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index bb74dfe1487..2455d13df8d 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -342,24 +342,25 @@ 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. + for block in 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); + } } } } |
