Skip to content

Commit a4796b1

Browse files
authored
[ARM] Emit error message when incompatible reg is specified (#147559)
At the moment the following piece of code causes undefined behavior: ``` int a; void b() { register float d2 asm("d2") = a; asm("" ::"r"(d2)); } ``` This happens because variable and register types are incompatible.
1 parent 0f2c31d commit a4796b1

File tree

3 files changed

+53
-1
lines changed

3 files changed

+53
-1
lines changed

llvm/lib/Target/ARM/ARMISelLowering.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20347,6 +20347,13 @@ ARMTargetLowering::getSingleConstraintMatchWeight(
2034720347
return weight;
2034820348
}
2034920349

20350+
static bool isIncompatibleReg(const MCPhysReg &PR, MVT VT) {
20351+
if (PR == 0 || VT == MVT::Other)
20352+
return false;
20353+
return (ARM::SPRRegClass.contains(PR) && VT != MVT::f32 && VT != MVT::i32) ||
20354+
(ARM::DPRRegClass.contains(PR) && VT != MVT::f64);
20355+
}
20356+
2035020357
using RCPair = std::pair<unsigned, const TargetRegisterClass *>;
2035120358

2035220359
RCPair ARMTargetLowering::getRegForInlineAsmConstraint(
@@ -20420,7 +20427,10 @@ RCPair ARMTargetLowering::getRegForInlineAsmConstraint(
2042020427
if (StringRef("{cc}").equals_insensitive(Constraint))
2042120428
return std::make_pair(unsigned(ARM::CPSR), &ARM::CCRRegClass);
2042220429

20423-
return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
20430+
auto RCP = TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
20431+
if (isIncompatibleReg(RCP.first, VT))
20432+
return {0, nullptr};
20433+
return RCP;
2042420434
}
2042520435

2042620436
/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
; RUN: not llc -filetype=obj %s -o /dev/null 2>&1 | FileCheck %s
2+
; CHECK: error: couldn't allocate input reg for constraint '{d2}'
3+
; CHECK-NEXT: error: couldn't allocate input reg for constraint '{s2}'
4+
5+
target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
6+
target triple = "armv8a-unknown-linux-gnueabihf"
7+
8+
@a = local_unnamed_addr global i32 0, align 4
9+
10+
define void @_Z1bv() local_unnamed_addr {
11+
entry:
12+
%0 = load i32, ptr @a, align 4
13+
%conv = sext i32 %0 to i64
14+
tail call void asm sideeffect "", "{d2}"(i64 %conv)
15+
ret void
16+
}
17+
18+
define void @_Z1cv() local_unnamed_addr {
19+
entry:
20+
%0 = load i32, ptr @a, align 4
21+
%conv = sext i32 %0 to i64
22+
tail call void asm sideeffect "", "{s2}"(i64 %conv)
23+
ret void
24+
}
25+
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
; RUN: llc -filetype=asm %s -o - | FileCheck %s
2+
3+
; CHECK: movw r0, :lower16:a
4+
; CHECK-NEXT: movt r0, :upper16:a
5+
; CHECK-NEXT: vldr s6, [r0]
6+
7+
target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
8+
target triple = "armv8a-unknown-linux-gnueabihf"
9+
10+
@a = local_unnamed_addr global i32 0, align 4
11+
12+
define void @_Z1dv() local_unnamed_addr {
13+
entry:
14+
%0 = load i32, ptr @a, align 4
15+
tail call void asm sideeffect "", "{s6}"(i32 %0)
16+
ret void
17+
}

0 commit comments

Comments
 (0)