Skip to content

Commit 8231b72

Browse files
ThePhDh-vetinari
authored andcommitted
✨ Speedy #embed implementation
1 parent a05117d commit 8231b72

37 files changed

+1238
-137
lines changed

clang/include/clang/AST/Expr.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4805,6 +4805,58 @@ class SourceLocExpr final : public Expr {
48054805
friend class ASTStmtReader;
48064806
};
48074807

4808+
/// Represents a function call to __builtin_pp_embed().
4809+
class PPEmbedExpr final : public Expr {
4810+
SourceLocation BuiltinLoc, RParenLoc;
4811+
DeclContext *ParentContext;
4812+
StringLiteral *Filename;
4813+
StringLiteral *BinaryData;
4814+
4815+
public:
4816+
enum Action {
4817+
NotFound,
4818+
FoundOne,
4819+
Expanded,
4820+
};
4821+
4822+
PPEmbedExpr(const ASTContext &Ctx, QualType ResultTy, StringLiteral* Filename, StringLiteral* BinaryData,
4823+
SourceLocation BLoc, SourceLocation RParenLoc,
4824+
DeclContext *Context);
4825+
4826+
/// Build an empty call expression.
4827+
explicit PPEmbedExpr(EmptyShell Empty)
4828+
: Expr(SourceLocExprClass, Empty) {}
4829+
4830+
/// If the PPEmbedExpr has been resolved return the subexpression
4831+
/// representing the resolved value. Otherwise return null.
4832+
const DeclContext *getParentContext() const { return ParentContext; }
4833+
DeclContext *getParentContext() { return ParentContext; }
4834+
4835+
SourceLocation getLocation() const { return BuiltinLoc; }
4836+
SourceLocation getBeginLoc() const { return BuiltinLoc; }
4837+
SourceLocation getEndLoc() const { return RParenLoc; }
4838+
4839+
StringLiteral *getFilenameStringLiteral() const { return Filename; }
4840+
StringLiteral *getDataStringLiteral() const { return BinaryData; }
4841+
4842+
size_t getDataElementCount(ASTContext &Context) const;
4843+
4844+
child_range children() {
4845+
return child_range(child_iterator(), child_iterator());
4846+
}
4847+
4848+
const_child_range children() const {
4849+
return const_child_range(child_iterator(), child_iterator());
4850+
}
4851+
4852+
static bool classof(const Stmt *T) {
4853+
return T->getStmtClass() == PPEmbedExprClass;
4854+
}
4855+
4856+
private:
4857+
friend class ASTStmtReader;
4858+
};
4859+
48084860
/// Describes an C or C++ initializer list.
48094861
///
48104862
/// InitListExpr describes an initializer list, which can be used to

clang/include/clang/AST/RecursiveASTVisitor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2809,6 +2809,7 @@ DEF_TRAVERSE_STMT(ShuffleVectorExpr, {})
28092809
DEF_TRAVERSE_STMT(ConvertVectorExpr, {})
28102810
DEF_TRAVERSE_STMT(StmtExpr, {})
28112811
DEF_TRAVERSE_STMT(SourceLocExpr, {})
2812+
DEF_TRAVERSE_STMT(PPEmbedExpr, {})
28122813

28132814
DEF_TRAVERSE_STMT(UnresolvedLookupExpr, {
28142815
TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));

clang/include/clang/Basic/DiagnosticCommonKinds.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ def err_expected_string_literal : Error<"expected string literal "
5959
"'external_source_symbol' attribute|"
6060
"as argument of '%1' attribute}0">;
6161

62+
def err_builtin_pp_embed_invalid_argument : Error<
63+
"invalid argument to '__builtin_pp_embed': %0">;
64+
6265
def err_invalid_string_udl : Error<
6366
"string literal with user-defined suffix cannot be used here">;
6467
def err_invalid_character_udl : Error<
@@ -80,6 +83,9 @@ def err_expected : Error<"expected %0">;
8083
def err_expected_either : Error<"expected %0 or %1">;
8184
def err_expected_after : Error<"expected %1 after %0">;
8285

86+
def err_builtin_pp_embed_invalid_location : Error<
87+
"'__builtin_pp_embed' in invalid location: %0%select{|%2}1">;
88+
8389
def err_param_redefinition : Error<"redefinition of parameter %0">;
8490
def warn_method_param_redefinition : Warning<"redefinition of method parameter %0">;
8591
def warn_method_param_declaration : Warning<"redeclaration of method parameter %0">,

