Skip to content

[CIR] Upstream support for cir.get_global #135095

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 10, 2025
Merged

Conversation

andykaylor
Copy link
Contributor

This adds basic support for referencing global variables from within functions via the cir.get_global operation.

@llvmbot llvmbot added clang Clang issues not falling into any other category ClangIR Anything related to the ClangIR project labels Apr 9, 2025
@andykaylor
Copy link
Contributor Author

@mmha

@llvmbot
Copy link
Member

llvmbot commented Apr 9, 2025

@llvm/pr-subscribers-clangir

@llvm/pr-subscribers-clang

Author: Andy Kaylor (andykaylor)

Changes

This adds basic support for referencing global variables from within functions via the cir.get_global operation.


Full diff: https://github.com/llvm/llvm-project/pull/135095.diff

9 Files Affected:

  • (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+31)
  • (modified) clang/include/clang/CIR/MissingFeatures.h (+5)
  • (modified) clang/lib/CIR/CodeGen/CIRGenExpr.cpp (+39-2)
  • (modified) clang/lib/CIR/CodeGen/CIRGenModule.cpp (+100)
  • (modified) clang/lib/CIR/CodeGen/CIRGenModule.h (+25)
  • (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+35)
  • (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+21)
  • (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h (+10)
  • (modified) clang/test/CIR/CodeGen/basic.c (+25)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index ce6f6c70189d9..000eb10e5c4ca 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -1279,6 +1279,37 @@ def GlobalOp : CIR_Op<"global"> {
   let hasVerifier = 1;
 }
 
+//===----------------------------------------------------------------------===//
+// GetGlobalOp
+//===----------------------------------------------------------------------===//
+
+def GetGlobalOp : CIR_Op<"get_global",
+    [Pure, DeclareOpInterfaceMethods<SymbolUserOpInterface>]> {
+  let summary = "Get the address of a global variable";
+  let description = [{
+    The `cir.get_global` operation retrieves the address pointing to a
+    named global variable. If the global variable is marked constant, writing
+    to the resulting address (such as through a `cir.store` operation) is
+    undefined. Resulting type must always be a `!cir.ptr<...>` type with the
+    same address space as the global variable.
+
+    Example:
+    ```mlir
+    %x = cir.get_global @gv : !cir.ptr<i32>
+    ```
+  }];
+
+  let arguments = (ins FlatSymbolRefAttr:$name);
+  let results = (outs Res<CIR_PointerType, "", []>:$addr);
+
+  let assemblyFormat = [{
+    $name `:` qualified(type($addr)) attr-dict
+  }];
+
+  // `GetGlobalOp` is fully verified by its traits.
+  let hasVerifier = 0;
+}
+
 //===----------------------------------------------------------------------===//
 // FuncOp
 //===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index 3188429ea3b1b..70ecb50a93e1d 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -35,6 +35,7 @@ struct MissingFeatures {
   static bool opGlobalThreadLocal() { return false; }
   static bool opGlobalConstant() { return false; }
   static bool opGlobalAlignment() { return false; }
+  static bool opGlobalWeakRef() { return false; }
 
   static bool supportIFuncAttr() { return false; }
   static bool supportVisibility() { return false; }
@@ -113,6 +114,10 @@ struct MissingFeatures {
   static bool incrementProfileCounter() { return false; }
   static bool insertBuiltinUnpredictable() { return false; }
   static bool objCGC() { return false; }
+  static bool setObjCGCLValueClass() { return false; }
+  static bool mangledNames() { return false; }
+  static bool setDLLStorageClass() { return false; }
+  static bool openMP() { return false; }
 
   // Missing types
   static bool dataMemberType() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 4b6652ad0b9e6..de76f5e4dd4d7 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -183,6 +183,43 @@ void CIRGenFunction::emitStoreThroughLValue(RValue src, LValue dst,
   emitStoreOfScalar(src.getScalarVal(), dst, isInit);
 }
 
+static LValue emitGlobalVarDeclLValue(CIRGenFunction &cgf, const Expr *e,
+                                      const VarDecl *vd) {
+  QualType T = e->getType();
+
+  // If it's thread_local, emit a call to its wrapper function instead.
+  assert(!cir::MissingFeatures::opGlobalThreadLocal());
+  if (vd->getTLSKind() == VarDecl::TLS_Dynamic)
+    cgf.cgm.errorNYI(e->getSourceRange(),
+                     "emitGlobalVarDeclLValue: thread_local variable");
+
+  // Check if the variable is marked as declare target with link clause in
+  // device codegen.
+  if (cgf.getLangOpts().OpenMP)
+    cgf.cgm.errorNYI(e->getSourceRange(), "emitGlobalVarDeclLValue: OpenMP");
+
+  // Traditional LLVM codegen handles thread local separately, CIR handles
+  // as part of getAddrOfGlobalVar.
+  mlir::Value v = cgf.cgm.getAddrOfGlobalVar(vd);
+
+  assert(!cir::MissingFeatures::addressSpace());
+  mlir::Type realVarTy = cgf.convertTypeForMem(vd->getType());
+  cir::PointerType realPtrTy = cgf.getBuilder().getPointerTo(realVarTy);
+  if (realPtrTy != v.getType())
+    v = cgf.getBuilder().createBitcast(v.getLoc(), v, realPtrTy);
+
+  CharUnits alignment = cgf.getContext().getDeclAlign(vd);
+  Address addr(v, realVarTy, alignment);
+  LValue lv;
+  if (vd->getType()->isReferenceType())
+    cgf.cgm.errorNYI(e->getSourceRange(),
+                     "emitGlobalVarDeclLValue: reference type");
+  else
+    lv = cgf.makeAddrLValue(addr, T, AlignmentSource::Decl);
+  assert(!cir::MissingFeatures::setObjCGCLValueClass());
+  return lv;
+}
+
 void CIRGenFunction::emitStoreOfScalar(mlir::Value value, Address addr,
                                        bool isVolatile, QualType ty,
                                        bool isInit, bool isNontemporal) {
@@ -288,7 +325,7 @@ LValue CIRGenFunction::emitDeclRefLValue(const DeclRefExpr *e) {
 
     // Check if this is a global variable
     if (vd->hasLinkage() || vd->isStaticDataMember())
-      cgm.errorNYI(vd->getSourceRange(), "emitDeclRefLValue: global variable");
+      return emitGlobalVarDeclLValue(*this, e, vd);
 
     Address addr = Address::invalid();
 
@@ -299,7 +336,7 @@ LValue CIRGenFunction::emitDeclRefLValue(const DeclRefExpr *e) {
     } else {
       // Otherwise, it might be static local we haven't emitted yet for some
       // reason; most likely, because it's in an outer function.
-      cgm.errorNYI(vd->getSourceRange(), "emitDeclRefLValue: static local");
+      cgm.errorNYI(e->getSourceRange(), "emitDeclRefLValue: static local");
     }
 
     return makeAddrLValue(addr, ty, AlignmentSource::Type);
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index d2259a9c41d22..3eecbfb7973fd 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -200,6 +200,105 @@ void CIRGenModule::emitGlobalFunctionDefinition(clang::GlobalDecl gd,
   }
 }
 
+mlir::Operation *CIRGenModule::getGlobalValue(StringRef name) {
+  mlir::Operation *global = mlir::SymbolTable::lookupSymbolIn(theModule, name);
+  if (!global)
+    return nullptr;
+  return global;
+}
+
+/// If the specified mangled name is not in the module,
+/// create and return an mlir GlobalOp with the specified type (TODO(cir):
+/// address space).
+///
+/// TODO(cir):
+/// 1. If there is something in the module with the specified name, return
+/// it potentially bitcasted to the right type.
+///
+/// 2. If \p d is non-null, it specifies a decl that correspond to this.  This
+/// is used to set the attributes on the global when it is first created.
+///
+/// 3. If \p isForDefinition is true, it is guaranteed that an actual global
+/// with type \p ty will be returned, not conversion of a variable with the same
+/// mangled name but some other type.
+cir::GlobalOp
+CIRGenModule::getOrCreateCIRGlobal(StringRef mangledName, mlir::Type ty,
+                                   LangAS langAS, const VarDecl *d,
+                                   ForDefinition_t isForDefinition) {
+  // Lookup the entry, lazily creating it if necessary.
+  cir::GlobalOp entry;
+  if (mlir::Operation *v = getGlobalValue(mangledName)) {
+    if (!isa<cir::GlobalOp>(v))
+      errorNYI(d->getSourceRange(), "global with non-GlobalOp type");
+    entry = cast<cir::GlobalOp>(v);
+  }
+
+  if (entry) {
+    assert(!cir::MissingFeatures::addressSpace());
+    assert(!cir::MissingFeatures::opGlobalWeakRef());
+
+    assert(!cir::MissingFeatures::setDLLStorageClass());
+    assert(!cir::MissingFeatures::openMP());
+
+    if (entry.getSymType() == ty)
+      return entry;
+
+    // If there are two attempts to define the same mangled name, issue an
+    // error.
+    //
+    // TODO(cir): look at mlir::GlobalValue::isDeclaration for all aspects of
+    // recognizing the global as a declaration, for now only check if
+    // initializer is present.
+    if (isForDefinition && !entry.isDeclaration()) {
+      errorNYI(d->getSourceRange(), "global with conflicting type");
+    }
+
+    // Address space check removed because it is unnecessary because CIR records
+    // address space info in types.
+
+    // (If global is requested for a definition, we always need to create a new
+    // global, not just return a bitcast.)
+    if (!isForDefinition)
+      return entry;
+  }
+
+  errorNYI(d->getSourceRange(), "reference of undeclared global");
+}
+
+cir::GlobalOp
+CIRGenModule::getOrCreateCIRGlobal(const VarDecl *d, mlir::Type ty,
+                                   ForDefinition_t isForDefinition) {
+  assert(d->hasGlobalStorage() && "Not a global variable");
+  QualType astTy = d->getType();
+  if (!ty)
+    ty = getTypes().convertTypeForMem(astTy);
+
+  assert(!cir::MissingFeatures::mangledNames());
+  return getOrCreateCIRGlobal(d->getIdentifier()->getName(), ty,
+                              astTy.getAddressSpace(), d, isForDefinition);
+}
+
+/// Return the mlir::Value for the address of the given global variable. If
+/// \p ty is non-null and if the global doesn't exist, then it will be created
+/// with the specified type instead of whatever the normal requested type would
+/// be. If \p isForDefinition is true, it is guaranteed that an actual global
+/// with type \p ty will be returned, not conversion of a variable with the same
+/// mangled name but some other type.
+mlir::Value CIRGenModule::getAddrOfGlobalVar(const VarDecl *d, mlir::Type ty,
+                                             ForDefinition_t isForDefinition) {
+  assert(d->hasGlobalStorage() && "Not a global variable");
+  QualType astTy = d->getType();
+  if (!ty)
+    ty = getTypes().convertTypeForMem(astTy);
+
+  assert(!cir::MissingFeatures::opGlobalThreadLocal());
+
+  cir::GlobalOp g = getOrCreateCIRGlobal(d, ty, isForDefinition);
+  mlir::Type ptrTy = builder.getPointerTo(g.getSymType());
+  return builder.create<cir::GetGlobalOp>(getLoc(d->getSourceRange()), ptrTy,
+                                          g.getSymName());
+}
+
 void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd,
                                            bool isTentative) {
   const QualType astTy = vd->getType();
@@ -505,6 +604,7 @@ cir::FuncOp CIRGenModule::getAddrOfFunction(clang::GlobalDecl gd,
     funcType = convertType(fd->getType());
   }
 
+  assert(!cir::MissingFeatures::mangledNames());
   cir::FuncOp func = getOrCreateCIRFunction(
       cast<NamedDecl>(gd.getDecl())->getIdentifier()->getName(), funcType, gd,
       forVTable, dontDefer, /*isThunk=*/false, isForDefinition);
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h
index fe39244fc7834..b57228a4263fc 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.h
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -85,6 +85,31 @@ class CIRGenModule : public CIRGenTypeCache {
   const clang::LangOptions &getLangOpts() const { return langOpts; }
   mlir::MLIRContext &getMLIRContext() { return *builder.getContext(); }
 
+  /// -------
+  /// Handling globals
+  /// -------
+
+  mlir::Operation *getGlobalValue(llvm::StringRef ref);
+
+  /// If the specified mangled name is not in the module, create and return an
+  /// mlir::GlobalOp value
+  cir::GlobalOp getOrCreateCIRGlobal(llvm::StringRef mangledName, mlir::Type ty,
+                                     LangAS langAS, const VarDecl *d,
+                                     ForDefinition_t isForDefinition);
+
+  cir::GlobalOp getOrCreateCIRGlobal(const VarDecl *d, mlir::Type ty,
+                                     ForDefinition_t isForDefinition);
+
+  /// Return the mlir::Value for the address of the given global variable.
+  /// If Ty is non-null and if the global doesn't exist, then it will be created
+  /// with the specified type instead of whatever the normal requested type
+  /// would be. If IsForDefinition is true, it is guaranteed that an actual
+  /// global with type Ty will be returned, not conversion of a variable with
+  /// the same mangled name but some other type.
+  mlir::Value
+  getAddrOfGlobalVar(const VarDecl *d, mlir::Type ty = {},
+                     ForDefinition_t isForDefinition = NotForDefinition);
+
   /// Helpers to convert the presumed location of Clang's SourceLocation to an
   /// MLIR Location.
   mlir::Location getLoc(clang::SourceLocation cLoc);
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 6bac6123a339d..b4822ea1d8236 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -764,6 +764,41 @@ parseGlobalOpTypeAndInitialValue(OpAsmParser &parser, TypeAttr &typeAttr,
   return success();
 }
 
+//===----------------------------------------------------------------------===//
+// GetGlobalOp
+//===----------------------------------------------------------------------===//
+
+LogicalResult
+cir::GetGlobalOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
+  // Verify that the result type underlying pointer type matches the type of
+  // the referenced cir.global or cir.func op.
+  mlir::Operation *op =
+      symbolTable.lookupNearestSymbolFrom(*this, getNameAttr());
+  if (op == nullptr || !(isa<GlobalOp>(op) || isa<FuncOp>(op)))
+    return emitOpError("'")
+           << getName()
+           << "' does not reference a valid cir.global or cir.func";
+
+  mlir::Type symTy;
+  if (auto g = dyn_cast<GlobalOp>(op)) {
+    symTy = g.getSymType();
+    assert(!cir::MissingFeatures::addressSpace());
+    assert(!cir::MissingFeatures::opGlobalThreadLocal());
+  } else if (auto f = dyn_cast<FuncOp>(op)) {
+    symTy = f.getFunctionType();
+  } else {
+    llvm_unreachable("Unexpected operation for GetGlobalOp");
+  }
+
+  auto resultType = dyn_cast<PointerType>(getAddr().getType());
+  if (!resultType || symTy != resultType.getPointee())
+    return emitOpError("result type pointee type '")
+           << resultType.getPointee() << "' does not match type " << symTy
+           << " of the global @" << getName();
+
+  return success();
+}
+
 //===----------------------------------------------------------------------===//
 // FuncOp
 //===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 7ca36409c9cac..7159f89c93a53 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -828,6 +828,26 @@ mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
   return mlir::LogicalResult::success();
 }
 
+mlir::LogicalResult CIRToLLVMGetGlobalOpLowering::matchAndRewrite(
+    cir::GetGlobalOp op, OpAdaptor adaptor,
+    mlir::ConversionPatternRewriter &rewriter) const {
+  // FIXME(cir): Premature DCE to avoid lowering stuff we're not using.
+  // CIRGen should mitigate this and not emit the get_global.
+  if (op->getUses().empty()) {
+    rewriter.eraseOp(op);
+    return mlir::success();
+  }
+
+  mlir::Type type = getTypeConverter()->convertType(op.getType());
+  mlir::Operation *newop =
+      rewriter.create<mlir::LLVM::AddressOfOp>(op.getLoc(), type, op.getName());
+
+  assert(!cir::MissingFeatures::opGlobalThreadLocal());
+
+  rewriter.replaceOp(op, newop);
+  return mlir::success();
+}
+
 /// Replace CIR global with a region initialized LLVM global and update
 /// insertion point to the end of the initializer block.
 void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp(
@@ -1418,6 +1438,7 @@ void ConvertCIRToLLVMPass::runOnOperation() {
                CIRToLLVMCmpOpLowering,
                CIRToLLVMConstantOpLowering,
                CIRToLLVMFuncOpLowering,
+               CIRToLLVMGetGlobalOpLowering,
                CIRToLLVMTrapOpLowering,
                CIRToLLVMUnaryOpLowering
       // clang-format on
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
index d53c4b31682bb..1de6c9c56b485 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
@@ -140,6 +140,16 @@ class CIRToLLVMFuncOpLowering : public mlir::OpConversionPattern<cir::FuncOp> {
                   mlir::ConversionPatternRewriter &) const override;
 };
 
+class CIRToLLVMGetGlobalOpLowering
+    : public mlir::OpConversionPattern<cir::GetGlobalOp> {
+public:
+  using mlir::OpConversionPattern<cir::GetGlobalOp>::OpConversionPattern;
+
+  mlir::LogicalResult
+  matchAndRewrite(cir::GetGlobalOp op, OpAdaptor,
+                  mlir::ConversionPatternRewriter &) const override;
+};
+
 class CIRToLLVMGlobalOpLowering
     : public mlir::OpConversionPattern<cir::GlobalOp> {
   const mlir::DataLayout &dataLayout;
diff --git a/clang/test/CIR/CodeGen/basic.c b/clang/test/CIR/CodeGen/basic.c
index 7184e395ce386..cf687e44044c4 100644
--- a/clang/test/CIR/CodeGen/basic.c
+++ b/clang/test/CIR/CodeGen/basic.c
@@ -144,3 +144,28 @@ void f5(void) {
 // OGCG:   br label %[[LOOP:.*]]
 // OGCG: [[LOOP]]:
 // OGCG:   br label %[[LOOP]]
+
+int gv;
+int f6(void) {
+  return gv;
+}
+
+//      CIR: cir.func @f6() -> !s32i
+// CIR-NEXT:   %[[RV:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"] {alignment = 4 : i64}
+// CIR-NEXT:   %[[GV_PTR:.*]] = cir.get_global @gv : !cir.ptr<!s32i>
+// CIR-NEXT:   %[[GV:.*]] = cir.load %[[GV_PTR]] : !cir.ptr<!s32i>, !s32i
+// CIR-NEXT:   cir.store %[[GV]], %[[RV]] : !s32i, !cir.ptr<!s32i>
+// CIR-NEXT:   %[[R:.*]] = cir.load %[[RV]] : !cir.ptr<!s32i>, !s32i
+// CIR-NEXT:   cir.return %[[R]] : !s32i
+
+// LLVM:      define i32 @f6()
+// LLVM-NEXT:   %[[RV_PTR:.*]] = alloca i32, i64 1, align 4
+// LLVM-NEXT:   %[[GV:.*]] = load i32, ptr @gv, align 4
+// LLVM-NEXT:   store i32 %[[GV]], ptr %[[RV_PTR]], align 4
+// LLVM-NEXT:   %[[RV:.*]] = load i32, ptr %[[RV_PTR]], align 4
+// LLVM-NEXT:   ret i32 %[[RV]]
+
+// OGCG:      define{{.*}} i32 @f6()
+// OGCG-NEXT: entry:
+// OGCG-NEXT:   %[[GV:.*]] = load i32, ptr @gv, align 4
+// OGCG-NEXT:   ret i32 %[[GV]]

The `cir.get_global` operation retrieves the address pointing to a
named global variable. If the global variable is marked constant, writing
to the resulting address (such as through a `cir.store` operation) is
undefined. Resulting type must always be a `!cir.ptr<...>` type with the
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
undefined. Resulting type must always be a `!cir.ptr<...>` type with the
undefined. The resulting type must always be a `!cir.ptr<...>` type with the

@@ -200,6 +200,105 @@ void CIRGenModule::emitGlobalFunctionDefinition(clang::GlobalDecl gd,
}
}

mlir::Operation *CIRGenModule::getGlobalValue(StringRef name) {
mlir::Operation *global = mlir::SymbolTable::lookupSymbolIn(theModule, name);
if (!global)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Er... what does this do? This 'if' ends up being a do-nothing here, since it just returns 'global' anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, weird. The incubator code had return {}; here, so it wasn't as obvious. I changed that to nullptr since it was actually returning a pointer and not an MLIR value, but I didn't notice the obvious redundancy of this. I'm pretty sure you're right that we can just return from line 204.

entry = cast<cir::GlobalOp>(v);
}

if (entry) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we invert this and do an eraly-return to save everything below the tab?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There will be a bunch of things that need to happen after all of this when the implementation is complete. When we've done everything here, if isForDefinition is true, we fall through to execute the same code that handles the case where entry is null.

This adds basic support for referencing global variables from within
functions via the cir.get_global operation.
@andykaylor andykaylor merged commit db22909 into llvm:main Apr 10, 2025
11 checks passed
@andykaylor andykaylor deleted the cir-getglobal branch April 10, 2025 21:15
YonahGoldberg pushed a commit to YonahGoldberg/llvm-project that referenced this pull request Apr 10, 2025
This adds basic support for referencing global variables from within
functions via the cir.get_global operation.
var-const pushed a commit to ldionne/llvm-project that referenced this pull request Apr 17, 2025
This adds basic support for referencing global variables from within
functions via the cir.get_global operation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang Clang issues not falling into any other category ClangIR Anything related to the ClangIR project
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants