Skip to content

Commit 741f70a

Browse files
authored
Improve command handle (#149)
1 parent c664427 commit 741f70a

File tree

17 files changed

+680
-248
lines changed

17 files changed

+680
-248
lines changed

CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ if(NOT WIN32)
9393
target_link_libraries(clice-core PUBLIC
9494
LLVMSupport
9595
LLVMFrontendOpenMP
96+
LLVMOption
9697
clangAST
9798
clangASTMatchers
9899
clangBasic
@@ -135,7 +136,7 @@ if(CLICE_ENABLE_TEST)
135136
)
136137
FetchContent_MakeAvailable(googletest)
137138

138-
target_link_libraries(unit_tests PRIVATE gtest_main clice-core)
139+
target_link_libraries(unit_tests PRIVATE gtest_main clice-core)
139140

140141
# integration_tests
141142
add_executable(integration_tests "${CMAKE_SOURCE_DIR}/src/Driver/integration_tests.cc")

include/Compiler/Command.h

Lines changed: 103 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4,67 +4,128 @@
44
#include "llvm/ADT/DenseSet.h"
55
#include "llvm/ADT/StringMap.h"
66
#include "llvm/Support/Allocator.h"
7+
#include "llvm/ADT/ArrayRef.h"
8+
#include <deque>
79

810
namespace clice {
911

10-
/// `CompilationDatabase` is responsible for managing the compile commands.
11-
///
12-
/// FIXME: currently we assume that a file only occurs once in the CDB.
13-
/// This is not always correct, but it is enough for now.
1412
class CompilationDatabase {
1513
public:
1614
using Self = CompilationDatabase;
1715

18-
/// Update the compile commands with the given file.
19-
void update_commands(this Self& self, llvm::StringRef file);
16+
enum class UpdateKind : std::uint8_t {
17+
Unchange,
18+
Create,
19+
Update,
20+
Delete,
21+
};
22+
23+
struct CommandInfo {
24+
/// TODO: add sysroot or no stdinc command info.
25+
llvm::StringRef dictionary;
2026

21-
/// Update the module map with the given file and module name.
22-
void update_module(llvm::StringRef file, llvm::StringRef name);
27+
/// The canonical command list.
28+
llvm::ArrayRef<const char*> arguments;
29+
};
2330

24-
/// Lookup the module interface unit file path of the given module name.
25-
llvm::StringRef get_module_file(llvm::StringRef name);
31+
struct DriverInfo {
32+
/// The target of this driver.
33+
llvm::StringRef target;
2634

27-
auto size() const {
28-
return commands.size();
29-
}
35+
/// The default system includes of this driver.
36+
llvm::ArrayRef<const char*> system_includes;
37+
};
38+
39+
struct UpdateInfo {
40+
/// The kind of update.
41+
UpdateKind kind;
3042

31-
enum class Style {
32-
GNU = 0,
33-
MSVC,
43+
llvm::StringRef file;
3444
};
3545

36-
void add_command(this Self& self,
37-
llvm::StringRef path,
38-
llvm::StringRef command,
39-
Style style = Style::GNU);
46+
struct LookupInfo {
47+
llvm::StringRef dictionary;
4048

41-
llvm::ArrayRef<const char*> get_command(this Self& self, llvm::StringRef path);
49+
std::vector<const char*> arguments;
50+
};
4251

43-
private:
44-
/// Save a string into memory pool. Make sure end with `\0`.
45-
llvm::StringRef save_string(this Self& self, llvm::StringRef string);
52+
CompilationDatabase();
4653

47-
std::vector<const char*> save_args(this Self& self, llvm::ArrayRef<const char*> args);
54+
auto save_string(this Self& self, llvm::StringRef string) -> llvm::StringRef;
55+
56+
auto save_cstring_list(this Self& self, llvm::ArrayRef<const char*> arguments)
57+
-> llvm::ArrayRef<const char*>;
58+
59+
/// Get an the option for specific argument.
60+
static std::optional<std::uint32_t> get_option_id(llvm::StringRef argument);
61+
62+
/// Query the compiler driver and return its driver info.
63+
auto query_driver(this Self& self, llvm::StringRef driver)
64+
-> std::expected<DriverInfo, std::string>;
65+
66+
/// Update with arguments.
67+
auto update_command(this Self& self,
68+
llvm::StringRef dictionary,
69+
llvm::StringRef file,
70+
llvm::ArrayRef<const char*> arguments) -> UpdateInfo;
71+
72+
/// Update with full command.
73+
auto update_command(this Self& self,
74+
llvm::StringRef dictionary,
75+
llvm::StringRef file,
76+
llvm::StringRef command) -> UpdateInfo;
77+
78+
/// Update commands from json file and return all updated file.
79+
auto load_commands(this Self& self, llvm::StringRef json_content)
80+
-> std::expected<std::vector<UpdateInfo>, std::string>;
81+
82+
auto get_command(this Self& self, llvm::StringRef file, bool resource_dir = false) -> LookupInfo;
4883

4984
private:
50-
/// For C++20 module, we only can got dependent module name
51-
/// in source context. But we need dependent module file path
52-
/// to build PCM. So we will scan(preprocess) all project files
53-
/// to build a module map between module name and module file path.
54-
/// **Note that** this only includes module interface unit, for module
55-
/// implementation unit, the scan could be delayed until compiling it.
56-
llvm::StringMap<std::string> moduleMap;
57-
58-
/// Memory pool for command arguments.
59-
llvm::BumpPtrAllocator memory_pool;
60-
61-
/// For lookup whether we already have the key.
62-
llvm::DenseSet<llvm::StringRef> unique;
63-
64-
// A map between file path and compile commands.
65-
/// TODO: Path cannot represent unique file, we should use better, like inode ...
66-
llvm::DenseMap<const char*, std::unique_ptr<std::vector<const char*>>> commands;
85+
/// The memory pool to hold all cstring and command list.
86+
llvm::BumpPtrAllocator allocator;
87+
88+
/// A cache between input string and its cache cstring
89+
/// in the allocator, make sure end with `\0`.
90+
llvm::DenseSet<llvm::StringRef> string_cache;
91+
92+
/// A cache between input command and its cache array
93+
/// in the allocator.
94+
llvm::DenseSet<llvm::ArrayRef<const char*>> arguments_cache;
95+
96+
/// The clang options we want to filter in all cases, like -c and -o.
97+
llvm::DenseSet<std::uint32_t> filtered_options;
98+
99+
/// A map between file path and its canonical command list.
100+
llvm::DenseMap<const void*, CommandInfo> command_infos;
101+
102+
/// A map between driver path and its query driver info.
103+
llvm::DenseMap<const void*, DriverInfo> driver_infos;
67104
};
68105

69106
} // namespace clice
70107

108+
namespace llvm {
109+
110+
template <>
111+
struct DenseMapInfo<llvm::ArrayRef<const char*>> {
112+
using T = llvm::ArrayRef<const char*>;
113+
114+
inline static T getEmptyKey() {
115+
return T(reinterpret_cast<T::const_pointer>(~0), T::size_type(0));
116+
}
117+
118+
inline static T getTombstoneKey() {
119+
return T(reinterpret_cast<T::const_pointer>(~1), T::size_type(0));
120+
}
121+
122+
static unsigned getHashValue(const T& value) {
123+
return llvm::hash_combine_range(value.begin(), value.end());
124+
}
125+
126+
static bool isEqual(const T& lhs, const T& rhs) {
127+
return lhs == rhs;
128+
}
129+
};
130+
131+
} // namespace llvm

include/Compiler/Compilation.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@ struct CompilationParams {
1515
/// Output file path.
1616
llvm::SmallString<128> outPath;
1717

18+
std::string directory;
19+
1820
/// Responsible for storing the arguments.
19-
llvm::ArrayRef<const char*> arguments;
21+
std::vector<const char*> arguments;
2022

2123
llvm::IntrusiveRefCntPtr<vfs::FileSystem> vfs = new ThreadSafeFS();
2224

@@ -32,12 +34,11 @@ struct CompilationParams {
3234
/// The memory buffers for all remapped file.
3335
llvm::StringMap<std::unique_ptr<llvm::MemoryBuffer>> buffers;
3436

35-
3637
void add_remapped_file(llvm::StringRef path,
3738
llvm::StringRef content,
3839
std::uint32_t bound = -1) {
39-
if(bound != -1) {
40-
assert(bound < content.size());
40+
if(bound != 0 && bound != -1) {
41+
assert(bound <= content.size());
4142
content = content.substr(0, bound);
4243
}
4344
buffers.try_emplace(path, llvm::MemoryBuffer::getMemBufferCopy(content));

include/Test/CTest.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,9 @@ struct Tester {
8080

8181
Tester& compile(llvm::StringRef standard = "-std=c++20") {
8282
auto command = std::format("clang++ {} {} -fms-extensions", standard, src_path);
83-
database.add_command(src_path, command);
84-
params.arguments = database.get_command(src_path);
85-
83+
database.update_command("fake", src_path, command);
84+
params.arguments = database.get_command(src_path).arguments;
85+
8686
auto info = clice::compile(params);
8787
ASSERT_TRUE(info);
8888
this->unit.emplace(std::move(*info));

0 commit comments

Comments
 (0)