clang/include/clang/Basic/StmtNodes.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ def OpaqueValueExpr : StmtNode<Expr>;
203203
def TypoExpr : StmtNode<Expr>;
204204
def RecoveryExpr : StmtNode<Expr>;
205205
def BuiltinBitCastExpr : StmtNode<ExplicitCastExpr>;
206+
def PPEmbedExpr : StmtNode<Expr>;
206207

207208
// Microsoft Extensions.
208209
def MSPropertyRefExpr : StmtNode<Expr>;

clang/include/clang/Basic/TokenKinds.def

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,6 @@ TOK(eod) // End of preprocessing directive (end of line inside a
154154
// directive).
155155
TOK(code_completion) // Code completion marker
156156

157-
// #embed speed support
158-
TOK(builtin_embed)
159-
160-
161157
// C99 6.4.9: Comments.
162158
TOK(comment) // Comment (only in -E -C[C] mode)
163159

@@ -758,6 +754,7 @@ ALIAS("__char32_t" , char32_t , KEYCXX)
758754
KEYWORD(__builtin_bit_cast , KEYALL)
759755
KEYWORD(__builtin_available , KEYALL)
760756
KEYWORD(__builtin_sycl_unique_stable_name, KEYSYCL)
757+
KEYWORD(__builtin_pp_embed , KEYALL)
761758

762759
// Keywords defined by Attr.td.
763760
#ifndef KEYWORD_ATTRIBUTE
@@ -993,6 +990,7 @@ ANNOTATION(repl_input_end)
993990
#undef CXX11_KEYWORD
994991
#undef KEYWORD
995992
#undef PUNCTUATOR
993+
#undef BUILTINOK
996994
#undef TOK
997995
#undef C99_KEYWORD
998996
#undef C23_KEYWORD
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//===--- MacroArgs.h - Formal argument info for Macros ----------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file defines the MacroArgs interface.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_CLANG_LEX_PPDIRECTIVEPARAMETER_H
14+
#define LLVM_CLANG_LEX_PPDIRECTIVEPARAMETER_H
15+
16+
#include "clang/Basic/SourceLocation.h"
17+
18+
namespace clang {
19+
20+
/// Captures basic information about a preprocessor directive parameter.
21+
class PPDirectiveParameter {
22+
public:
23+
SourceLocation Start;
24+
SourceLocation End;
25+
26+
PPDirectiveParameter(SourceLocation Start, SourceLocation End)
27+
: Start(Start), End(End) {}
28+
};
29+
30+
} // end namespace clang
31+
32+
#endif
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
//===--- MacroArgs.h - Formal argument info for Macros ----------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file defines the MacroArgs interface.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_CLANG_LEX_PPEMBEDPARAMETERS_H
14+
#define LLVM_CLANG_LEX_PPEMBEDPARAMETERS_H
15+
16+
#include "clang/Lex/Token.h"
17+
#include "clang/Lex/PPDirectiveParameter.h"
18+
#include "llvm/ADT/SmallVector.h"
19+
20+
namespace clang {
21+
22+
/// Preprocessor extension embed parameter "clang::offset"
23+
/// `clang::offset( constant-expression )`
24+
class PPEmbedParameterOffset : public PPDirectiveParameter {
25+
public:
26+
size_t Offset;
27+
28+
PPEmbedParameterOffset(size_t Offset, SourceLocation Start, SourceLocation End)
29+
: Offset(Offset), PPDirectiveParameter(Start, End) {}
30+
};
31+
32+
/// Preprocessor standard embed parameter "limit"
33+
/// `limit( constant-expression )`
34+
class PPEmbedParameterLimit : public PPDirectiveParameter {
35+
public:
36+
size_t Limit;
37+
38+
PPEmbedParameterLimit(size_t Limit, SourceLocation Start,
39+
SourceLocation End)
40+
: Limit(Limit), PPDirectiveParameter(Start, End) {}
41+
};
42+
43+
/// Preprocessor standard embed parameter "prefix"
44+
/// `prefix( balanced-token-seq )`
45+
class PPEmbedParameterPrefix : public PPDirectiveParameter {
46+
public:
47+
SmallVector<Token, 2> Tokens;
48+
49+
PPEmbedParameterPrefix(SmallVector<Token, 2> Tokens, SourceLocation Start,
50+
SourceLocation End)
51+
: Tokens(std::move(Tokens)), PPDirectiveParameter(Start, End) {}
52+
};
53+
54+
/// Preprocessor standard embed parameter "suffix"
55+
/// `suffix( balanced-token-seq )`
56+
class PPEmbedParameterSuffix : public PPDirectiveParameter {
57+
public:
58+
SmallVector<Token, 2> Tokens;
59+
60+
PPEmbedParameterSuffix(SmallVector<Token, 2> Tokens, SourceLocation Start,
61+
SourceLocation End)
62+
: Tokens(std::move(Tokens)), PPDirectiveParameter(Start, End) {}
63+
};
64+
65+
/// Preprocessor standard embed parameter "if_empty"
66+
/// `if_empty( balanced-token-seq )`
67+
class PPEmbedParameterIfEmpty : public PPDirectiveParameter {
68+
public:
69+
SmallVector<Token, 2> Tokens;
70+
71+
PPEmbedParameterIfEmpty(SmallVector<Token, 2> Tokens, SourceLocation Start,
72+
SourceLocation End)
73+
: Tokens(std::move(Tokens)), PPDirectiveParameter(Start, End) {}
74+
};
75+
76+
} // end namespace clang
77+
78+
#endif

