Skip to content

Commit d84b986

Browse files
cyndyishidamylai-mtk
authored andcommitted
[InstallAPI] Hookup Input files & basic ASTVisitor (llvm#82552)
This patch takes in json files as input to determine that header files to process, and in which order, to pass along for CC1 invocations. This patch also includes an ASTVisitor to collect simple global variables.
1 parent 5db1d25 commit d84b986

File tree

12 files changed

+472
-8
lines changed

12 files changed

+472
-8
lines changed

clang/include/clang/InstallAPI/Context.h

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
#ifndef LLVM_CLANG_INSTALLAPI_CONTEXT_H
1010
#define LLVM_CLANG_INSTALLAPI_CONTEXT_H
1111

12+
#include "clang/Basic/Diagnostic.h"
13+
#include "clang/Basic/FileManager.h"
14+
#include "clang/InstallAPI/HeaderFile.h"
1215
#include "llvm/TextAPI/InterfaceFile.h"
1316
#include "llvm/TextAPI/RecordVisitor.h"
1417
#include "llvm/TextAPI/RecordsSlice.h"
@@ -24,8 +27,23 @@ struct InstallAPIContext {
2427
/// Library attributes that are typically passed as linker inputs.
2528
llvm::MachO::RecordsSlice::BinaryAttrs BA;
2629

27-
/// Active target triple to parse.
28-
llvm::Triple TargetTriple{};
30+
/// All headers that represent a library.
31+
HeaderSeq InputHeaders;
32+
33+
/// Active language mode to parse in.
34+
Language LangMode = Language::ObjC;
35+
36+
/// Active header access type.
37+
HeaderType Type = HeaderType::Unknown;
38+
39+
/// Active TargetSlice for symbol record collection.
40+
std::shared_ptr<llvm::MachO::RecordsSlice> Slice;
41+
42+
/// FileManager for all I/O operations.
43+
FileManager *FM = nullptr;
44+
45+
/// DiagnosticsEngine for all error reporting.
46+
DiagnosticsEngine *Diags = nullptr;
2947

3048
/// File Path of output location.
3149
llvm::StringRef OutputLoc{};
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//===- InstallAPI/Frontend.h -----------------------------------*- 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+
/// Top level wrappers for InstallAPI frontend operations.
10+
///
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_CLANG_INSTALLAPI_FRONTEND_H
14+
#define LLVM_CLANG_INSTALLAPI_FRONTEND_H
15+
16+
#include "clang/AST/ASTConsumer.h"
17+
#include "clang/Frontend/CompilerInstance.h"
18+
#include "clang/Frontend/FrontendActions.h"
19+
#include "clang/InstallAPI/Context.h"
20+
#include "clang/InstallAPI/Visitor.h"
21+
#include "llvm/ADT/Twine.h"
22+
#include "llvm/Support/MemoryBuffer.h"
23+
24+
namespace clang {
25+
namespace installapi {
26+
27+
/// Create a buffer that contains all headers to scan
28+
/// for global symbols with.
29+
std::unique_ptr<llvm::MemoryBuffer>
30+
createInputBuffer(const InstallAPIContext &Ctx);
31+
32+
class InstallAPIAction : public ASTFrontendAction {
33+
public:
34+
explicit InstallAPIAction(llvm::MachO::RecordsSlice &Records)
35+
: Records(Records) {}
36+
37+
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
38+
StringRef InFile) override {
39+
return std::make_unique<InstallAPIVisitor>(CI.getASTContext(), Records);
40+
}
41+
42+
private:
43+
llvm::MachO::RecordsSlice &Records;
44+
};
45+
} // namespace installapi
46+
} // namespace clang
47+
48+
#endif // LLVM_CLANG_INSTALLAPI_FRONTEND_H

clang/include/clang/InstallAPI/HeaderFile.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "clang/Basic/LangStandard.h"
1717
#include "llvm/ADT/StringRef.h"
18+
#include "llvm/Support/ErrorHandling.h"
1819
#include "llvm/Support/Regex.h"
1920
#include <optional>
2021
#include <string>
@@ -32,6 +33,20 @@ enum class HeaderType {
3233
Project,
3334
};
3435

36+
inline StringRef getName(const HeaderType T) {
37+
switch (T) {
38+
case HeaderType::Public:
39+
return "Public";
40+
case HeaderType::Private:
41+
return "Private";
42+
case HeaderType::Project:
43+
return "Project";
44+
case HeaderType::Unknown:
45+
return "Unknown";
46+
}
47+
llvm_unreachable("unexpected header type");
48+
}
49+
3550
class HeaderFile {
3651
/// Full input path to header.
3752
std::string FullPath;
@@ -52,6 +67,14 @@ class HeaderFile {
5267

5368
static llvm::Regex getFrameworkIncludeRule();
5469

70+
HeaderType getType() const { return Type; }
71+
StringRef getIncludeName() const { return IncludeName; }
72+
StringRef getPath() const { return FullPath; }
73+
74+
bool useIncludeName() const {
75+
return Type != HeaderType::Project && !IncludeName.empty();
76+
}
77+
5578
bool operator==(const HeaderFile &Other) const {
5679
return std::tie(Type, FullPath, IncludeName, Language) ==
5780
std::tie(Other.Type, Other.FullPath, Other.IncludeName,
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//===- InstallAPI/Visitor.h -----------------------------------*- 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+
/// ASTVisitor Interface for InstallAPI frontend operations.
10+
///
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_CLANG_INSTALLAPI_VISITOR_H
14+
#define LLVM_CLANG_INSTALLAPI_VISITOR_H
15+
16+
#include "clang/AST/Mangle.h"
17+
#include "clang/AST/RecursiveASTVisitor.h"
18+
#include "clang/Basic/TargetInfo.h"
19+
#include "clang/Frontend/FrontendActions.h"
20+
#include "llvm/ADT/Twine.h"
21+
#include "llvm/TextAPI/RecordsSlice.h"
22+
23+
namespace clang {
24+
namespace installapi {
25+
26+
/// ASTVisitor for collecting declarations that represent global symbols.
27+
class InstallAPIVisitor final : public ASTConsumer,
28+
public RecursiveASTVisitor<InstallAPIVisitor> {
29+
public:
30+
InstallAPIVisitor(ASTContext &ASTCtx, llvm::MachO::RecordsSlice &Slice)
31+
: Slice(Slice),
32+
MC(ItaniumMangleContext::create(ASTCtx, ASTCtx.getDiagnostics())),
33+
Layout(ASTCtx.getTargetInfo().getDataLayoutString()) {}
34+
void HandleTranslationUnit(ASTContext &ASTCtx) override;
35+
36+
/// Collect global variables.
37+
bool VisitVarDecl(const VarDecl *D);
38+
39+
private:
40+
std::string getMangledName(const NamedDecl *D) const;
41+
std::string getBackendMangledName(llvm::Twine Name) const;
42+
43+
llvm::MachO::RecordsSlice &Slice;
44+
std::unique_ptr<clang::ItaniumMangleContext> MC;
45+
StringRef Layout;
46+
};
47+
48+
} // namespace installapi
49+
} // namespace clang
50+
51+
#endif // LLVM_CLANG_INSTALLAPI_VISITOR_H

clang/lib/InstallAPI/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
set(LLVM_LINK_COMPONENTS
22
Support
33
TextAPI
4+
Core
45
)
56

67
add_clang_library(clangInstallAPI
78
FileList.cpp
9+
Frontend.cpp
810
HeaderFile.cpp
11+
Visitor.cpp
912

1013
LINK_LIBS
1114
clangAST

clang/lib/InstallAPI/Frontend.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//===- Frontend.cpp ---------------------------------------------*- 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+
#include "clang/InstallAPI/Frontend.h"
10+
#include "clang/AST/Availability.h"
11+
#include "llvm/ADT/SmallString.h"
12+
#include "llvm/ADT/StringRef.h"
13+
14+
using namespace llvm;
15+
using namespace llvm::MachO;
16+
17+
namespace clang::installapi {
18+
19+
static StringRef getFileExtension(clang::Language Lang) {
20+
switch (Lang) {
21+
default:
22+
llvm_unreachable("Unexpected language option.");
23+
case clang::Language::C:
24+
return ".c";
25+
case clang::Language::CXX:
26+
return ".cpp";
27+
case clang::Language::ObjC:
28+
return ".m";
29+
case clang::Language::ObjCXX:
30+
return ".mm";
31+
}
32+
}
33+
34+
std::unique_ptr<MemoryBuffer> createInputBuffer(const InstallAPIContext &Ctx) {
35+
assert(Ctx.Type != HeaderType::Unknown &&
36+
"unexpected access level for parsing");
37+
SmallString<4096> Contents;
38+
raw_svector_ostream OS(Contents);
39+
for (const HeaderFile &H : Ctx.InputHeaders) {
40+
if (H.getType() != Ctx.Type)
41+
continue;
42+
if (Ctx.LangMode == Language::C || Ctx.LangMode == Language::CXX)
43+
OS << "#include ";
44+
else
45+
OS << "#import ";
46+
if (H.useIncludeName())
47+
OS << "<" << H.getIncludeName() << ">";
48+
else
49+
OS << "\"" << H.getPath() << "\"";
50+
}
51+
if (Contents.empty())
52+
return nullptr;
53+
54+
return llvm::MemoryBuffer::getMemBufferCopy(
55+
Contents, "installapi-includes" + getFileExtension(Ctx.LangMode));
56+
}
57+
58+
} // namespace clang::installapi

clang/lib/InstallAPI/Visitor.cpp

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
//===- Visitor.cpp ---------------------------------------------*- 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+
#include "clang/InstallAPI/Visitor.h"
10+
#include "clang/AST/Availability.h"
11+
#include "clang/Basic/Linkage.h"
12+
#include "llvm/ADT/SmallString.h"
13+
#include "llvm/ADT/StringRef.h"
14+
#include "llvm/IR/DataLayout.h"
15+
#include "llvm/IR/Mangler.h"
16+
17+
using namespace llvm;
18+
using namespace llvm::MachO;
19+
20+
namespace clang::installapi {
21+
22+
// Exported NamedDecl needs to have externally visibiliy linkage and
23+
// default visibility from LinkageComputer.
24+
static bool isExported(const NamedDecl *D) {
25+
auto LV = D->getLinkageAndVisibility();
26+
return isExternallyVisible(LV.getLinkage()) &&
27+
(LV.getVisibility() == DefaultVisibility);
28+
}
29+
30+
static SymbolFlags getFlags(bool WeakDef, bool ThreadLocal) {
31+
SymbolFlags Result = SymbolFlags::None;
32+
if (WeakDef)
33+
Result |= SymbolFlags::WeakDefined;
34+
if (ThreadLocal)
35+
Result |= SymbolFlags::ThreadLocalValue;
36+
37+
return Result;
38+
}
39+
40+
void InstallAPIVisitor::HandleTranslationUnit(ASTContext &ASTCtx) {
41+
if (ASTCtx.getDiagnostics().hasErrorOccurred())
42+
return;
43+
44+
auto *D = ASTCtx.getTranslationUnitDecl();
45+
TraverseDecl(D);
46+
}
47+
48+
std::string InstallAPIVisitor::getMangledName(const NamedDecl *D) const {
49+
SmallString<256> Name;
50+
if (MC->shouldMangleDeclName(D)) {
51+
raw_svector_ostream NStream(Name);
52+
MC->mangleName(D, NStream);
53+
} else
54+
Name += D->getNameAsString();
55+
56+
return getBackendMangledName(Name);
57+
}
58+
59+
std::string InstallAPIVisitor::getBackendMangledName(Twine Name) const {
60+
SmallString<256> FinalName;
61+
Mangler::getNameWithPrefix(FinalName, Name, DataLayout(Layout));
62+
return std::string(FinalName);
63+
}
64+
65+
/// Collect all global variables.
66+
bool InstallAPIVisitor::VisitVarDecl(const VarDecl *D) {
67+
// Skip function parameters.
68+
if (isa<ParmVarDecl>(D))
69+
return true;
70+
71+
// Skip variables in records. They are handled seperately for C++.
72+
if (D->getDeclContext()->isRecord())
73+
return true;
74+
75+
// Skip anything inside functions or methods.
76+
if (!D->isDefinedOutsideFunctionOrMethod())
77+
return true;
78+
79+
// If this is a template but not specialization or instantiation, skip.
80+
if (D->getASTContext().getTemplateOrSpecializationInfo(D) &&
81+
D->getTemplateSpecializationKind() == TSK_Undeclared)
82+
return true;
83+
84+
// TODO: Capture SourceLocation & Availability for Decls.
85+
const RecordLinkage Linkage =
86+
isExported(D) ? RecordLinkage::Exported : RecordLinkage::Internal;
87+
const bool WeakDef = D->hasAttr<WeakAttr>();
88+
const bool ThreadLocal = D->getTLSKind() != VarDecl::TLS_None;
89+
Slice.addGlobal(getMangledName(D), Linkage, GlobalRecord::Kind::Variable,
90+
getFlags(WeakDef, ThreadLocal));
91+
return true;
92+
}
93+
94+
} // namespace clang::installapi

clang/test/InstallAPI/basic.test

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@
1616
// CHECK-NOT: warning:
1717

1818
//--- basic_inputs.json
19+
{
20+
"headers": [
21+
],
22+
"version": "3"
23+
}
1924

2025
//--- expected.tbd
2126
{

0 commit comments

Comments
 (0)