-
-
Notifications
You must be signed in to change notification settings - Fork 15k
Implement asm! interpolate
#156719
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Implement asm! interpolate
#156719
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -208,6 +208,10 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { | |
| // Const operands get injected directly into the template | ||
| template_str.push_str(string); | ||
| } | ||
| InlineAsmOperandRef::Interpolate { string } => { | ||
| // Interpolate operands get injected directly into the template | ||
| template_str.push_str(string); | ||
| } | ||
|
Comment on lines
+211
to
+214
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the intended behavior of this? fn zero(mut x: u64) -> u64 {
unsafe {
asm!("mov {0}, {1}", interpolate "$0", inout(reg) x,
options(att_syntax));
}
x
}
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This absolutely needs to have |
||
| InlineAsmOperandRef::SymFn { .. } | ||
| | InlineAsmOperandRef::SymStatic { .. } => { | ||
| // Only emit the raw symbol name | ||
|
|
@@ -409,6 +413,12 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { | |
| // here unlike normal inline assembly. | ||
| template_str.push_str(string); | ||
| } | ||
| GlobalAsmOperandRef::Interpolate { string } => { | ||
| // Interpolate operands get injected directly into the | ||
| // template. Note that we don't need to escape $ | ||
| // here unlike normal inline assembly. | ||
| template_str.push_str(string); | ||
| } | ||
| GlobalAsmOperandRef::SymFn { instance } => { | ||
| let llval = self.get_fn(instance); | ||
| self.add_compiler_used_global(llval); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,9 @@ | ||
| #![allow(non_camel_case_types)] | ||
|
|
||
| use rustc_abi::{BackendRepr, Primitive, Scalar, Size}; | ||
| use rustc_hir::LangItem; | ||
| use rustc_hir::attrs::PeImportNameType; | ||
| use rustc_middle::mir::interpret::{self, alloc_range}; | ||
| use rustc_middle::ty::layout::TyAndLayout; | ||
| use rustc_middle::ty::{self, Instance, TyCtxt}; | ||
| use rustc_middle::{bug, mir, span_bug}; | ||
|
|
@@ -170,6 +172,63 @@ pub fn asm_const_to_str<'tcx>( | |
| } | ||
| } | ||
|
|
||
| pub fn asm_interpolate_to_str<'tcx>( | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not too familiar with the consteval code, but I wonder if some ugly edge cases could be triggered by passing in a const-transmute of something that isn't a slice (e.g. transmute a tuple of a dangling pointer + a random length to a
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. consteval will check for validity invariant violations, so that should be the case, but safety invariant such as UTF-8 is not checked. |
||
| tcx: TyCtxt<'tcx>, | ||
| sp: Span, | ||
| const_value: mir::ConstValue, | ||
| ty_and_layout: TyAndLayout<'tcx>, | ||
| ) -> &'tcx str { | ||
| let (alloc_id, range) = match const_value { | ||
| mir::ConstValue::Slice { alloc_id, meta } => { | ||
| (alloc_id, alloc_range(Size::ZERO, Size::from_bytes(meta))) | ||
| } | ||
|
Comment on lines
+182
to
+184
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was unable to actually trigger this. |
||
| mir::ConstValue::Indirect { alloc_id, offset } => { | ||
| let alloc = tcx.global_alloc(alloc_id).unwrap_memory().inner(); | ||
|
|
||
| let BackendRepr::ScalarPair( | ||
| a @ Scalar::Initialized { value: Primitive::Pointer(_), .. }, | ||
| b @ Scalar::Initialized { value: Primitive::Int(..), .. }, | ||
| ) = ty_and_layout.backend_repr | ||
| else { | ||
| span_bug!( | ||
| sp, | ||
| "expected slice ABI in Indirect for promoted asm interpolate, but got {:#?}", | ||
| ty_and_layout.backend_repr | ||
| ) | ||
| }; | ||
|
|
||
| let (a_size, b_size) = (a.size(&tcx), b.size(&tcx)); | ||
| let b_offset = (offset + a_size).align_to(b.align(&tcx).abi); | ||
|
|
||
| let ptr = alloc.read_scalar(&tcx, alloc_range(offset, a_size), true); | ||
| let size = alloc.read_scalar(&tcx, alloc_range(b_offset, b_size), false); | ||
| let Ok(interpret::Scalar::Ptr(ptr, _)) = ptr else { | ||
| span_bug!( | ||
| sp, | ||
| "expected Ptr in ScalarPair for promoted asm interpolate, but got {ptr:#?}", | ||
| ) | ||
| }; | ||
| let Ok(interpret::Scalar::Int(size)) = size else { | ||
| span_bug!( | ||
| sp, | ||
| "expected Int in ScalarPair for promoted asm interpolate, but got {size:#?}", | ||
| ) | ||
| }; | ||
|
Comment on lines
+205
to
+216
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure if this is overkill. Happy to just |
||
|
|
||
| (ptr.provenance.alloc_id(), alloc_range(Size::ZERO, Size::from_bytes(size))) | ||
| } | ||
| _ => span_bug!( | ||
| sp, | ||
| "expected Slice or Indirect for promoted asm interpolate, but got {:#?}", | ||
| const_value | ||
| ), | ||
| }; | ||
|
|
||
| let alloc = tcx.global_alloc(alloc_id).unwrap_memory().inner(); | ||
| let bytes = alloc.get_bytes_strip_provenance(&tcx, range).unwrap(); | ||
| unsafe { str::from_utf8_unchecked(bytes) } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is unsound as |
||
| } | ||
|
|
||
| pub fn is_mingw_gnu_toolchain(target: &Target) -> bool { | ||
| target.os == Os::Windows && target.env == Env::Gnu && target.cfg_abi == CfgAbi::Unspecified | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, this needs the same escaping as the main template string.
View changes since the review