1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 20:23:11 +01:00
llvm-mirror/test/Bitcode/blockaddress-addrspace.ll
Alex Richardson a73a5b4199 Place the BlockAddress type in the address space of the containing function
While this should not matter for most architectures (where the program
address space is 0), it is important for CHERI (and therefore Arm Morello).
We use address space 200 for all of our code pointers and without this
change we assert in the SelectionDAG handling of BlockAddress nodes.

It is also useful for AVR: previously programs targeting
AVR that attempt to read their own machine code
via a pointer to a label would instead read from RAM
using a pointer relative to the the start of program flash.

Reviewed By: dylanmckay, theraven
Differential Revision: https://reviews.llvm.org/D48803
2021-07-02 12:17:55 +01:00

287 lines
8.2 KiB
LLVM

; RUN: rm -rf %t && split-file %s %t
; RUN: llvm-as %t/global-use-good.ll -o - | llvm-dis -o /dev/null
; RUN: not llvm-as %t/global-use-bad.ll -o /dev/null 2>&1 | FileCheck %t/global-use-bad.ll
; RUN: llvm-as %t/global-fwddecl-good.ll -o - | llvm-dis -o /dev/null
; RUN: not llvm-as %t/global-fwddecl-bad.ll -o /dev/null 2>&1 | FileCheck %t/global-fwddecl-bad.ll
; RUN: llvm-as %t/return-fwddecl-good.ll -o - | llvm-dis -o /dev/null
; RUN: not llvm-as %t/return-fwddecl-bad.ll -o /dev/null 2>&1 | FileCheck %t/return-fwddecl-bad.ll
; RUN: llvm-as %t/return-self-good.ll -o - | llvm-dis -o /dev/null
; RUN: not llvm-as %t/return-self-bad.ll -o /dev/null 2>&1 | FileCheck %t/return-self-bad.ll
; RUN: not llvm-as %t/return-self-bad-2.ll -o /dev/null 2>&1 | FileCheck %t/return-self-bad-2.ll
; RUN: not llvm-as %t/return-unknown-fn-bad.ll -o /dev/null 2>&1 | FileCheck %t/return-unknown-fn-bad.ll
; RUN: llvm-as %t/call-fwddecl-good.ll -o - | llvm-dis -o /dev/null
; RUN: not llvm-as %t/call-fwddecl-bad.ll -o /dev/null 2>&1 | FileCheck %t/call-fwddecl-bad.ll
; RUN: llvm-as %t/phi-good.ll -o - | llvm-dis -o /dev/null
; RUN: not llvm-as %t/phi-bad.ll -o /dev/null 2>&1 | FileCheck %t/phi-bad.ll
; RUN: llvm-as %t/fwddecl-phi-good.ll -o - | llvm-dis -o /dev/null
; RUN: not llvm-as %t/fwddecl-phi-bad.ll -o /dev/null 2>&1 | FileCheck %t/fwddecl-phi-bad.ll
; RUN: not llvm-as %t/bad-type-not-ptr.ll -o /dev/null 2>&1 | FileCheck %t/bad-type-not-ptr.ll
; RUN: not llvm-as %t/bad-type-not-i8-ptr.ll -o /dev/null 2>&1 | FileCheck %t/bad-type-not-i8-ptr.ll
;--- global-use-good.ll
target datalayout = "P2"
define void @fn_in_prog_as_implicit() {
unreachable
bb:
ret void
}
define void @fn_in_prog_as_explicit() addrspace(2) {
unreachable
bb:
ret void
}
define void @fn_in_other_as() addrspace(1) {
unreachable
bb:
ret void
}
@global1 = constant i8 addrspace(2)* blockaddress(@fn_in_prog_as_implicit, %bb)
@global2 = constant i8 addrspace(2)* blockaddress(@fn_in_prog_as_explicit, %bb)
@global3 = constant i8 addrspace(1)* blockaddress(@fn_in_other_as, %bb)
;--- global-use-bad.ll
define void @fn() addrspace(1) {
unreachable
bb:
ret void
}
@global1 = constant i8 addrspace(2)* blockaddress(@fn, %bb)
; CHECK: [[#@LINE-1]]:38: error: constant expression type mismatch: got type 'i8 addrspace(1)*' but expected 'i8 addrspace(2)*'
; Check that a global blockaddress of a forward-declared function
; uses the type of the global variable address space for the forward declaration
;--- global-fwddecl-good.ll
@global = constant i8 addrspace(2)* blockaddress(@fwddecl_in_prog_as, %bb)
define void @fwddecl_in_prog_as() addrspace(2) {
unreachable
bb:
ret void
}
;--- global-fwddecl-bad.ll
; This forward declaration does not match the actual function type so we should get an error:
@global = constant i8 addrspace(2)* blockaddress(@fwddecl_in_unexpected_as, %bb)
; CHECK: [[#@LINE-1]]:77: error: 'bb' defined with type 'i8 addrspace(1)*' but expected 'i8 addrspace(2)*'
define void @fwddecl_in_unexpected_as() addrspace(1) {
unreachable
bb:
ret void
}
; When returning blockaddresses of forward-declared functions we
; can also use the type of the variable.
;--- return-fwddecl-good.ll
define i8 addrspace(2)* @take_as2() {
ret i8 addrspace(2)* blockaddress(@fwddecl_as2, %bb)
}
define i8 addrspace(1)* @take_as1() {
ret i8 addrspace(1)* blockaddress(@fwddecl_as1, %bb)
}
define void @fwddecl_as1() addrspace(1) {
unreachable
bb:
ret void
}
define void @fwddecl_as2() addrspace(2) {
unreachable
bb:
ret void
}
;--- return-fwddecl-bad.ll
define i8 addrspace(2)* @take_bad() {
ret i8 addrspace(2)* blockaddress(@fwddecl_as1, %bb)
; CHECK: [[#@LINE-1]]:51: error: 'bb' defined with type 'i8 addrspace(1)*' but expected 'i8 addrspace(2)*'
}
define void @fwddecl_as1() addrspace(1) {
unreachable
bb:
ret void
}
;--- return-self-good.ll
target datalayout = "P2"
define i8 addrspace(0)* @take_self_as0() addrspace(0) {
L1:
br label %L2
L2:
ret i8 addrspace(0)* blockaddress(@take_self_as0, %L3)
L3:
unreachable
}
define i8 addrspace(2)* @take_self_prog_as() {
L1:
br label %L2
L2:
ret i8 addrspace(2)* blockaddress(@take_self_prog_as, %L3)
L3:
unreachable
}
define i8 addrspace(1)* @take_self_as1() addrspace(1) {
L1:
br label %L2
L2:
ret i8 addrspace(1)* blockaddress(@take_self_as1, %L3)
L3:
unreachable
}
define i8 addrspace(2)* @take_self_as2() addrspace(2) {
L1:
br label %L2
L2:
ret i8 addrspace(2)* blockaddress(@take_self_as2, %L3)
L3:
unreachable
}
;--- return-self-bad.ll
target datalayout = "P2"
define i8 addrspace(2)* @take_self_bad() addrspace(1) {
L1:
br label %L2
L2:
ret i8 addrspace(2)* blockaddress(@take_self_bad, %L3)
; CHECK: [[#@LINE-1]]:24: error: constant expression type mismatch: got type 'i8 addrspace(1)*' but expected 'i8 addrspace(2)*'
L3:
unreachable
}
;--- return-self-bad-2.ll
target datalayout = "P2"
define i8* @take_self_bad_prog_as() {
L1:
br label %L2
L2:
ret i8* blockaddress(@take_self_bad_prog_as, %L3)
; CHECK: [[#@LINE-1]]:11: error: constant expression type mismatch: got type 'i8 addrspace(2)*' but expected 'i8*'
L3:
unreachable
}
;--- return-unknown-fn-bad.ll
target datalayout = "P2"
define i8 addrspace(1)* @return_unknown_fn() addrspace(1) {
ret i8 addrspace(1)* blockaddress(@undefined, %bb)
; CHECK: [[#@LINE-1]]:37: error: expected function name in blockaddress
}
;--- call-fwddecl-good.ll
target datalayout = "P2"
define void @call_from_fn_in_as2() addrspace(2) {
call addrspace(2) void bitcast (i8 addrspace(2)* blockaddress(@fwddecl_as2, %bb) to void () addrspace(2)*)()
ret void
}
define void @call_from_fn_in_as1() addrspace(1) {
call addrspace(1) void bitcast (i8 addrspace(1)* blockaddress(@fwddecl_as1, %bb) to void () addrspace(1)*)()
ret void
}
define void @fwddecl_as2() addrspace(2) {
unreachable
bb:
ret void
}
define void @fwddecl_as1() addrspace(1) {
unreachable
bb:
ret void
}
;--- call-fwddecl-bad.ll
target datalayout = "P2"
define void @call_from_fn_in_as2_explicit() addrspace(2) {
call addrspace(2) void bitcast (i8 addrspace(2)* blockaddress(@fwddecl_as1, %bb) to void () addrspace(2)*)()
; CHECK: [[#@LINE-1]]:79: error: 'bb' defined with type 'i8 addrspace(1)*' but expected 'i8 addrspace(2)*'
ret void
}
define void @fwddecl_as1() addrspace(1) {
unreachable
bb:
ret void
}
;--- phi-good.ll
target datalayout = "P2"
define i8 addrspace(1)* @f1() addrspace(1) {
L1:
br label %L3
L2:
br label %L3
L3:
%p = phi i8 addrspace(1)* [ blockaddress(@f1, %L4), %L2 ], [ null, %L1 ]
ret i8 addrspace(1)* %p
L4:
unreachable
}
define i8 addrspace(2)* @f2() {
L1:
br label %L3
L2:
br label %L3
L3:
%p = phi i8 addrspace(2)* [ blockaddress(@f2, %L4), %L2 ], [ null, %L1 ]
ret i8 addrspace(2)* %p
L4:
unreachable
}
;--- phi-bad.ll
target datalayout = "P2"
define i8* @f() {
L1:
br label %L3
L2:
br label %L3
L3:
%p = phi i8* [ blockaddress(@f, %L4), %L2 ], [ null, %L1 ]
; CHECK: [[#@LINE-1]]:18: error: constant expression type mismatch: got type 'i8 addrspace(2)*' but expected 'i8*'
ret i8* %p
}
; A blockaddress function forward-declaration used in a phi node should
; create the forward declaration in the same address space as the current function
;--- fwddecl-phi-good.ll
define i8 addrspace(1)* @f() addrspace(1) {
L1:
br label %L3
L2:
br label %L3
L3:
%p = phi i8 addrspace(1)* [ blockaddress(@fwddecl_as1, %bb), %L2 ], [ null, %L1 ]
ret i8 addrspace(1)* %p
L4:
unreachable
}
define void @fwddecl_as1() addrspace(1) {
unreachable
bb:
ret void
}
;--- fwddecl-phi-bad.ll
define i8 addrspace(2)* @f() addrspace(2) {
L1:
br label %L3
L2:
br label %L3
L3:
%p = phi i8 addrspace(2)* [ blockaddress(@fwddecl_as1, %bb), %L2 ], [ null, %L1 ]
; CHECK: [[#@LINE-1]]:58: error: 'bb' defined with type 'i8 addrspace(1)*' but expected 'i8 addrspace(2)*'
ret i8 addrspace(2)* %p
L4:
unreachable
}
define void @fwddecl_as1() addrspace(1) {
unreachable
bb:
ret void
}
;--- bad-type-not-ptr.ll
@global = constant i8 blockaddress(@unknown_fn, %bb)
; CHECK: [[#@LINE-1]]:23: error: type of blockaddress must be a pointer and not 'i8'
;--- bad-type-not-i8-ptr.ll
@global = constant i32* blockaddress(@unknown_fn, %bb)
; CHECK: [[#@LINE-1]]:25: error: constant expression type mismatch: got type 'i8*' but expected 'i32*'