clang/include/clang/Lex/Preprocessor.h

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "clang/Lex/ModuleLoader.h"
3030
#include "clang/Lex/ModuleMap.h"
3131
#include "clang/Lex/PPCallbacks.h"
32+
#include "clang/Lex/PPEmbedParameters.h"
3233
#include "clang/Lex/Token.h"
3334
#include "clang/Lex/TokenLexer.h"
3435
#include "llvm/ADT/APSInt.h"
@@ -1163,6 +1164,9 @@ class Preprocessor {
11631164

11641165
void updateOutOfDateIdentifier(IdentifierInfo &II) const;
11651166

1167+
/// Buffers for used #embed directives
1168+
std::vector<std::string> EmbedBuffers;
1169+
11661170
public:
11671171
Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts,
11681172
DiagnosticsEngine &diags, const LangOptions &LangOpts,
@@ -1730,15 +1734,15 @@ class Preprocessor {
17301734
bool LexHeaderName(Token &Result, bool AllowMacroExpansion = true);
17311735

17321736
struct LexEmbedParametersResult {
1733-
bool Successful;
1734-
std::optional<size_t> MaybeLimitParam;
1735-
std::optional<size_t> MaybeOffsetParam;
1736-
std::optional<SmallVector<Token, 2>> MaybeIfEmptyParam;
1737-
std::optional<SmallVector<Token, 2>> MaybePrefixParam;
1738-
std::optional<SmallVector<Token, 2>> MaybeSuffixParam;
1739-
int UnrecognizedParams;
1737+
std::optional<PPEmbedParameterLimit> MaybeLimitParam;
1738+
std::optional<PPEmbedParameterOffset> MaybeOffsetParam;
1739+
std::optional<PPEmbedParameterIfEmpty> MaybeIfEmptyParam;
1740+
std::optional<PPEmbedParameterPrefix> MaybePrefixParam;
1741+
std::optional<PPEmbedParameterSuffix> MaybeSuffixParam;
17401742
SourceLocation StartLoc;
17411743
SourceLocation EndLoc;
1744+
int UnrecognizedParams;
1745+
bool Successful;
17421746
};
17431747

17441748
LexEmbedParametersResult LexEmbedParameters(Token &Current,
@@ -1807,7 +1811,7 @@ class Preprocessor {
18071811
/// Parses a simple integer literal to get its numeric value. Floating
18081812
/// point literals and user defined literals are rejected. Used primarily to
18091813
/// handle pragmas that accept integer arguments.
1810-
bool parseSimpleIntegerLiteral(Token &Tok, uint64_t &Value);
1814+
bool parseSimpleIntegerLiteral(Token &Tok, uint64_t &Value, bool WithLex = true);
18111815

18121816
/// Disables macro expansion everywhere except for preprocessor directives.
18131817
void SetMacroExpansionOnlyInDirectives() {
@@ -2724,12 +2728,18 @@ class Preprocessor {
27242728
// Binary data inclusion
27252729
void HandleEmbedDirective(SourceLocation HashLoc, Token &Tok,
27262730
const FileEntry *LookupFromFile = nullptr);
2727-
void HandleEmbedDirectiveNaive(
2728-
SourceLocation FilenameTok, LexEmbedParametersResult &Params,
2729-
StringRef BinaryContents, const size_t TargetCharWidth);
2730-
void HandleEmbedDirectiveBuiltin(
2731-
SourceLocation FilenameTok, LexEmbedParametersResult &Params,
2732-
StringRef BinaryContents, const size_t TargetCharWidth);
2731+
void HandleEmbedDirectiveNaive(SourceLocation HashLoc,
2732+
SourceLocation FilenameTok,
2733+
LexEmbedParametersResult &Params,
2734+
StringRef BinaryContents,
2735+
const size_t TargetCharWidth);
2736+
void HandleEmbedDirectiveBuiltin(SourceLocation HashLoc,
2737+
const Token &FilenameTok,
2738+
StringRef ResolvedFilename,
2739+
StringRef SearchPath, StringRef RelativePath,
2740+
LexEmbedParametersResult &Params,
2741+
StringRef BinaryContents,
2742+
const size_t TargetCharWidth);
27332743

27342744
// File inclusion.
27352745
void HandleIncludeDirective(SourceLocation HashLoc, Token &Tok,

clang/include/clang/Sema/Sema.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5983,6 +5983,10 @@ class Sema final {
59835983
ArrayRef<Expr *> Arg, SourceLocation RParenLoc,
59845984
Expr *Config = nullptr, bool IsExecConfig = false,
59855985
ADLCallKind UsesADL = ADLCallKind::NotADL);
5986+
/// `Fn` may be a null pointer.
5987+
void ModifyCallExprArguments(Expr *Fn, SourceLocation LParenLoc,
5988+
SmallVectorImpl<Expr *> &ArgExprs,
5989+
SourceLocation RParenLoc);
59865990

59875991
ExprResult ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,
59885992
MultiExprArg ExecConfig,
@@ -6100,6 +6104,34 @@ class Sema final {
61006104
SourceLocation BuiltinLoc,
61016105
SourceLocation RPLoc);
61026106

6107+
// __builtin_pp_embed()
6108+
ExprResult ActOnPPEmbedExpr(SourceLocation BuiltinLoc,
6109+
SourceLocation Base64DataLocation,
6110+
SourceLocation RPLoc, StringLiteral *Filename,
6111+
QualType DataTy, std::vector<char> BinaryData);
6112+
6113+
IntegerLiteral *ExpandSinglePPEmbedExpr(PPEmbedExpr *PPEmbed);
6114+
6115+
PPEmbedExpr::Action
6116+
CheckExprListForPPEmbedExpr(ArrayRef<Expr *> ExprList,
6117+
std::optional<QualType> MaybeInitType);
6118+
PPEmbedExpr::Action
6119+
ExpandPPEmbedExprInExprList(ArrayRef<Expr *> ExprList,
6120+
SmallVectorImpl<Expr *> &OutputExprList,
6121+
bool ClearOutputFirst = true);
6122+
PPEmbedExpr::Action
6123+
ExpandPPEmbedExprInExprList(SmallVectorImpl<Expr *> &OutputList);
6124+
6125+
enum PPEmbedExprContext {
6126+
PPEEC__StaticAssert,
6127+
PPEEC_StaticAssert,
6128+
};
6129+
6130+
StringRef GetLocationName(PPEmbedExprContext Context) const;
6131+
6132+
bool DiagnosePPEmbedExpr(Expr *&E, SourceLocation ContextLocation,
6133+
PPEmbedExprContext Context, bool SingleAllowed = true);
6134+
61036135
// Build a potentially resolved SourceLocExpr.
61046136
ExprResult BuildSourceLocExpr(SourceLocExpr::IdentKind Kind,
61056137
QualType ResultTy, SourceLocation BuiltinLoc,
@@ -8292,6 +8324,10 @@ class Sema final {
82928324
SourceLocation EqualLoc,
82938325
ParsedTemplateArgument DefaultArg);
82948326

8327+
void ModifyTemplateArguments(
8328+
const TemplateTy &Template,
8329+
SmallVectorImpl<ParsedTemplateArgument> &TemplateArgs);
8330+
82958331
TemplateParameterList *
82968332
ActOnTemplateParameterList(unsigned Depth,
82978333
SourceLocation ExportLoc,

clang/include/clang/Serialization/ASTBitCodes.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1715,6 +1715,9 @@ enum StmtCode {
17151715
/// A SourceLocExpr record.
17161716
EXPR_SOURCE_LOC,
17171717

1718+
/// A PPEmbedExpr record.
1719+
EXPR_BUILTIN_PP_EMBED,
1720+
17181721
/// A ShuffleVectorExpr record.
17191722
EXPR_SHUFFLE_VECTOR,
17201723

0 commit comments

Comments
 (0)