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][CIRGen] Add codegen for global compound literals #454

Merged
merged 1 commit into from
Feb 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
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 @@ -674,8 +674,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 @@ -1190,15 +1191,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 @@ -1279,6 +1309,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 @@ -1371,6 +1408,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-enable -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-enable -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 }
Loading