From 4277124e8acb8efed73dee9bc32a1744c807dcdf Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 21 Mar 2025 16:35:02 -0700 Subject: [PATCH 1/4] [TableGen] Validate the shift amount for !srl, !shl, and !sra operators. The C operator has undefined behavior for out of bounds shifts so we should check this. --- llvm/lib/TableGen/Record.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp index c5b9b670b6f42..655c4078697f3 100644 --- a/llvm/lib/TableGen/Record.cpp +++ b/llvm/lib/TableGen/Record.cpp @@ -1537,7 +1537,13 @@ const Init *BinOpInit::Fold(const Record *CurRec) const { if (LHSi && RHSi) { int64_t LHSv = LHSi->getValue(), RHSv = RHSi->getValue(); int64_t Result; - switch (getOpcode()) { + + unsigned Opc = getOpcode(); + if ((Opc == SHL || Opc == SRA || Opc == SRL) && (RHSv < 0 || RHSv >= 64)) + PrintFatalError(CurRec->getLoc(), + "Illegal operation: out of bounds shift"); + + switch (Opc) { default: llvm_unreachable("Bad opcode!"); case ADD: Result = LHSv + RHSv; break; case SUB: Result = LHSv - RHSv; break; @@ -1556,7 +1562,7 @@ const Init *BinOpInit::Fold(const Record *CurRec) const { case OR: Result = LHSv | RHSv; break; case XOR: Result = LHSv ^ RHSv; break; case SHL: Result = (uint64_t)LHSv << (uint64_t)RHSv; break; - case SRA: Result = LHSv >> RHSv; break; + case SRA: Result = LHSv >> (uint64_t)RHSv; break; case SRL: Result = (uint64_t)LHSv >> (uint64_t)RHSv; break; } return IntInit::get(getRecordKeeper(), Result); From a87d75a4056b8844b588acf9895c021292399be5 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Tue, 12 Aug 2025 13:11:58 -0700 Subject: [PATCH 2/4] fixup! Address review comments --- llvm/lib/TableGen/Record.cpp | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp index c2f9b884bb800..633f55db18681 100644 --- a/llvm/lib/TableGen/Record.cpp +++ b/llvm/lib/TableGen/Record.cpp @@ -1547,12 +1547,7 @@ const Init *BinOpInit::Fold(const Record *CurRec) const { int64_t LHSv = LHSi->getValue(), RHSv = RHSi->getValue(); int64_t Result; - unsigned Opc = getOpcode(); - if ((Opc == SHL || Opc == SRA || Opc == SRL) && (RHSv < 0 || RHSv >= 64)) - PrintFatalError(CurRec->getLoc(), - "Illegal operation: out of bounds shift"); - - switch (Opc) { + switch (getOpcode()) { default: llvm_unreachable("Bad opcode!"); case ADD: Result = LHSv + RHSv; break; case SUB: Result = LHSv - RHSv; break; @@ -1570,9 +1565,24 @@ const Init *BinOpInit::Fold(const Record *CurRec) const { case AND: Result = LHSv & RHSv; break; case OR: Result = LHSv | RHSv; break; case XOR: Result = LHSv ^ RHSv; break; - case SHL: Result = (uint64_t)LHSv << (uint64_t)RHSv; break; - case SRA: Result = LHSv >> (uint64_t)RHSv; break; - case SRL: Result = (uint64_t)LHSv >> (uint64_t)RHSv; break; + case SHL: + if (RHSv < 0 || RHSv >= 64) + PrintFatalError(CurRec->getLoc(), + "Illegal operation: out of bounds shift"); + Result = (uint64_t)LHSv << (uint64_t)RHSv; + break; + case SRA: + if (RHSv < 0 || RHSv >= 64) + PrintFatalError(CurRec->getLoc(), + "Illegal operation: out of bounds shift"); + Result = LHSv >> (uint64_t)RHSv; + break; + case SRL: + if (RHSv < 0 || RHSv >= 64) + PrintFatalError(CurRec->getLoc(), + "Illegal operation: out of bounds shift"); + Result = (uint64_t)LHSv >> (uint64_t)RHSv; + break; } return IntInit::get(getRecordKeeper(), Result); } From cbbf70c8ac5d25621bb3338089e3c37614d0820b Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Tue, 12 Aug 2025 13:17:20 -0700 Subject: [PATCH 3/4] fixup! Add test --- llvm/test/TableGen/math.td | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/llvm/test/TableGen/math.td b/llvm/test/TableGen/math.td index 64151a5ca0075..fe8faf0a79e33 100644 --- a/llvm/test/TableGen/math.td +++ b/llvm/test/TableGen/math.td @@ -3,6 +3,9 @@ // RUN: not llvm-tblgen -DERROR2 %s 2>&1 | FileCheck --check-prefix=ERROR2 %s // RUN: not llvm-tblgen -DERROR3 %s 2>&1 | FileCheck --check-prefix=ERROR3 %s // RUN: not llvm-tblgen -DERROR4 %s 2>&1 | FileCheck --check-prefix=ERROR4 %s +// RUN: not llvm-tblgen -DERROR5 %s 2>&1 | FileCheck --check-prefix=ERROR5 %s +// RUN: not llvm-tblgen -DERROR6 %s 2>&1 | FileCheck --check-prefix=ERROR6 %s +// RUN: not llvm-tblgen -DERROR7 %s 2>&1 | FileCheck --check-prefix=ERROR7 %s // XFAIL: vg_leak // CHECK: def shifts @@ -143,3 +146,18 @@ def v954 : Int; // CHECK: def vneg // CHECK: Value = -2 def vneg : Int; + +#ifdef ERROR5 +// ERROR5: error: Illegal operation: out of bounds shift +def vshl_neg : Int; +#endif + +#ifdef ERROR6 +// ERROR6: error: Illegal operation: out of bounds shift +def vsra_large : Int; +#endif + +#ifdef ERROR7 +// ERROR7: error: Illegal operation: out of bounds shift +def vsrl_large : Int; +#endif From 16e48f6109f1ffe01c79a2216ca710da7f985c5c Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Thu, 21 Aug 2025 22:40:56 -0700 Subject: [PATCH 4/4] Update llvm/lib/TableGen/Record.cpp --- llvm/lib/TableGen/Record.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp index 633f55db18681..3657a15ab1989 100644 --- a/llvm/lib/TableGen/Record.cpp +++ b/llvm/lib/TableGen/Record.cpp @@ -1546,7 +1546,6 @@ const Init *BinOpInit::Fold(const Record *CurRec) const { if (LHSi && RHSi) { int64_t LHSv = LHSi->getValue(), RHSv = RHSi->getValue(); int64_t Result; - switch (getOpcode()) { default: llvm_unreachable("Bad opcode!"); case ADD: Result = LHSv + RHSv; break;