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/CGExprAgg.cpp | |
| parent | af82e63c28f67bf61a9b2b0e64bc55be4acf520e (diff) | |
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/CGExprAgg.cpp')
| -rw-r--r-- | clang/lib/CodeGen/CGExprAgg.cpp | 40 |
1 files changed, 32 insertions, 8 deletions
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index c369163ffaa9..0c8755852192 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -506,6 +506,16 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType, uint64_t NumInitElements = Args.size(); uint64_t NumArrayElements = AType->getNumElements(); + for (const auto *Init : Args) { + if (const auto *Embed = dyn_cast<EmbedExpr>(Init->IgnoreParenImpCasts())) { + NumInitElements += Embed->getDataElementCount() - 1; + if (NumInitElements > NumArrayElements) { + NumInitElements = NumArrayElements; + break; + } + } + } + assert(NumInitElements <= NumArrayElements); QualType elementType = @@ -574,23 +584,37 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType, llvm::Value *one = llvm::ConstantInt::get(CGF.SizeTy, 1); - // Emit the explicit initializers. - for (uint64_t i = 0; i != NumInitElements; ++i) { + auto Emit = [&](Expr *Init, uint64_t ArrayIndex) { llvm::Value *element = begin; - if (i > 0) { - element = Builder.CreateInBoundsGEP(llvmElementType, begin, - llvm::ConstantInt::get(CGF.SizeTy, i), - "arrayinit.element"); + if (ArrayIndex > 0) { + element = Builder.CreateInBoundsGEP( + llvmElementType, begin, + llvm::ConstantInt::get(CGF.SizeTy, ArrayIndex), "arrayinit.element"); // Tell the cleanup that it needs to destroy up to this // element. TODO: some of these stores can be trivially // observed to be unnecessary. - if (endOfInit.isValid()) Builder.CreateStore(element, endOfInit); + if (endOfInit.isValid()) + Builder.CreateStore(element, endOfInit); } LValue elementLV = CGF.MakeAddrLValue( Address(element, llvmElementType, elementAlign), elementType); - EmitInitializationToLValue(Args[i], elementLV); + EmitInitializationToLValue(Init, elementLV); + return true; + }; + + unsigned ArrayIndex = 0; + // Emit the explicit initializers. + for (uint64_t i = 0; i != NumInitElements; ++i) { + if (ArrayIndex >= NumInitElements) + break; + if (auto *EmbedS = dyn_cast<EmbedExpr>(Args[i]->IgnoreParenImpCasts())) { + EmbedS->doForEachDataElement(Emit, ArrayIndex); + } else { + Emit(Args[i], ArrayIndex); + ArrayIndex++; + } } // Check whether there's a non-trivial array-fill expression. |
