From 34c256d7dae1ec40ef11cea54b465ba1a1b9c75e Mon Sep 17 00:00:00 2001 From: YazZz1k Date: Fri, 2 Feb 2024 13:54:39 +0300 Subject: [PATCH] [CIR][CIRGen] Add codegen for some comp-literal exprs --- clang/lib/CIR/CodeGen/CIRGenCstEmitter.h | 7 +++ clang/lib/CIR/CodeGen/CIRGenExprConst.cpp | 56 +++++++++++++++++++++-- clang/lib/CIR/CodeGen/CIRGenModule.h | 6 +++ clang/test/CIR/CodeGen/compound-literal.c | 29 ++++++++++++ 4 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 clang/test/CIR/CodeGen/compound-literal.c diff --git a/clang/lib/CIR/CodeGen/CIRGenCstEmitter.h b/clang/lib/CIR/CodeGen/CIRGenCstEmitter.h index 5c9e545f227f..086c68baec9c 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCstEmitter.h +++ b/clang/lib/CIR/CodeGen/CIRGenCstEmitter.h @@ -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); @@ -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. diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConst.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConst.cpp index bfd5f4bd50ce..1a9c4a1bd996 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprConst.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprConst.cpp @@ -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) { @@ -1190,6 +1191,34 @@ ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) { return Visit(base.get()); } +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()); @@ -1197,8 +1226,9 @@ ConstantLValue ConstantLValueEmitter::VisitConstantExpr(const ConstantExpr *E) { 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 @@ -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?"); @@ -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); diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h index b200b210b888..a598400dd80c 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.h +++ b/clang/lib/CIR/CodeGen/CIRGenModule.h @@ -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 diff --git a/clang/test/CIR/CodeGen/compound-literal.c b/clang/test/CIR/CodeGen/compound-literal.c new file mode 100644 index 000000000000..327774c74f9f --- /dev/null +++ b/clang/test/CIR/CodeGen/compound-literal.c @@ -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 {alignment = 4 : i64} +// CIR: cir.global external @a = #cir.const_struct<{#cir.global_view<@".compoundLiteral.0"> : !cir.ptr}> : !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 {alignment = 4 : i64} +// CIR: cir.global external @b = #cir.const_struct<{#cir.global_view<@".compoundLiteral.1"> : !cir.ptr}> : !ty_22S22 + +// LLVM: @.compoundLiteral.1 = internal global [1 x i32] [i32 1] +// LLVM: @b = global %struct.S { ptr @.compoundLiteral.1 }