Skip to content

Commit

Permalink
[CIR][CIRGen] Add codegen for global compound literals (#454)
Browse files Browse the repository at this point in the history
This PR adds support for global compound literals.
The implementation is almost the same as in original codegen. But the
original codegen can reuse the value of emitted compound literal global
variable in case then the init expression of new variable and this
variable are the same.
It's easy to implement this feature. But I can't find any test-case then
this feature will be applied. So I decided to ignore this optimization
opportunity to avoid mistakes.
  • Loading branch information
YazZz1k authored and lanza committed Apr 29, 2024
1 parent a13ce63 commit 5b8c3dd
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 4 deletions.
7 changes: 7 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenCstEmitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,14 @@ class ConstantEmitter {
/// Is the current emission context abstract?
bool isAbstract() const { return Abstract; }

bool isInConstantContext() const { return InConstantContext; }
void setInConstantContext(bool var) { InConstantContext = var; }

/// Try to emit the initiaizer of the given declaration as an abstract
/// constant. If this succeeds, the emission must be finalized.
mlir::Attribute tryEmitForInitializer(const VarDecl &D);
mlir::Attribute tryEmitForInitializer(const Expr *E, LangAS destAddrSpace,
QualType destType);

void finalize(mlir::cir::GlobalOp global);

Expand Down Expand Up @@ -106,6 +111,8 @@ class ConstantEmitter {
mlir::Attribute emitAbstract(SourceLocation loc, const APValue &value,
QualType T);

mlir::Attribute tryEmitConstantExpr(const ConstantExpr *CE);

// These are private helper routines of the constant emitter that
// can't actually be private because things are split out into helper
// functions and classes.
Expand Down
56 changes: 52 additions & 4 deletions clang/lib/CIR/CodeGen/CIRGenExprConst.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -841,8 +841,9 @@ class ConstExprEmitter
mlir::Attribute VisitStmt(Stmt *S, QualType T) { return nullptr; }

mlir::Attribute VisitConstantExpr(ConstantExpr *CE, QualType T) {
assert(0 && "unimplemented");
return {};
if (mlir::Attribute Result = Emitter.tryEmitConstantExpr(CE))
return Result;
return Visit(CE->getSubExpr(), T);
}

mlir::Attribute VisitParenExpr(ParenExpr *PE, QualType T) {
Expand Down Expand Up @@ -1371,15 +1372,44 @@ ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {
return Visit(base.get<const Expr *>());
}

static ConstantLValue
tryEmitGlobalCompoundLiteral(ConstantEmitter &emitter,
const CompoundLiteralExpr *E) {
CIRGenModule &CGM = emitter.CGM;

LangAS addressSpace = E->getType().getAddressSpace();
mlir::Attribute C = emitter.tryEmitForInitializer(E->getInitializer(),
addressSpace, E->getType());
if (!C) {
assert(!E->isFileScope() &&
"file-scope compound literal did not have constant initializer!");
return nullptr;
}

auto GV = CIRGenModule::createGlobalOp(
CGM, CGM.getLoc(E->getSourceRange()),
CGM.createGlobalCompoundLiteralName(),
CGM.getTypes().convertTypeForMem(E->getType()),
E->getType().isConstantStorage(CGM.getASTContext(), false, false));
GV.setInitialValueAttr(C);
GV.setLinkage(mlir::cir::GlobalLinkageKind::InternalLinkage);
CharUnits Align = CGM.getASTContext().getTypeAlignInChars(E->getType());
GV.setAlignment(Align.getAsAlign().value());

emitter.finalize(GV);
return CGM.getBuilder().getGlobalViewAttr(GV);
}

ConstantLValue ConstantLValueEmitter::VisitConstantExpr(const ConstantExpr *E) {
assert(0 && "NYI");
return Visit(E->getSubExpr());
}

ConstantLValue
ConstantLValueEmitter::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
assert(0 && "NYI");
return nullptr;
ConstantEmitter CompoundLiteralEmitter(CGM, Emitter.CGF);
CompoundLiteralEmitter.setInConstantContext(Emitter.isInConstantContext());
return tryEmitGlobalCompoundLiteral(CompoundLiteralEmitter, E);
}

ConstantLValue
Expand Down Expand Up @@ -1460,6 +1490,13 @@ mlir::Attribute ConstantEmitter::tryEmitForInitializer(const VarDecl &D) {
return markIfFailed(tryEmitPrivateForVarInit(D));
}

mlir::Attribute ConstantEmitter::tryEmitForInitializer(const Expr *E,
LangAS destAddrSpace,
QualType destType) {
initializeNonAbstract(destAddrSpace);
return markIfFailed(tryEmitPrivateForMemory(E, destType));
}

void ConstantEmitter::finalize(mlir::cir::GlobalOp global) {
assert(InitializedNonAbstract &&
"finalizing emitter that was used for abstract emission?");
Expand Down Expand Up @@ -1552,6 +1589,17 @@ mlir::Attribute ConstantEmitter::tryEmitAbstract(const APValue &value,
return validateAndPopAbstract(C, state);
}

mlir::Attribute ConstantEmitter::tryEmitConstantExpr(const ConstantExpr *CE) {
if (!CE->hasAPValueResult())
return nullptr;

QualType RetType = CE->getType();
if (CE->isGLValue())
RetType = CGM.getASTContext().getLValueReferenceType(RetType);

return emitAbstract(CE->getBeginLoc(), CE->getAPValueResult(), RetType);
}

mlir::Attribute ConstantEmitter::tryEmitAbstractForMemory(const Expr *E,
QualType destType) {
auto nonMemoryDestType = getNonMemoryType(CGM, destType);
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,12 @@ class CIRGenModule : public CIRGenTypeCache {
StringRef Name = ".str");
unsigned StringLiteralCnt = 0;

unsigned CompoundLitaralCnt = 0;
/// Return the unique name for global compound literal
std::string createGlobalCompoundLiteralName() {
return (Twine(".compoundLiteral.") + Twine(CompoundLitaralCnt++)).str();
}

/// Return the AST address space of constant literal, which is used to emit
/// the constant literal as global variable in LLVM IR.
/// Note: This is not necessarily the address space of the constant literal
Expand Down
29 changes: 29 additions & 0 deletions clang/test/CIR/CodeGen/compound-literal.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -S -emit-llvm %s -o %t.ll
// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM


typedef struct {
int *arr;
} S;

S a = {
.arr = (int[]){}
};

// CIR: cir.global "private" internal @".compoundLiteral.0" = #cir.zero : !cir.array<!s32i x 0> {alignment = 4 : i64}
// CIR: cir.global external @a = #cir.const_struct<{#cir.global_view<@".compoundLiteral.0"> : !cir.ptr<!s32i>}> : !ty_22S22

// LLVM: @.compoundLiteral.0 = internal global [0 x i32] zeroinitializer
// LLVM: @a = global %struct.S { ptr @.compoundLiteral.0 }

S b = {
.arr = (int[]){1}
};

// CIR: cir.global "private" internal @".compoundLiteral.1" = #cir.const_array<[#cir.int<1> : !s32i]> : !cir.array<!s32i x 1> {alignment = 4 : i64}
// CIR: cir.global external @b = #cir.const_struct<{#cir.global_view<@".compoundLiteral.1"> : !cir.ptr<!s32i>}> : !ty_22S22

// LLVM: @.compoundLiteral.1 = internal global [1 x i32] [i32 1]
// LLVM: @b = global %struct.S { ptr @.compoundLiteral.1 }

0 comments on commit 5b8c3dd

Please sign in to comment.