[llvm] 5cc87b4 - [AsmParser] Add missing globals declarations in incomplete IR mode (#79855)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 31 03:24:38 PST 2024


Author: Nikita Popov
Date: 2024-01-31T12:24:35+01:00
New Revision: 5cc87b424be87db4247f34ae5477be8b09a573e9

URL: https://github.com/llvm/llvm-project/commit/5cc87b424be87db4247f34ae5477be8b09a573e9
DIFF: https://github.com/llvm/llvm-project/commit/5cc87b424be87db4247f34ae5477be8b09a573e9.diff

LOG: [AsmParser] Add missing globals declarations in incomplete IR mode (#79855)

If `-allow-incomplete-ir` is enabled, automatically insert declarations
for missing globals.

If a global is only used in calls with the same function type, insert a
function declaration with that type.

Otherwise, insert a dummy i8 global. The fallback case could be extended
with various heuristics (e.g. we could look at load/store types), but
I've chosen to keep it simple for now, because I'm unsure to what degree
this would really useful without more experience. I expect that in most
cases the declaration type doesn't really matter (note that the type of
an external global specifies a *minimum* size only, not a precise size).

This is a followup to https://github.com/llvm/llvm-project/pull/78421.

Added: 
    llvm/test/Assembler/incomplete-ir-declarations.ll

Modified: 
    llvm/lib/AsmParser/LLParser.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index d6c5993797de1..e111ca9c7e6b5 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -303,15 +303,7 @@ bool LLParser::validateEndOfModule(bool UpgradeDebugInfo) {
                  "use of undefined comdat '$" +
                      ForwardRefComdats.begin()->first + "'");
 
-  // Automatically create declarations for intrinsics. Intrinsics can only be
-  // called directly, so the call function type directly determines the
-  // declaration function type.
   for (const auto &[Name, Info] : make_early_inc_range(ForwardRefVals)) {
-    if (!StringRef(Name).starts_with("llvm."))
-      continue;
-
-    // Don't do anything if the intrinsic is called with 
diff erent function
-    // types. This would result in a verifier error anyway.
     auto GetCommonFunctionType = [](Value *V) -> FunctionType * {
       FunctionType *FTy = nullptr;
       for (User *U : V->users()) {
@@ -322,10 +314,38 @@ bool LLParser::validateEndOfModule(bool UpgradeDebugInfo) {
       }
       return FTy;
     };
-    if (FunctionType *FTy = GetCommonFunctionType(Info.first)) {
-      Function *Fn =
-          Function::Create(FTy, GlobalValue::ExternalLinkage, Name, M);
-      Info.first->replaceAllUsesWith(Fn);
+
+    auto GetDeclarationType = [&](StringRef Name, Value *V) -> Type * {
+      // Automatically create declarations for intrinsics. Intrinsics can only
+      // be called directly, so the call function type directly determines the
+      // declaration function type.
+      if (Name.starts_with("llvm."))
+        // Don't do anything if the intrinsic is called with 
diff erent function
+        // types. This would result in a verifier error anyway.
+        return GetCommonFunctionType(V);
+
+      if (AllowIncompleteIR) {
+        // If incomplete IR is allowed, also add declarations for
+        // non-intrinsics. First check whether this global is only used in
+        // calls with the same type, in which case we'll insert a function.
+        if (auto *Ty = GetCommonFunctionType(V))
+          return Ty;
+
+        // Otherwise, fall back to using a dummy i8 type.
+        return Type::getInt8Ty(Context);
+      }
+      return nullptr;
+    };
+
+    if (Type *Ty = GetDeclarationType(Name, Info.first)) {
+      GlobalValue *GV;
+      if (auto *FTy = dyn_cast<FunctionType>(Ty))
+        GV = Function::Create(FTy, GlobalValue::ExternalLinkage, Name, M);
+      else
+        GV = new GlobalVariable(*M, Ty, /*isConstant*/ false,
+                                GlobalValue::ExternalLinkage,
+                                /*Initializer*/ nullptr, Name);
+      Info.first->replaceAllUsesWith(GV);
       Info.first->eraseFromParent();
       ForwardRefVals.erase(Name);
     }

diff  --git a/llvm/test/Assembler/incomplete-ir-declarations.ll b/llvm/test/Assembler/incomplete-ir-declarations.ll
new file mode 100644
index 0000000000000..6cdff80883c27
--- /dev/null
+++ b/llvm/test/Assembler/incomplete-ir-declarations.ll
@@ -0,0 +1,20 @@
+; RUN: opt -S -allow-incomplete-ir < %s | FileCheck %s
+
+; CHECK: @fn2 = external global i8
+; CHECK: @g1 = external global i8
+; CHECK: @g2 = external global i8
+; CHECK: @g3 = external global i8
+
+; CHECK: declare void @fn1(i32)
+
+define ptr @test() {
+  call void @fn1(i32 0)
+  call void @fn1(i32 1)
+  call void @fn2(i32 2)
+  call void @fn2(i32 2, i32 3)
+  load i32, ptr @g1
+  store i32 0, ptr @g1
+  load i32, ptr @g1
+  load i64, ptr @g2
+  ret ptr @g3
+}


        


More information about the llvm-commits mailing list