Skip to content
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

[CIR][CodeGen] support array def after decl with unknown bound #375

Merged
merged 2 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 39 additions & 6 deletions clang/lib/CIR/CodeGen/CIRGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,8 @@ mlir::Value CIRGenModule::getGlobalValue(const Decl *D) {
mlir::cir::GlobalOp CIRGenModule::createGlobalOp(CIRGenModule &CGM,
mlir::Location loc,
StringRef name, mlir::Type t,
bool isCst) {
bool isCst,
mlir::Operation *insertPoint) {
mlir::cir::GlobalOp g;
auto &builder = CGM.getBuilder();
{
Expand All @@ -486,8 +487,12 @@ mlir::cir::GlobalOp CIRGenModule::createGlobalOp(CIRGenModule &CGM,
builder.setInsertionPoint(curCGF->CurFn);

g = builder.create<mlir::cir::GlobalOp>(loc, name, t, isCst);
if (!curCGF)
CGM.getModule().push_back(g);
if (!curCGF) {
if (insertPoint)
CGM.getModule().insert(insertPoint, g);
else
CGM.getModule().push_back(g);
}

// Default to private until we can judge based on the initializer,
// since MLIR doesn't allow public declarations.
Expand All @@ -501,6 +506,31 @@ void CIRGenModule::setCommonAttributes(GlobalDecl GD, mlir::Operation *GV) {
assert(!UnimplementedFeature::setCommonAttributes());
}

void CIRGenModule::replaceGlobal(mlir::cir::GlobalOp Old,
mlir::cir::GlobalOp New) {
assert(Old.getSymName() == New.getSymName() && "symbol names must match");

// If the types does not match, update all references to Old to the new type.
auto OldTy = Old.getSymType();
auto NewTy = New.getSymType();
if (OldTy != NewTy) {
auto OldSymUses = Old.getSymbolUses(theModule.getOperation());
if (OldSymUses.has_value()) {
for (auto Use : *OldSymUses) {
auto UseOp = dyn_cast<mlir::cir::GetGlobalOp>(Use.getUser());
assert(UseOp && "GlobalOp symbol user is not a GetGlobalOp");
Lancern marked this conversation as resolved.
Show resolved Hide resolved

auto UseOpResultValue = UseOp.getAddr();
UseOpResultValue.setType(
mlir::cir::PointerType::get(builder.getContext(), NewTy));
}
bcardosolopes marked this conversation as resolved.
Show resolved Hide resolved
}
}

// Remove old global from the module.
Old.erase();
}

/// If the specified mangled name is not in the module,
/// create and return an mlir GlobalOp with the specified type (TODO(cir):
/// address space).
Expand Down Expand Up @@ -592,11 +622,14 @@ CIRGenModule::getOrCreateCIRGlobal(StringRef MangledName, mlir::Type Ty,
// mlir::SymbolTable::Visibility::Public is the default, no need to explicitly
// mark it as such.
auto GV = CIRGenModule::createGlobalOp(*this, loc, MangledName, Ty,
/*isConstant=*/false);
/*isConstant=*/false,
/*insertPoint=*/Entry.getOperation());

// If we already created a global with the same mangled name (but different
// type) before, take its name and remove it from its parent.
assert(!Entry && "not implemented");
// type) before, replace it with the new global.
if (Entry) {
replaceGlobal(Entry, GV);
}

// This is the first use or definition of a mangled name. If there is a
// deferred decl with this name, remember that we need to emit it at the end
Expand Down
11 changes: 10 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,8 @@ class CIRGenModule : public CIRGenTypeCache {

static mlir::cir::GlobalOp createGlobalOp(CIRGenModule &CGM,
mlir::Location loc, StringRef name,
mlir::Type t, bool isCst = false);
mlir::Type t, bool isCst = false,
mlir::Operation *insertPoint = nullptr);

/// 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
Expand Down Expand Up @@ -445,6 +446,14 @@ class CIRGenModule : public CIRGenTypeCache {
void setGVProperties(mlir::Operation *Op, const NamedDecl *D) const;
void setGVPropertiesAux(mlir::Operation *Op, const NamedDecl *D) const;

/// Replace the present global `Old` with the given global `New`. Their symbol
/// names must match; their types can be different. Usages of the old global
/// will be automatically updated if their types mismatch.
///
/// This function will erase the old global. This function will NOT insert the
/// new global into the module.
void replaceGlobal(mlir::cir::GlobalOp Old, mlir::cir::GlobalOp New);

/// Determine whether the definition must be emitted; if this returns \c
/// false, the definition can be emitted lazily if it's used.
bool MustBeEmitted(const clang::ValueDecl *D);
Expand Down
11 changes: 11 additions & 0 deletions clang/test/CIR/CodeGen/array-unknown-bound.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-cir %s -o - | FileCheck %s

extern int table[];
// CHECK: cir.global external @table = #cir.const_array<[#cir.int<1> : !s32i, #cir.int<2> : !s32i, #cir.int<3> : !s32i]> : !cir.array<!s32i x 3>

int test() { return table[1]; }
// CHECK: cir.func @_Z4testv() -> !s32i extra( {inline = #cir.inline<no>, optnone = #cir.optnone} ) {
// CHECK-NEXT: %0 = cir.alloca !s32i, cir.ptr <!s32i>, ["__retval"] {alignment = 4 : i64}
// CHECK-NEXT: %1 = cir.get_global @table : cir.ptr <!cir.array<!s32i x 3>>

int table[3] {1, 2, 3};
Lancern marked this conversation as resolved.
Show resolved Hide resolved