diff options
author | Mariya Podchishchaeva <mariya.podchishchaeva@intel.com> | 2024-06-20 14:38:46 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-20 14:38:46 +0200 |
commit | 41c6e4379204ffc00948edd33d59ba5ebbceaba2 (patch) | |
tree | b8508b8f0e7f108d1f6759922f49f367bd24fb00 /clang/lib/CodeGen/CGExprConstant.cpp | |
parent | af82e63c28f67bf61a9b2b0e64bc55be4acf520e (diff) | |
download | llvm-41c6e4379204ffc00948edd33d59ba5ebbceaba2.zip llvm-41c6e4379204ffc00948edd33d59ba5ebbceaba2.tar.gz llvm-41c6e4379204ffc00948edd33d59ba5ebbceaba2.tar.bz2 |
Reland [clang][Sema, Lex, Parse] Preprocessor embed in C and C++ (#95802)
This commit implements the entirety of the now-accepted [N3017
-Preprocessor
Embed](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3017.htm) and
its sister C++ paper [p1967](https://wg21.link/p1967). It implements
everything in the specification, and includes an implementation that
drastically improves the time it takes to embed data in specific
scenarios (the initialization of character type arrays). The mechanisms
used to do this are used under the "as-if" rule, and in general when the
system cannot detect it is initializing an array object in a variable
declaration, will generate EmbedExpr AST node which will be expanded by
AST consumers (CodeGen or constant expression evaluators) or expand
embed directive as a comma expression.
This reverts commit
https://github.com/llvm/llvm-project/commit/682d461d5a231cee54d65910e6341769419a67d7.
---------
Co-authored-by: The Phantom Derpstorm <phdofthehouse@gmail.com>
Co-authored-by: Aaron Ballman <aaron@aaronballman.com>
Co-authored-by: cor3ntin <corentinjabot@gmail.com>
Co-authored-by: H. Vetinari <h.vetinari@gmx.com>
Diffstat (limited to 'clang/lib/CodeGen/CGExprConstant.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGExprConstant.cpp | 118 |
1 files changed, 93 insertions, 25 deletions
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 0712f40..0fd3792 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -1061,6 +1061,24 @@ public: return Visit(E->getInitializer(), T); } + llvm::Constant *ProduceIntToIntCast(const Expr *E, QualType DestType) { + QualType FromType = E->getType(); + // See also HandleIntToIntCast in ExprConstant.cpp + if (FromType->isIntegerType()) + if (llvm::Constant *C = Visit(E, FromType)) + if (auto *CI = dyn_cast<llvm::ConstantInt>(C)) { + unsigned SrcWidth = CGM.getContext().getIntWidth(FromType); + unsigned DstWidth = CGM.getContext().getIntWidth(DestType); + if (DstWidth == SrcWidth) + return CI; + llvm::APInt A = FromType->isSignedIntegerType() + ? CI->getValue().sextOrTrunc(DstWidth) + : CI->getValue().zextOrTrunc(DstWidth); + return llvm::ConstantInt::get(CGM.getLLVMContext(), A); + } + return nullptr; + } + llvm::Constant *VisitCastExpr(const CastExpr *E, QualType destType) { if (const auto *ECE = dyn_cast<ExplicitCastExpr>(E)) CGM.EmitExplicitCastExprType(ECE, Emitter.CGF); @@ -1142,23 +1160,8 @@ public: case CK_IntToOCLSampler: llvm_unreachable("global sampler variables are not generated"); - case CK_IntegralCast: { - QualType FromType = subExpr->getType(); - // See also HandleIntToIntCast in ExprConstant.cpp - if (FromType->isIntegerType()) - if (llvm::Constant *C = Visit(subExpr, FromType)) - if (auto *CI = dyn_cast<llvm::ConstantInt>(C)) { - unsigned SrcWidth = CGM.getContext().getIntWidth(FromType); - unsigned DstWidth = CGM.getContext().getIntWidth(destType); - if (DstWidth == SrcWidth) - return CI; - llvm::APInt A = FromType->isSignedIntegerType() - ? CI->getValue().sextOrTrunc(DstWidth) - : CI->getValue().zextOrTrunc(DstWidth); - return llvm::ConstantInt::get(CGM.getLLVMContext(), A); - } - return nullptr; - } + case CK_IntegralCast: + return ProduceIntToIntCast(subExpr, destType); case CK_Dependent: llvm_unreachable("saw dependent cast!"); @@ -1249,15 +1252,42 @@ public: return llvm::ConstantInt::get(CGM.getLLVMContext(), I->getValue()); } + static APValue withDestType(ASTContext &Ctx, const Expr *E, QualType SrcType, + QualType DestType, const llvm::APSInt &Value) { + if (!Ctx.hasSameType(SrcType, DestType)) { + if (DestType->isFloatingType()) { + llvm::APFloat Result = + llvm::APFloat(Ctx.getFloatTypeSemantics(DestType), 1); + llvm::RoundingMode RM = + E->getFPFeaturesInEffect(Ctx.getLangOpts()).getRoundingMode(); + if (RM == llvm::RoundingMode::Dynamic) + RM = llvm::RoundingMode::NearestTiesToEven; + Result.convertFromAPInt(Value, Value.isSigned(), RM); + return APValue(Result); + } + } + return APValue(Value); + } + llvm::Constant *EmitArrayInitialization(const InitListExpr *ILE, QualType T) { auto *CAT = CGM.getContext().getAsConstantArrayType(ILE->getType()); assert(CAT && "can't emit array init for non-constant-bound array"); + uint64_t NumInitElements = ILE->getNumInits(); const uint64_t NumElements = CAT->getZExtSize(); + for (const auto *Init : ILE->inits()) { + if (const auto *Embed = + dyn_cast<EmbedExpr>(Init->IgnoreParenImpCasts())) { + NumInitElements += Embed->getDataElementCount() - 1; + if (NumInitElements > NumElements) { + NumInitElements = NumElements; + break; + } + } + } // Initialising an array requires us to automatically // initialise any elements that have not been initialised explicitly - uint64_t NumInitableElts = - std::min<uint64_t>(ILE->getNumInits(), NumElements); + uint64_t NumInitableElts = std::min<uint64_t>(NumInitElements, NumElements); QualType EltType = CAT->getElementType(); @@ -1270,23 +1300,61 @@ public: } // Copy initializer elements. - SmallVector<llvm::Constant*, 16> Elts; + SmallVector<llvm::Constant *, 16> Elts; if (fillC && fillC->isNullValue()) Elts.reserve(NumInitableElts + 1); else Elts.reserve(NumElements); llvm::Type *CommonElementType = nullptr; - for (unsigned i = 0; i < NumInitableElts; ++i) { - const Expr *Init = ILE->getInit(i); - llvm::Constant *C = Emitter.tryEmitPrivateForMemory(Init, EltType); + auto Emit = [&](const Expr *Init, unsigned ArrayIndex) { + llvm::Constant *C = nullptr; + C = Emitter.tryEmitPrivateForMemory(Init, EltType); if (!C) - return nullptr; - if (i == 0) + return false; + if (ArrayIndex == 0) CommonElementType = C->getType(); else if (C->getType() != CommonElementType) CommonElementType = nullptr; Elts.push_back(C); + return true; + }; + + unsigned ArrayIndex = 0; + QualType DestTy = CAT->getElementType(); + for (unsigned i = 0; i < ILE->getNumInits(); ++i) { + const Expr *Init = ILE->getInit(i); + if (auto *EmbedS = dyn_cast<EmbedExpr>(Init->IgnoreParenImpCasts())) { + StringLiteral *SL = EmbedS->getDataStringLiteral(); + llvm::APSInt Value(CGM.getContext().getTypeSize(DestTy), + DestTy->isUnsignedIntegerType()); + llvm::Constant *C; + for (unsigned I = EmbedS->getStartingElementPos(), + N = EmbedS->getDataElementCount(); + I != EmbedS->getStartingElementPos() + N; ++I) { + Value = SL->getCodeUnit(I); + if (DestTy->isIntegerType()) { + C = llvm::ConstantInt::get(CGM.getLLVMContext(), Value); + } else { + C = Emitter.tryEmitPrivateForMemory( + withDestType(CGM.getContext(), Init, EmbedS->getType(), DestTy, + Value), + EltType); + } + if (!C) + return nullptr; + Elts.push_back(C); + ArrayIndex++; + } + if ((ArrayIndex - EmbedS->getDataElementCount()) == 0) + CommonElementType = C->getType(); + else if (C->getType() != CommonElementType) + CommonElementType = nullptr; + } else { + if (!Emit(Init, ArrayIndex)) + return nullptr; + ArrayIndex++; + } } llvm::ArrayType *Desired = |