Skip to content

Instantly share code, notes, and snippets.

@playXE
Created December 13, 2019 20:03
Show Gist options
  • Save playXE/7cb6a544aa28766ed293b481a48938bf to your computer and use it in GitHub Desktop.
Save playXE/7cb6a544aa28766ed293b481a48938bf to your computer and use it in GitHub Desktop.
Codegen irGenerator;
for (auto* module : Module::getAllImportedModules()) {
irGenerator.compile(*module);
}
auto& mainModule = irGenerator.compile(module);
if (dumpIR) {
mainModule.setModuleIdentifier("");
mainModule.setSourceFileName("");
mainModule.print(llvm::outs(), nullptr);
return 0;
}
llvm::Module linkedModule("", irGenerator.getLLVMContext());
llvm::Linker linker(linkedModule);
llvm::StringSet linked;
if (verbose)
std::cout << "Started linking procedure" << std::endl;
for (auto& module : irGenerator.getGeneratedModules()) {
if (verbose)
std::cout << "Linking '" << module->getName() << "' module" << std::endl;
auto pos = linked.find(module->getName());
if (pos == linked.end()) {
linked.insert(module->getName());
bool error = linker.linkInModule(std::move(module));
if (error)
{
printf("FAIL\n");
errorExit("LLVM module linking failed");
}
}
}
if (emitLLVMBitcode) {
::emitLLVMBitcode(linkedModule, "output.bc");
return 0;
}
auto ccPath = getCCompilerPath();
bool msvc = llvm::StringRef(ccPath).endswith_lower("cl.exe");
llvm::SmallString<128> temporaryOutputFilePath;
auto* outputFileExtension = emitAssembly ? "s" : msvc ? "obj" : "o";
if (auto error = llvm::sys::fs::createTemporaryFile("jazz", outputFileExtension, temporaryOutputFilePath)) {
errorExit(error.message());
}
auto fileType = emitAssembly ? llvm::TargetMachine::CGFT_AssemblyFile : llvm::TargetMachine::CGFT_ObjectFile;
auto relocModel = emitPositionIndependentCode ? llvm::Reloc::Model::PIC_ : llvm::Reloc::Model::Static;
emitCode(linkedModule, temporaryOutputFilePath, fileType, relocModel,level,isDebug);
if (!outputDirectory.empty()) {
auto error = llvm::sys::fs::create_directories(outputDirectory);
if (error) errorExit(error.message());
}
if (compileOnly || emitAssembly) {
llvm::SmallString<128> outputFilePath = outputDirectory;
llvm::sys::path::append(outputFilePath, llvm::Twine("output.") + outputFileExtension);
auto command = std::string("mv ");
command = (command + temporaryOutputFilePath + " " + outputFilePath).str();
system(command.c_str());
return 0;
}
llvm::SmallString<128> temporaryExecutablePath;
const char* executableNamePattern = msvc ? "jazz-%%%%%%%%.exe" : "jazz-%%%%%%%%.out";
if (auto error = llvm::sys::fs::createUniqueFile(executableNamePattern, temporaryExecutablePath)) {
errorExit(error.message());
}
std::vector<std::string> ccArgs = {
msvc ? ccPath.c_str() : argv0,
temporaryOutputFilePath.c_str(),
};
std::string outputPathFlag = ((msvc ? "-Fe" : "-o") + temporaryExecutablePath).str();
ccArgs.push_back(outputPathFlag.c_str());
ccArgs.push_back("-lc");
ccArgs.push_back("-lpthread");
if (shared) ccArgs.push_back("-shared");
if (manifest) {
for (auto& library : manifest->getLinkLibraries()) {
ccArgs.push_back(std::string("-l" + library));
}
}
if (msvc) {
ccArgs.push_back("-link");
ccArgs.push_back("-DEBUG");
ccArgs.push_back("legacy_stdio_definitions.lib");
ccArgs.push_back("ucrt.lib");
ccArgs.push_back("msvcrt.lib");
}
llvm::StringRef out = "c-compiler-stdout.txt";
llvm::StringRef err = "c-compiler-stderr.txt";
llvm::Optional<llvm::StringRef> redirects[3] = { llvm::None, out, err };
std::vector<llvm::StringRef> ccArgStringRefs(ccArgs.begin(), ccArgs.end());
int ccExitStatus = msvc ? llvm::sys::ExecuteAndWait(ccArgs[0], ccArgStringRefs, llvm::None, redirects) : invokeLinker(ccArgs,linkLibraries,static_link,use_musl);
llvm::sys::fs::remove(temporaryOutputFilePath);
uint64_t fileSize;
if (!llvm::sys::fs::file_size(out, fileSize) && fileSize == 0) llvm::sys::fs::remove(out);
if (!llvm::sys::fs::file_size(err, fileSize) && fileSize == 0) llvm::sys::fs::remove(err);
if (ccExitStatus != 0) return ccExitStatus;
if (run) {
std::string error;
llvm::StringRef executableArgs[] = { temporaryExecutablePath };
printColored("\tRunning ",llvm::raw_ostream::GREEN);
std::cout << "'" << executableArgs[0] << "'" << std::endl;
int executableExitStatus = llvm::sys::ExecuteAndWait(executableArgs[0], executableArgs, llvm::None, {}, 0, 0, &error);
llvm::sys::fs::remove(temporaryExecutablePath);
if (msvc) {
auto path = temporaryExecutablePath;
llvm::sys::path::replace_extension(path, "ilk");
llvm::sys::fs::remove(path);
llvm::sys::path::replace_extension(path, "pdb");
llvm::sys::fs::remove(path);
}
if (!error.empty()) {
llvm::outs() << error << '\n';
}
return executableExitStatus;
}
llvm::SmallString<128> outputPathPrefix = outputDirectory;
if (!outputPathPrefix.empty()) {
outputPathPrefix.append(llvm::sys::path::get_separator());
}
if (outputFileName.empty()) {
outputFileName = "a";
auto command = std::string("mv ");
command = (command + temporaryExecutablePath).str();
command = (command + " " + outputPathPrefix + outputFileName + (msvc ? ".exe" : ".out")).str();
std::system(command.c_str());
} else {
auto command = std::string("mv ");
command = (command + temporaryExecutablePath).str();
command = (command + " " + outputPathPrefix + outputFileName + (msvc ? ".exe" : "")).str();
std::system(command.c_str());
}
if (msvc) {
auto path = temporaryExecutablePath;
llvm::sys::path::replace_extension(path, "ilk");
llvm::sys::path::replace_extension(path, "pdb");
renameFile(path, outputPathPrefix + outputFileName + ".pdb");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment