-
Notifications
You must be signed in to change notification settings - Fork 15.2k
Open
Description
This is rust-lang/rust#147267
Rust lowers naked functions to a module asm
block - the following Rust code
#[unsafe(no_mangle)]
extern "C" fn foo() {
unsafe {
core::arch::asm!("mov rax, QWORD PTR gs:[60h]");
}
}
#[unsafe(naked)]
#[unsafe(no_mangle)]
extern "C" fn foo2() {
core::arch::naked_asm!("mov rax, QWORD PTR gs:[60h]")
}
ends up as
LLVM IR
; ModuleID = 'test.881695139e95559a-cgu.0'
source_filename = "test.881695139e95559a-cgu.0"
target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc"
module asm ".intel_syntax"
module asm ".pushsection .text.foo2,\22xr\22"
module asm ".balign 4"
module asm ".globl foo2"
module asm ".def foo2"
module asm ".scl 2"
module asm ".type 32"
module asm ".endef"
module asm "foo2:"
module asm "mov rax, QWORD PTR gs:[60h]"
module asm ".popsection"
module asm ""
module asm ".att_syntax"
@vtable.0 = private unnamed_addr constant <{ [24 x i8], ptr, ptr, ptr }> <{ [24 x i8] c"\00\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00", ptr @"_ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17hd1c75b492168a55dE", ptr @"_ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17h4262cf38e2e29668E", ptr @"_ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17h4262cf38e2e29668E" }>, align 8
; std::rt::lang_start
; Function Attrs: uwtable
define hidden i64 @_ZN3std2rt10lang_start17h433cd31365191fd0E(ptr %main, i64 %argc, ptr %argv, i8 %sigpipe) unnamed_addr #0 {
start:
%_7 = alloca [8 x i8], align 8
store ptr %main, ptr %_7, align 8
; call std::rt::lang_start_internal
%_0 = call i64 @_ZN3std2rt19lang_start_internal17h4a182455c3ab4a29E(ptr align 1 %_7, ptr align 8 @vtable.0, i64 %argc, ptr %argv, i8 %sigpipe)
ret i64 %_0
}
; std::rt::lang_start::{{closure}}
; Function Attrs: inlinehint uwtable
define internal i32 @"_ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17h4262cf38e2e29668E"(ptr align 8 %_1) unnamed_addr #1 {
start:
%_4 = load ptr, ptr %_1, align 8
; call std::sys::backtrace::__rust_begin_short_backtrace
call void @_ZN3std3sys9backtrace28__rust_begin_short_backtrace17hc9806c74f494fc26E(ptr %_4)
; call <() as std::process::Termination>::report
%self = call i32 @"_ZN54_$LT$$LP$$RP$$u20$as$u20$std..process..Termination$GT$6report17h264280877e7cdf26E"()
ret i32 %self
}
; std::sys::backtrace::__rust_begin_short_backtrace
; Function Attrs: noinline uwtable
define internal void @_ZN3std3sys9backtrace28__rust_begin_short_backtrace17hc9806c74f494fc26E(ptr %f) unnamed_addr #2 {
start:
; call core::ops::function::FnOnce::call_once
call void @_ZN4core3ops8function6FnOnce9call_once17h2ca7e55b5cd60158E(ptr %f)
call void asm sideeffect "", "~{memory}"(), !srcloc !3
ret void
}
; core::ops::function::FnOnce::call_once{{vtable.shim}}
; Function Attrs: inlinehint uwtable
define internal i32 @"_ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17hd1c75b492168a55dE"(ptr %_1) unnamed_addr #1 {
start:
%_2 = alloca [0 x i8], align 1
%0 = load ptr, ptr %_1, align 8
; call core::ops::function::FnOnce::call_once
%_0 = call i32 @_ZN4core3ops8function6FnOnce9call_once17h3de95b96d12b004dE(ptr %0)
ret i32 %_0
}
; core::ops::function::FnOnce::call_once
; Function Attrs: inlinehint uwtable
define internal void @_ZN4core3ops8function6FnOnce9call_once17h2ca7e55b5cd60158E(ptr %_1) unnamed_addr #1 {
start:
%_2 = alloca [0 x i8], align 1
call void %_1()
ret void
}
; core::ops::function::FnOnce::call_once
; Function Attrs: inlinehint uwtable
define internal i32 @_ZN4core3ops8function6FnOnce9call_once17h3de95b96d12b004dE(ptr %0) unnamed_addr #1 personality ptr @__CxxFrameHandler3 {
start:
%_2 = alloca [0 x i8], align 1
%_1 = alloca [8 x i8], align 8
store ptr %0, ptr %_1, align 8
; invoke std::rt::lang_start::{{closure}}
%_0 = invoke i32 @"_ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17h4262cf38e2e29668E"(ptr align 8 %_1)
to label %bb1 unwind label %funclet_bb3
bb3: ; preds = %funclet_bb3
cleanupret from %cleanuppad unwind to caller
funclet_bb3: ; preds = %start
%cleanuppad = cleanuppad within none []
br label %bb3
bb1: ; preds = %start
ret i32 %_0
}
; <() as std::process::Termination>::report
; Function Attrs: inlinehint uwtable
define internal i32 @"_ZN54_$LT$$LP$$RP$$u20$as$u20$std..process..Termination$GT$6report17h264280877e7cdf26E"() unnamed_addr #1 {
start:
ret i32 0
}
; Function Attrs: nounwind uwtable
define dso_local void @foo() unnamed_addr #3 {
start:
call void asm sideeffect alignstack inteldialect "mov rax, QWORD PTR gs:[60h]", "~{dirflag},~{fpsr},~{flags},~{memory}"(), !srcloc !4
ret void
}
; test::main
; Function Attrs: uwtable
define hidden void @_ZN4test4main17h31abd93402dadb48E() unnamed_addr #0 {
start:
ret void
}
; std::rt::lang_start_internal
; Function Attrs: uwtable
declare i64 @_ZN3std2rt19lang_start_internal17h4a182455c3ab4a29E(ptr align 1, ptr align 8, i64, ptr, i8) unnamed_addr #0
declare i32 @__CxxFrameHandler3(...) unnamed_addr #4
; Function Attrs: noinline nounwind uwtable
declare void @foo2() unnamed_addr #5
define i32 @main(i32 %0, ptr %1) unnamed_addr #4 {
top:
%2 = sext i32 %0 to i64
; call std::rt::lang_start
%3 = call i64 @_ZN3std2rt10lang_start17h433cd31365191fd0E(ptr @_ZN4test4main17h31abd93402dadb48E, i64 %2, ptr %1, i8 0)
%4 = trunc i64 %3 to i32
ret i32 %4
}
attributes #0 = { uwtable "target-cpu"="x86-64" "target-features"="+cx16,+sse3,+sahf" }
attributes #1 = { inlinehint uwtable "target-cpu"="x86-64" "target-features"="+cx16,+sse3,+sahf" }
attributes #2 = { noinline uwtable "target-cpu"="x86-64" "target-features"="+cx16,+sse3,+sahf" }
attributes #3 = { nounwind uwtable "target-cpu"="x86-64" "target-features"="+cx16,+sse3,+sahf" }
attributes #4 = { "target-cpu"="x86-64" }
attributes #5 = { noinline nounwind uwtable "target-cpu"="x86-64" "target-features"="+cx16,+sse3,+sahf" }
!llvm.module.flags = !{!0, !1}
!llvm.ident = !{!2}
!0 = !{i32 8, !"PIC Level", i32 2}
!1 = !{i32 7, !"PIE Level", i32 2}
!2 = !{!"rustc version 1.90.0 (1159e78c4 2025-09-14)"}
!3 = !{i64 2898316946459614}
!4 = !{i64 433791696970
However, LLVM with x86_64-pc-windows-msvc as host tools does not accept mov rax, QWORD PTR gs:[60h]
in module asm:
PS> rustc test.rs
error: unknown token in expression
|
note: instantiated into assembly here
--> <inline asm>:10:27
|
10 | mov rax, QWORD PTR gs:[60h]
| ^
error: aborting due to 1 previous error
PS> rustc --emit=llvm-ir test.rs && clang test.ll
warning: overriding the module target triple with x86_64-pc-windows-msvc19.44.35217 [-Woverride-module]
<inline asm>:10:27: error: unknown token in expression
mov rax, QWORD PTR gs:[60h]
^
error: cannot compile inline asm
1 warning and 1 error generated
The error goes away if I pass -masm=intel
to Clang, or use [0x96]
instead of [60h]
. The error also does not appear if the code is compiled with Linux host tools, such as on godbolt. It is also accepted by regular inline assembly (call void asm
).
Reduced:
source_filename = "short.ll"
target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc"
module asm ".intel_syntax"
module asm ".pushsection .text"
module asm "foo2:"
module asm "mov rax, QWORD PTR gs:[60h]"
module asm ".popsection"
module asm ""
module asm ".att_syntax"