
This introduces a new `ptrtoaddr` instruction which is similar to `ptrtoint` but has two differences: 1) Unlike `ptrtoint`, `ptrtoaddr` does not capture provenance 2) `ptrtoaddr` only extracts (and then extends/truncates) the low index-width bits of the pointer For most architectures, difference 2) does not matter since index (address) width and pointer representation width are the same, but this does make a difference for architectures that have pointers that aren't just plain integer addresses such as AMDGPU fat pointers or CHERI capabilities. This commit introduces textual and bitcode IR support as well as basic code generation, but optimization passes do not handle the new instruction yet so it may result in worse code than using ptrtoint. Follow-up changes will update capture tracking, etc. for the new instruction. RFC: https://discourse.llvm.org/t/clarifiying-the-semantics-of-ptrtoint/83987/54 Reviewed By: nikic Pull Request: https://github.com/llvm/llvm-project/pull/139357
114 lines
3.0 KiB
LLVM
114 lines
3.0 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc -mtriple=x86_64-linux-gnu < %s -o - | FileCheck %s --check-prefix=CHECK
|
|
|
|
define i1 @ptrtoaddr_1(ptr %p) {
|
|
; CHECK-LABEL: ptrtoaddr_1:
|
|
; CHECK: # %bb.0: # %entry
|
|
; CHECK-NEXT: movq %rdi, %rax
|
|
; CHECK-NEXT: xorb $1, %al
|
|
; CHECK-NEXT: # kill: def $al killed $al killed $rax
|
|
; CHECK-NEXT: retq
|
|
entry:
|
|
%addr = ptrtoaddr ptr %p to i64
|
|
%trunc = trunc i64 %addr to i1
|
|
%ret = xor i1 %trunc, 1
|
|
ret i1 %ret
|
|
}
|
|
|
|
define i8 @ptrtoaddr_8(ptr %p) {
|
|
; CHECK-LABEL: ptrtoaddr_8:
|
|
; CHECK: # %bb.0: # %entry
|
|
; CHECK-NEXT: movq %rdi, %rax
|
|
; CHECK-NEXT: notb %al
|
|
; CHECK-NEXT: # kill: def $al killed $al killed $rax
|
|
; CHECK-NEXT: retq
|
|
entry:
|
|
%addr = ptrtoaddr ptr %p to i64
|
|
%trunc = trunc i64 %addr to i8
|
|
%ret = xor i8 %trunc, -1
|
|
ret i8 %ret
|
|
}
|
|
|
|
define i16 @ptrtoaddr_16(ptr %p) {
|
|
; CHECK-LABEL: ptrtoaddr_16:
|
|
; CHECK: # %bb.0: # %entry
|
|
; CHECK-NEXT: movq %rdi, %rax
|
|
; CHECK-NEXT: notl %eax
|
|
; CHECK-NEXT: # kill: def $ax killed $ax killed $rax
|
|
; CHECK-NEXT: retq
|
|
entry:
|
|
%addr = ptrtoaddr ptr %p to i64
|
|
%trunc = trunc i64 %addr to i16
|
|
%ret = xor i16 %trunc, -1
|
|
ret i16 %ret
|
|
}
|
|
|
|
define i32 @ptrtoaddr_32(ptr %p) {
|
|
; CHECK-LABEL: ptrtoaddr_32:
|
|
; CHECK: # %bb.0: # %entry
|
|
; CHECK-NEXT: movq %rdi, %rax
|
|
; CHECK-NEXT: notl %eax
|
|
; CHECK-NEXT: # kill: def $eax killed $eax killed $rax
|
|
; CHECK-NEXT: retq
|
|
entry:
|
|
%addr = ptrtoaddr ptr %p to i64
|
|
%trunc = trunc i64 %addr to i32
|
|
%ret = xor i32 %trunc, -1
|
|
ret i32 %ret
|
|
}
|
|
|
|
define i64 @ptrtoaddr_64(ptr %p) {
|
|
; CHECK-LABEL: ptrtoaddr_64:
|
|
; CHECK: # %bb.0: # %entry
|
|
; CHECK-NEXT: movq %rdi, %rax
|
|
; CHECK-NEXT: notq %rax
|
|
; CHECK-NEXT: retq
|
|
entry:
|
|
%addr = ptrtoaddr ptr %p to i64
|
|
%ret = xor i64 %addr, -1
|
|
ret i64 %ret
|
|
}
|
|
|
|
define i128 @ptrtoaddr_128(ptr %p) {
|
|
; CHECK-LABEL: ptrtoaddr_128:
|
|
; CHECK: # %bb.0: # %entry
|
|
; CHECK-NEXT: movq %rdi, %rax
|
|
; CHECK-NEXT: notq %rax
|
|
; CHECK-NEXT: movq $-1, %rdx
|
|
; CHECK-NEXT: retq
|
|
entry:
|
|
%addr = ptrtoaddr ptr %p to i64
|
|
%ext = zext i64 %addr to i128
|
|
%ret = xor i128 %ext, -1
|
|
ret i128 %ret
|
|
}
|
|
|
|
|
|
define <2 x i64> @ptrtoaddr_vec(<2 x ptr> %p) {
|
|
; CHECK-LABEL: ptrtoaddr_vec:
|
|
; CHECK: # %bb.0: # %entry
|
|
; CHECK-NEXT: pcmpeqd %xmm1, %xmm1
|
|
; CHECK-NEXT: pxor %xmm1, %xmm0
|
|
; CHECK-NEXT: retq
|
|
entry:
|
|
%addr = ptrtoaddr <2 x ptr> %p to <2 x i64>
|
|
%ret = xor <2 x i64> %addr, <i64 -1, i64 -1>
|
|
ret <2 x i64> %ret
|
|
}
|
|
|
|
; UTC_ARGS: --disable
|
|
|
|
@foo = global [16 x i8] zeroinitializer
|
|
@addr = global i64 ptrtoaddr (ptr @foo to i64)
|
|
; CHECK: addr:
|
|
; CHECK-NEXT: .quad foo
|
|
; CHECK-NEXT: .size addr, 8
|
|
@addr_plus_one = global i64 ptrtoaddr (ptr getelementptr (i8, ptr @foo, i64 1) to i64)
|
|
; CHECK: addr_plus_one:
|
|
; CHECK-NEXT: .quad foo+1
|
|
; CHECK-NEXT: .size addr_plus_one, 8
|
|
@const_addr = global i64 ptrtoaddr (ptr getelementptr (i8, ptr null, i64 1) to i64)
|
|
; CHECK: const_addr:
|
|
; CHECK-NEXT: .quad 0+1
|
|
; CHECK-NEXT: .size const_addr, 8
|