Skip to content

Commit ae0d224

Browse files
authored
[BPF] Fix linking issues in static map initializers (#91310)
When BPF object files are linked with bpftool, every symbol must be accompanied by BTF info. Ensure that extern functions referenced by global variable initializers are included in BTF. The primary motivation is "static" initialization of PROG maps: ```c extern int elsewhere(struct xdp_md *); struct { __uint(type, BPF_MAP_TYPE_PROG_ARRAY); __uint(max_entries, 1); __type(key, int); __type(value, int); __array(values, int (struct xdp_md *)); } prog_map SEC(".maps") = { .values = { elsewhere } }; ``` BPF backend needs debug info to produce BTF. Debug info is not normally generated for external variables and functions. Previously, it was solved differently for variables (collecting variable declarations in ExternalDeclarations vector) and functions (logic invoked during codegen in CGExpr.cpp). This patch generalises ExternalDefclarations to include both function and variable declarations. This change ensures that function references are not missed no matter the context. Previously external functions referenced in constant expressions lacked debug info.
1 parent 2bc474b commit ae0d224

File tree

17 files changed

+139
-26
lines changed

17 files changed

+139
-26
lines changed

clang/include/clang/AST/ASTConsumer.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ namespace clang {
2323
class ASTDeserializationListener; // layering violation because void* is ugly
2424
class SemaConsumer; // layering violation required for safe SemaConsumer
2525
class TagDecl;
26+
class DeclaratorDecl;
2627
class VarDecl;
2728
class FunctionDecl;
2829
class ImportDecl;
@@ -105,7 +106,7 @@ class ASTConsumer {
105106
/// CompleteExternalDeclaration - Callback invoked at the end of a translation
106107
/// unit to notify the consumer that the given external declaration should be
107108
/// completed.
108-
virtual void CompleteExternalDeclaration(VarDecl *D) {}
109+
virtual void CompleteExternalDeclaration(DeclaratorDecl *D) {}
109110

110111
/// Callback invoked when an MSInheritanceAttr has been attached to a
111112
/// CXXRecordDecl.

clang/include/clang/Frontend/MultiplexConsumer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class MultiplexConsumer : public SemaConsumer {
6767
void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override;
6868
void HandleImplicitImportDecl(ImportDecl *D) override;
6969
void CompleteTentativeDefinition(VarDecl *D) override;
70-
void CompleteExternalDeclaration(VarDecl *D) override;
70+
void CompleteExternalDeclaration(DeclaratorDecl *D) override;
7171
void AssignInheritanceModel(CXXRecordDecl *RD) override;
7272
void HandleVTable(CXXRecordDecl *RD) override;
7373
ASTMutationListener *GetASTMutationListener() override;

clang/include/clang/Sema/Sema.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3098,7 +3098,7 @@ class Sema final : public SemaBase {
30983098
TentativeDefinitionsType TentativeDefinitions;
30993099

31003100
/// All the external declarations encoutered and used in the TU.
3101-
SmallVector<VarDecl *, 4> ExternalDeclarations;
3101+
SmallVector<DeclaratorDecl *, 4> ExternalDeclarations;
31023102

31033103
/// Generally null except when we temporarily switch decl contexts,
31043104
/// like in \see SemaObjC::ActOnObjCTemporaryExitContainerContext.

clang/lib/CodeGen/BackendConsumer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ class BackendConsumer : public ASTConsumer {
107107
void HandleTagDeclDefinition(TagDecl *D) override;
108108
void HandleTagDeclRequiredDefinition(const TagDecl *D) override;
109109
void CompleteTentativeDefinition(VarDecl *D) override;
110-
void CompleteExternalDeclaration(VarDecl *D) override;
110+
void CompleteExternalDeclaration(DeclaratorDecl *D) override;
111111
void AssignInheritanceModel(CXXRecordDecl *RD) override;
112112
void HandleVTable(CXXRecordDecl *RD) override;
113113

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3141,21 +3141,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
31413141
return LV;
31423142
}
31433143

3144-
if (const auto *FD = dyn_cast<FunctionDecl>(ND)) {
3145-
LValue LV = EmitFunctionDeclLValue(*this, E, FD);
3146-
3147-
// Emit debuginfo for the function declaration if the target wants to.
3148-
if (getContext().getTargetInfo().allowDebugInfoForExternalRef()) {
3149-
if (CGDebugInfo *DI = CGM.getModuleDebugInfo()) {
3150-
auto *Fn =
3151-
cast<llvm::Function>(LV.getPointer(*this)->stripPointerCasts());
3152-
if (!Fn->getSubprogram())
3153-
DI->EmitFunctionDecl(FD, FD->getLocation(), T, Fn);
3154-
}
3155-
}
3156-
3157-
return LV;
3158-
}
3144+
if (const auto *FD = dyn_cast<FunctionDecl>(ND))
3145+
return EmitFunctionDeclLValue(*this, E, FD);
31593146

31603147
// FIXME: While we're emitting a binding from an enclosing scope, all other
31613148
// DeclRefExprs we see should be implicitly treated as if they also refer to

clang/lib/CodeGen/CodeGenAction.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ void BackendConsumer::CompleteTentativeDefinition(VarDecl *D) {
376376
Gen->CompleteTentativeDefinition(D);
377377
}
378378

379-
void BackendConsumer::CompleteExternalDeclaration(VarDecl *D) {
379+
void BackendConsumer::CompleteExternalDeclaration(DeclaratorDecl *D) {
380380
Gen->CompleteExternalDeclaration(D);
381381
}
382382

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5185,8 +5185,11 @@ void CodeGenModule::EmitTentativeDefinition(const VarDecl *D) {
51855185
EmitGlobalVarDefinition(D);
51865186
}
51875187

5188-
void CodeGenModule::EmitExternalDeclaration(const VarDecl *D) {
5189-
EmitExternalVarDeclaration(D);
5188+
void CodeGenModule::EmitExternalDeclaration(const DeclaratorDecl *D) {
5189+
if (auto const *V = dyn_cast<const VarDecl>(D))
5190+
EmitExternalVarDeclaration(V);
5191+
if (auto const *FD = dyn_cast<const FunctionDecl>(D))
5192+
EmitExternalFunctionDeclaration(FD);
51905193
}
51915194

51925195
CharUnits CodeGenModule::GetTargetTypeStoreSize(llvm::Type *Ty) const {
@@ -5622,6 +5625,18 @@ void CodeGenModule::EmitExternalVarDeclaration(const VarDecl *D) {
56225625
}
56235626
}
56245627

5628+
void CodeGenModule::EmitExternalFunctionDeclaration(const FunctionDecl *FD) {
5629+
if (CGDebugInfo *DI = getModuleDebugInfo())
5630+
if (getCodeGenOpts().hasReducedDebugInfo()) {
5631+
auto *Ty = getTypes().ConvertType(FD->getType());
5632+
StringRef MangledName = getMangledName(FD);
5633+
auto *Fn = dyn_cast<llvm::Function>(
5634+
GetOrCreateLLVMFunction(MangledName, Ty, FD, /* ForVTable */ false));
5635+
if (!Fn->getSubprogram())
5636+
DI->EmitFunctionDecl(FD, FD->getLocation(), FD->getType(), Fn);
5637+
}
5638+
}
5639+
56255640
static bool isVarDeclStrongDefinition(const ASTContext &Context,
56265641
CodeGenModule &CGM, const VarDecl *D,
56275642
bool NoCommon) {

clang/lib/CodeGen/CodeGenModule.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1338,7 +1338,7 @@ class CodeGenModule : public CodeGenTypeCache {
13381338

13391339
void EmitTentativeDefinition(const VarDecl *D);
13401340

1341-
void EmitExternalDeclaration(const VarDecl *D);
1341+
void EmitExternalDeclaration(const DeclaratorDecl *D);
13421342

13431343
void EmitVTable(CXXRecordDecl *Class);
13441344

@@ -1690,6 +1690,7 @@ class CodeGenModule : public CodeGenTypeCache {
16901690

16911691
void EmitGlobalVarDefinition(const VarDecl *D, bool IsTentative = false);
16921692
void EmitExternalVarDeclaration(const VarDecl *D);
1693+
void EmitExternalFunctionDeclaration(const FunctionDecl *D);
16931694
void EmitAliasDefinition(GlobalDecl GD);
16941695
void emitIFuncDefinition(GlobalDecl GD);
16951696
void emitCPUDispatchDefinition(GlobalDecl GD);

clang/lib/CodeGen/ModuleBuilder.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ namespace {
310310
Builder->EmitTentativeDefinition(D);
311311
}
312312

313-
void CompleteExternalDeclaration(VarDecl *D) override {
313+
void CompleteExternalDeclaration(DeclaratorDecl *D) override {
314314
Builder->EmitExternalDeclaration(D);
315315
}
316316

clang/lib/Frontend/MultiplexConsumer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ void MultiplexConsumer::CompleteTentativeDefinition(VarDecl *D) {
357357
Consumer->CompleteTentativeDefinition(D);
358358
}
359359

360-
void MultiplexConsumer::CompleteExternalDeclaration(VarDecl *D) {
360+
void MultiplexConsumer::CompleteExternalDeclaration(DeclaratorDecl *D) {
361361
for (auto &Consumer : Consumers)
362362
Consumer->CompleteExternalDeclaration(D);
363363
}

0 commit comments

Comments
 (0)