use crate::builder::Builder;
use crate::context::CodegenCx;
+use crate::errors::UnwindingInlineAsm;
use crate::type_of::LayoutGccExt;
+use crate::callee::get_fn;
// Rust asm! and GCC Extended Asm semantics differ substantially.
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>)>) {
if options.contains(InlineAsmOptions::MAY_UNWIND) {
self.sess()
- .struct_span_err(span[0], "GCC backend does not support unwinding from inline asm")
+ .create_err(UnwindingInlineAsm { span: span[0] })
.emit();
return;
}
let asm_arch = self.tcx.sess.asm_arch.unwrap();
let is_x86 = matches!(asm_arch, InlineAsmArch::X86 | InlineAsmArch::X86_64);
let att_dialect = is_x86 && options.contains(InlineAsmOptions::ATT_SYNTAX);
- let intel_dialect = is_x86 && !options.contains(InlineAsmOptions::ATT_SYNTAX);
// GCC index of an output operand equals its position in the array
let mut outputs = vec![];
}
InlineAsmOperandRef::SymFn { instance } => {
+ // TODO(@Amanieu): Additional mangling is needed on
+ // some targets to add a leading underscore (Mach-O)
+ // or byte count suffixes (x86 Windows).
constants_len += self.tcx.symbol_name(instance).name.len();
}
InlineAsmOperandRef::SymStatic { def_id } => {
+ // TODO(@Amanieu): Additional mangling is needed on
+ // some targets to add a leading underscore (Mach-O).
constants_len += self.tcx.symbol_name(Instance::mono(self.tcx, def_id)).name.len();
}
}
// processed in the previous pass
}
- InlineAsmOperandRef::Const { .. }
- | InlineAsmOperandRef::SymFn { .. }
- | InlineAsmOperandRef::SymStatic { .. } => {
+ InlineAsmOperandRef::SymFn { instance } => {
+ inputs.push(AsmInOperand {
+ constraint: "X".into(),
+ rust_idx,
+ val: self.cx.rvalue_as_function(get_fn(self.cx, instance))
+ .get_address(None),
+ });
+ }
+
+ InlineAsmOperandRef::SymStatic { def_id } => {
+ inputs.push(AsmInOperand {
+ constraint: "X".into(),
+ rust_idx,
+ val: self.cx.get_static(def_id).get_address(None),
+ });
+ }
+
+ InlineAsmOperandRef::Const { .. } => {
// processed in the previous pass
}
}
// 3. Build the template string
let mut template_str = String::with_capacity(estimate_template_length(template, constants_len, att_dialect));
- if !intel_dialect {
+ if att_dialect {
template_str.push_str(ATT_SYNTAX_INS);
}
}
InlineAsmOperandRef::SymFn { instance } => {
+ // TODO(@Amanieu): Additional mangling is needed on
+ // some targets to add a leading underscore (Mach-O)
+ // or byte count suffixes (x86 Windows).
let name = self.tcx.symbol_name(instance).name;
template_str.push_str(name);
}
InlineAsmOperandRef::SymStatic { def_id } => {
- // TODO(@Commeownist): This may not be sufficient for all kinds of statics.
- // Some statics may need the `@plt` suffix, like thread-local vars.
+ // TODO(@Amanieu): Additional mangling is needed on
+ // some targets to add a leading underscore (Mach-O).
let instance = Instance::mono(self.tcx, def_id);
let name = self.tcx.symbol_name(instance).name;
template_str.push_str(name);
}
}
- if !intel_dialect {
+ if att_dialect {
template_str.push_str(INTEL_SYNTAX_INS);
}
if 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(), builtin_unreachable, &[], None);
+ self.call(self.type_void(), None, builtin_unreachable, &[], None);
}
// Write results to outputs.
InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg)
| InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) => "x",
InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v",
- InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => unimplemented!(),
+ InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "Yk",
+ InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg0) => unimplemented!(),
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => unimplemented!(),
InlineAsmRegClass::X86(
- X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg,
+ X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg | X86InlineAsmRegClass::tmm_reg,
) => unreachable!("clobber-only"),
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
bug!("GCC backend does not support SPIR-V")
| InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => cx.type_f32(),
InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg) => unimplemented!(),
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => cx.type_i16(),
+ InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg0) => cx.type_i16(),
+ InlineAsmRegClass::X86(X86InlineAsmRegClass::tmm_reg) => unimplemented!(),
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(),
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
bug!("LLVM backend does not support SPIR-V")
}
}
-impl<'gcc, 'tcx> AsmMethods for CodegenCx<'gcc, 'tcx> {
- fn codegen_global_asm(&self, template: &[InlineAsmTemplatePiece], operands: &[GlobalAsmOperandRef], options: InlineAsmOptions, _line_spans: &[Span]) {
+impl<'gcc, 'tcx> AsmMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
+ fn codegen_global_asm(&self, template: &[InlineAsmTemplatePiece], operands: &[GlobalAsmOperandRef<'tcx>], options: InlineAsmOptions, _line_spans: &[Span]) {
let asm_arch = self.tcx.sess.asm_arch.unwrap();
// Default to Intel syntax on x86
- let intel_syntax = matches!(asm_arch, InlineAsmArch::X86 | InlineAsmArch::X86_64)
- && !options.contains(InlineAsmOptions::ATT_SYNTAX);
+ let att_dialect = matches!(asm_arch, InlineAsmArch::X86 | InlineAsmArch::X86_64)
+ && options.contains(InlineAsmOptions::ATT_SYNTAX);
// Build the template string
let mut template_str = String::new();
// here unlike normal inline assembly.
template_str.push_str(string);
}
+
+ GlobalAsmOperandRef::SymFn { instance } => {
+ // TODO(@Amanieu): Additional mangling is needed on
+ // some targets to add a leading underscore (Mach-O)
+ // or byte count suffixes (x86 Windows).
+ let name = self.tcx.symbol_name(instance).name;
+ template_str.push_str(name);
+ }
+
+ GlobalAsmOperandRef::SymStatic { def_id } => {
+ // TODO(@Amanieu): Additional mangling is needed on
+ // some targets to add a leading underscore (Mach-O).
+ let instance = Instance::mono(self.tcx, def_id);
+ let name = self.tcx.symbol_name(instance).name;
+ template_str.push_str(name);
+ }
}
}
}
}
let template_str =
- if intel_syntax {
- format!("{}\n\t.intel_syntax noprefix", template_str)
+ if att_dialect {
+ format!(".att_syntax\n\t{}\n\t.intel_syntax noprefix", template_str)
}
else {
- format!(".att_syntax\n\t{}\n\t.intel_syntax noprefix", template_str)
+ template_str
};
// NOTE: seems like gcc will put the asm in the wrong section, so set it to .text manually.
let template_str = format!(".pushsection .text\n{}\n.popsection", template_str);
_ => unreachable!(),
},
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => None,
- InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg) => {
+ InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg0) => None,
+ InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg | X86InlineAsmRegClass::tmm_reg) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => unimplemented!(),