| 53 | */ |
| 54 | |
| 55 | fn codegen_inline_asm( |
| 56 | &mut self, |
| 57 | template: &[InlineAsmTemplatePiece], |
| 58 | operands: &[InlineAsmOperandRef<'tcx, Self>], |
| 59 | options: InlineAsmOptions, |
| 60 | _line_spans: &[Span], |
| 61 | _instance: Instance<'_>, |
| 62 | _dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>, |
| 63 | ) { |
| 64 | const SUPPORTED_OPTIONS: InlineAsmOptions = InlineAsmOptions::NORETURN; |
| 65 | let unsupported_options = options & !SUPPORTED_OPTIONS; |
| 66 | if !unsupported_options.is_empty() { |
| 67 | self.err(&format!("asm flags not supported: {unsupported_options:?}")); |
| 68 | } |
| 69 | // vec of lines, and each line is vec of tokens |
| 70 | let mut tokens = vec![vec![]]; |
| 71 | for piece in template { |
| 72 | match piece { |
| 73 | InlineAsmTemplatePiece::String(asm) => { |
| 74 | // We cannot use str::lines() here because we don't want the behavior of "the |
| 75 | // last newline is optional", we want an empty string for the last line if |
| 76 | // there is no newline terminator. |
| 77 | // Lambda copied from std LinesAnyMap |
| 78 | let lines = asm.split('\n').map(|line| { |
| 79 | let l = line.len(); |
| 80 | if l > 0 && line.as_bytes()[l - 1] == b'\r' { |
| 81 | &line[0..l - 1] |
| 82 | } else { |
| 83 | line |
| 84 | } |
| 85 | }); |
| 86 | for (index, line) in lines.enumerate() { |
| 87 | if index != 0 { |
| 88 | // There was a newline, add a new line. |
| 89 | tokens.push(vec![]); |
| 90 | } |
| 91 | let mut chars = line.chars(); |
| 92 | while let Some(token) = self.lex_word(&mut chars) { |
| 93 | tokens.last_mut().unwrap().push(token); |
| 94 | } |
| 95 | } |
| 96 | } |
| 97 | &InlineAsmTemplatePiece::Placeholder { |
| 98 | operand_idx, |
| 99 | modifier, |
| 100 | span, |
| 101 | } => { |
| 102 | if let Some(modifier) = modifier { |
| 103 | self.tcx |
| 104 | .sess |
| 105 | .span_err(span, format!("asm modifiers are not supported: {modifier}")); |
| 106 | } |
| 107 | let line = tokens.last_mut().unwrap(); |
| 108 | let typeof_kind = line.last().and_then(|prev| match prev { |
| 109 | Token::Word("typeof") => Some(TypeofKind::Plain), |
| 110 | Token::Word("typeof*") => Some(TypeofKind::Dereference), |
| 111 | _ => None, |
| 112 | }); |