Skip to content

Commit 15b2a9b

Browse files
committed
add CLANG_AS_SWAP env var to swap clang as input
Change-Id: I8fb28509ab5f17dc451464c8bdb34cfb5240fc39
1 parent 5e8249e commit 15b2a9b

File tree

1 file changed

+115
-12
lines changed

1 file changed

+115
-12
lines changed

clang/tools/driver/cc1as_main.cpp

Lines changed: 115 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,109 @@
5757
#include <memory>
5858
#include <optional>
5959
#include <system_error>
60+
61+
// Add these includes at the top
62+
#include "llvm/Support/MD5.h"
63+
#include <cstdlib>
64+
#include <map>
65+
6066
using namespace clang;
6167
using namespace clang::driver;
6268
using namespace clang::driver::options;
6369
using namespace llvm;
6470
using namespace llvm::opt;
6571

72+
// Helper function to parse CLANG_AS_SWAP environment variable
73+
static std::map<uint64_t, std::string> parseSwapConfig() {
74+
std::map<uint64_t, std::string> swapMap;
75+
76+
const char* swapConfig = std::getenv("CLANG_AS_SWAP");
77+
if (!swapConfig) return swapMap;
78+
79+
StringRef config(swapConfig);
80+
SmallVector<StringRef, 8> pairs;
81+
config.split(pairs, ',');
82+
83+
for (StringRef pair : pairs) {
84+
SmallVector<StringRef, 2> hashAndFile;
85+
pair.split(hashAndFile, ':');
86+
if (hashAndFile.size() != 2) continue;
87+
88+
uint64_t hash;
89+
if (!hashAndFile[0].getAsInteger(16, hash)) {
90+
swapMap[hash] = hashAndFile[1].str();
91+
}
92+
}
93+
94+
return swapMap;
95+
}
96+
97+
// Helper function to get file content
98+
static std::unique_ptr<MemoryBuffer> getFileContent(StringRef Path, DiagnosticsEngine &Diags) {
99+
ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
100+
MemoryBuffer::getFileOrSTDIN(Path, /*IsText=*/true);
101+
102+
if (std::error_code EC = BufferOrErr.getError()) {
103+
Diags.Report(diag::err_fe_error_reading) << Path << EC.message();
104+
return nullptr;
105+
}
106+
107+
return std::move(*BufferOrErr);
108+
}
109+
110+
// Function to handle debug output
111+
static void handleDebugOutput(StringRef InputFile, StringRef Content) {
112+
if (const char* dbg = std::getenv("DBG_CLANG_AS")) {
113+
if (dbg[0] == '1') {
114+
MD5 Hasher;
115+
Hasher.update(Content);
116+
MD5::MD5Result Result = Hasher.final();
117+
118+
// Use the low() method to get lower 64 bits
119+
uint64_t Hash64 = Result.low();
120+
121+
llvm::errs() << "DBG_CLANG_AS: Input file: " << InputFile
122+
<< "\nMD5 (lower 64 bits): 0x"
123+
<< llvm::format_hex(Hash64, 16) << "\n";
124+
}
125+
}
126+
}
127+
128+
// Function to handle content swapping
129+
static std::unique_ptr<MemoryBuffer> handleContentSwap(
130+
StringRef InputFile,
131+
StringRef OrigContent,
132+
DiagnosticsEngine &Diags) {
133+
134+
auto swapMap = parseSwapConfig();
135+
if (swapMap.empty()) {
136+
return nullptr;
137+
}
138+
139+
// Calculate MD5 of original content
140+
MD5 Hasher;
141+
Hasher.update(OrigContent);
142+
MD5::MD5Result Result = Hasher.final();
143+
144+
// Use the low() method to get lower 64 bits
145+
uint64_t Hash64 = Result.low();
146+
147+
// Check if we need to swap content
148+
auto it = swapMap.find(Hash64);
149+
if (it != swapMap.end()) {
150+
// Found matching hash, try to load replacement content
151+
auto NewBuffer = getFileContent(it->second, Diags);
152+
if (NewBuffer) {
153+
llvm::errs() << "CLANG_AS_SWAP: Replacing content of " << InputFile
154+
<< "\nOriginal hash: 0x" << llvm::format_hex(Hash64, 16)
155+
<< "\nReplacement file: " << it->second << "\n";
156+
return NewBuffer;
157+
}
158+
}
159+
160+
return nullptr;
161+
}
162+
66163
namespace {
67164

68165
/// Helper class for representing a single invocation of the assembler.
@@ -414,29 +511,35 @@ getOutputStream(StringRef Path, DiagnosticsEngine &Diags, bool Binary) {
414511

415512
static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
416513
DiagnosticsEngine &Diags) {
417-
// Get the target specific parser.
418-
std::string Error;
419-
const Target *TheTarget = TargetRegistry::lookupTarget(Opts.Triple, Error);
420-
if (!TheTarget)
421-
return Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
422514

423-
ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer =
424-
MemoryBuffer::getFileOrSTDIN(Opts.InputFile, /*IsText=*/true);
515+
// Read original input file
516+
auto Buffer = getFileContent(Opts.InputFile, Diags);
517+
if (!Buffer) return true;
518+
519+
// Handle debug output if enabled
520+
handleDebugOutput(Opts.InputFile, Buffer->getBuffer());
425521

426-
if (std::error_code EC = Buffer.getError()) {
427-
return Diags.Report(diag::err_fe_error_reading)
428-
<< Opts.InputFile << EC.message();
522+
// Check for content swap
523+
if (auto NewBuffer = handleContentSwap(Opts.InputFile, Buffer->getBuffer(), Diags)) {
524+
Buffer = std::move(NewBuffer);
429525
}
430526

527+
// Get the target specific parser
528+
std::string Error;
529+
const Target *TheTarget = TargetRegistry::lookupTarget(Opts.Triple, Error);
530+
if (!TheTarget)
531+
return Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
532+
431533
SourceMgr SrcMgr;
432534

433-
// Tell SrcMgr about this buffer, which is what the parser will pick up.
434-
unsigned BufferIndex = SrcMgr.AddNewSourceBuffer(std::move(*Buffer), SMLoc());
535+
// Tell SrcMgr about this buffer, which is what the parser will pick up
536+
unsigned BufferIndex = SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc());
435537

436538
// Record the location of the include directories so that the lexer can find
437539
// it later.
438540
SrcMgr.setIncludeDirs(Opts.IncludePaths);
439541

542+
// Rest of original implementation...
440543
std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(Opts.Triple));
441544
assert(MRI && "Unable to create target register info!");
442545

0 commit comments

Comments
 (0)