[llvm] [IR] Don't allow label arguments (PR #137799)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 29 06:29:42 PDT 2025


https://github.com/nikic updated https://github.com/llvm/llvm-project/pull/137799

>From a86463295b57c4f93380482df9cfb7254695c78b Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Tue, 29 Apr 2025 13:03:45 +0200
Subject: [PATCH 1/2] [IR] Don't allow label arguments

We currently accept label arguments to inline asm calls. Remove
this in favor of callbr, or at least the use of blockaddress.

I didn't bother implementing bitcode upgrade support for this,
as we just have one very old test for this functionality, but I
can add it if desired.
---
 llvm/lib/AsmParser/LLParser.cpp               | 4 +++-
 llvm/lib/Bitcode/Writer/BitcodeWriter.cpp     | 9 ++-------
 llvm/lib/IR/Type.cpp                          | 2 +-
 llvm/lib/IR/Verifier.cpp                      | 2 --
 llvm/test/Assembler/invalid-label-call-arg.ll | 9 +++++++++
 llvm/test/Assembler/invalid-label.ll          | 2 +-
 llvm/test/CodeGen/X86/asm-block-labels.ll     | 6 +++---
 llvm/test/Verifier/invalid-label-param.ll     | 6 +-----
 8 files changed, 20 insertions(+), 20 deletions(-)
 create mode 100644 llvm/test/Assembler/invalid-label-call-arg.ll

diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 370d124dc42b4..dd37d9b9e3796 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -3072,6 +3072,8 @@ bool LLParser::parseParameterList(SmallVectorImpl<ParamInfo> &ArgList,
     Value *V;
     if (parseType(ArgTy, ArgLoc))
       return true;
+    if (!FunctionType::isValidArgumentType(ArgTy))
+      return error(ArgLoc, "invalid type for function argument");
 
     AttrBuilder ArgAttrs(M->getContext());
 
@@ -3381,7 +3383,7 @@ bool LLParser::parseArgumentList(SmallVectorImpl<ArgInfo> &ArgList,
         CurValID = ArgID + 1;
       }
 
-      if (!ArgTy->isFirstClassType())
+      if (!FunctionType::isValidArgumentType(ArgTy))
         return error(TypeLoc, "invalid type for function argument");
 
       ArgList.emplace_back(TypeLoc, ArgTy,
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 73bed85c65b3d..5226db9db1e03 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -3488,13 +3488,8 @@ void ModuleBitcodeWriter::writeInstruction(const Instruction &I,
     pushValueAndType(CI.getCalledOperand(), InstID, Vals); // Callee
 
     // Emit value #'s for the fixed parameters.
-    for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) {
-      // Check for labels (can happen with asm labels).
-      if (FTy->getParamType(i)->isLabelTy())
-        Vals.push_back(VE.getValueID(CI.getArgOperand(i)));
-      else
-        pushValue(CI.getArgOperand(i), InstID, Vals); // fixed param.
-    }
+    for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i)
+      pushValue(CI.getArgOperand(i), InstID, Vals); // fixed param.
 
     // Emit type/value pairs for varargs params.
     if (FTy->isVarArg()) {
diff --git a/llvm/lib/IR/Type.cpp b/llvm/lib/IR/Type.cpp
index 884609e734298..1c68b173364f9 100644
--- a/llvm/lib/IR/Type.cpp
+++ b/llvm/lib/IR/Type.cpp
@@ -390,7 +390,7 @@ bool FunctionType::isValidReturnType(Type *RetTy) {
 }
 
 bool FunctionType::isValidArgumentType(Type *ArgTy) {
-  return ArgTy->isFirstClassType();
+  return ArgTy->isFirstClassType() && !ArgTy->isLabelTy();
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 262e7022099d7..28ba944d8ede3 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -2934,8 +2934,6 @@ void Verifier::visitFunction(const Function &F) {
           FT->getParamType(i));
     Check(Arg.getType()->isFirstClassType(),
           "Function arguments must have first-class types!", &Arg);
-    Check(!Arg.getType()->isLabelTy(),
-          "Function argument cannot be of label type!", &Arg, &F);
     if (!IsIntrinsic) {
       Check(!Arg.getType()->isMetadataTy(),
             "Function takes metadata but isn't an intrinsic", &Arg, &F);
diff --git a/llvm/test/Assembler/invalid-label-call-arg.ll b/llvm/test/Assembler/invalid-label-call-arg.ll
new file mode 100644
index 0000000000000..575ec6b05e38e
--- /dev/null
+++ b/llvm/test/Assembler/invalid-label-call-arg.ll
@@ -0,0 +1,9 @@
+; RUN: not llvm-as < %s 2>&1 | FileCheck %s
+
+; CHECK: invalid type for function argument
+define void @test() {
+bb:
+  call void asm "", ""(label %bb)
+  ret void
+}
+
diff --git a/llvm/test/Assembler/invalid-label.ll b/llvm/test/Assembler/invalid-label.ll
index 33dc63610aae3..ae464b362135b 100644
--- a/llvm/test/Assembler/invalid-label.ll
+++ b/llvm/test/Assembler/invalid-label.ll
@@ -2,7 +2,7 @@
 ; RUN: FileCheck %s < %t
 ; Test the case where an invalid label name is used
 
-; CHECK: unable to create block named 'bb'
+; CHECK: invalid type for function argument
 
 define void @test(label %bb) {
 bb:
diff --git a/llvm/test/CodeGen/X86/asm-block-labels.ll b/llvm/test/CodeGen/X86/asm-block-labels.ll
index 44bb7518ab6ee..fd78c793fa73e 100644
--- a/llvm/test/CodeGen/X86/asm-block-labels.ll
+++ b/llvm/test/CodeGen/X86/asm-block-labels.ll
@@ -13,7 +13,7 @@ entry:
 	call void asm sideeffect "int $$1", "~{dirflag},~{fpsr},~{flags},~{memory}"( )
 	call void asm sideeffect ".file \22block12.c\22", "~{dirflag},~{fpsr},~{flags}"( )
 	call void asm sideeffect ".line 2", "~{dirflag},~{fpsr},~{flags}"( )
-	call void asm sideeffect "brl ${0:l}", "X,~{dirflag},~{fpsr},~{flags},~{memory}"( label %"LASM$foo" )
+	call void asm sideeffect "brl ${0:l}", "X,~{dirflag},~{fpsr},~{flags},~{memory}"(ptr blockaddress(@bar, %"LASM$foo"))
 	br label %return
 
 return:		; preds = %"LASM$foo"
@@ -24,7 +24,7 @@ define void @baz() {
 entry:
 	call void asm sideeffect ".file \22block12.c\22", "~{dirflag},~{fpsr},~{flags}"( )
 	call void asm sideeffect ".line 3", "~{dirflag},~{fpsr},~{flags}"( )
-	call void asm sideeffect "brl ${0:l}", "X,~{dirflag},~{fpsr},~{flags},~{memory}"( label %"LASM$foo" )
+	call void asm sideeffect "brl ${0:l}", "X,~{dirflag},~{fpsr},~{flags},~{memory}"(ptr blockaddress(@baz, %"LASM$foo"))
 	call void asm sideeffect ".file \22block12.c\22", "~{dirflag},~{fpsr},~{flags}"( )
 	call void asm sideeffect ".line 4", "~{dirflag},~{fpsr},~{flags}"( )
 	call void asm sideeffect "int $$1", "~{dirflag},~{fpsr},~{flags},~{memory}"( )
@@ -42,7 +42,7 @@ return:		; preds = %"LASM$foo"
 
 define void @quux() {
 entry:
-	call void asm sideeffect inteldialect "brl ${0:l}", "X,~{dirflag},~{fpsr},~{flags},~{memory}"( label %"LASM$foo" )
+	call void asm sideeffect inteldialect "brl ${0:l}", "X,~{dirflag},~{fpsr},~{flags},~{memory}"(ptr blockaddress(@quux, %"LASM$foo"))
 	br label %"LASM$foo"
 
 "LASM$foo":		; preds = %entry
diff --git a/llvm/test/Verifier/invalid-label-param.ll b/llvm/test/Verifier/invalid-label-param.ll
index c89ce99ce1e9f..92d8b80086dcb 100644
--- a/llvm/test/Verifier/invalid-label-param.ll
+++ b/llvm/test/Verifier/invalid-label-param.ll
@@ -7,8 +7,4 @@ define void @invalid_arg_type(i32 %0) {
 }
 
 declare void @foo(label)
-; CHECK: Function argument cannot be of label type!
-; CHECK-NEXT: label %0
-; CHECK-NEXT: ptr @foo
-
-
+; CHECK: invalid type for function argument

>From 901abf075f49ec61193a5a1b97c71f284c95e608 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Tue, 29 Apr 2025 15:29:24 +0200
Subject: [PATCH 2/2] Add release note

---
 llvm/docs/ReleaseNotes.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 9e2e63cffdf82..aded1bd67ed76 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -64,6 +64,7 @@ Changes to the LLVM IR
 
 * Updated semantics of `llvm.type.checked.load.relative` to match that of
   `llvm.load.relative`.
+* Inline asm calls no longer accept ``label`` arguments. Use ``callbr`` instead.
 
 Changes to LLVM infrastructure
 ------------------------------



More information about the llvm-commits mailing list