forked from llvm/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 339
/
Copy pathDriver.cpp
128 lines (110 loc) · 4.48 KB
/
Driver.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
//===- Driver.cpp - A C Interface for the Clang Driver --------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file provides a C API for extracting information from the clang driver.
//
//===----------------------------------------------------------------------===//
#include "clang-c/Driver.h"
#include "CIndexDiagnostic.h"
#include "CXDiagnosticSetDiagnosticConsumer.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Frontend/CompilerInstance.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/TargetParser/Host.h"
using namespace clang;
CXExternalActionList *
clang_Driver_getExternalActionsForCommand_v0(int ArgC, const char **ArgV,
const char **Environment,
const char *WorkingDirectory,
CXDiagnosticSet *OutDiags) {
if (OutDiags)
*OutDiags = nullptr;
// Non empty environments are not currently supported.
if (Environment)
return nullptr;
// ArgV must at least include the compiler executable name.
if (ArgC < 1)
return nullptr;
// Use createPhysicalFileSystem instead of getRealFileSystem so that
// setCurrentWorkingDirectory doesn't change the working directory of the
// process.
std::unique_ptr<llvm::vfs::FileSystem> VFS =
llvm::vfs::createPhysicalFileSystem();
CXDiagnosticSetDiagnosticConsumer DiagConsumer;
SmallVector<const char *, 256> Args(ArgV, ArgV + ArgC);
llvm::BumpPtrAllocator Alloc;
if (llvm::Error E =
driver::expandResponseFiles(Args, /*CLMode=*/false, Alloc)) {
// Construct a default DiagnosticOptions to use to emit the failure.
DiagnosticOptions DiagOpts;
auto Diags = CompilerInstance::createDiagnostics(*VFS, &DiagOpts,
&DiagConsumer, false);
Diags->Report(diag::err_drv_expand_response_file)
<< llvm::toString(std::move(E));
return nullptr;
}
auto DiagOpts = CreateAndPopulateDiagOpts(Args);
auto Diags = CompilerInstance::createDiagnostics(*VFS, DiagOpts.release(),
&DiagConsumer, false);
if (WorkingDirectory)
if (std::error_code EC =
VFS->setCurrentWorkingDirectory(WorkingDirectory)) {
Diags->Report(diag::err_drv_unable_to_set_working_directory) <<
WorkingDirectory;
if (OutDiags)
*OutDiags = DiagConsumer.getDiagnosticSet();
return nullptr;
}
driver::Driver TheDriver(ArgV[0], llvm::sys::getDefaultTargetTriple(), *Diags, "clang LLVM compiler",
VFS.release());
TheDriver.setCheckInputsExist(false);
std::unique_ptr<driver::Compilation> C(
TheDriver.BuildCompilation(Args));
if (!C || Diags->hasErrorOccurred()) {
if (OutDiags)
*OutDiags = DiagConsumer.getDiagnosticSet();
return nullptr;
}
const driver::JobList &Jobs = C->getJobs();
CXExternalAction **Actions = new CXExternalAction *[Jobs.size()];
int AI = 0;
for (auto &&J : Jobs) {
// First calculate the total space we'll need for this action's arguments.
llvm::opt::ArgStringList Args = J.getArguments();
Args.insert(Args.begin(), J.getExecutable());
int ArgSpace = (Args.size() + 1) * sizeof(const char *);
for (auto &&Arg : Args)
ArgSpace += strlen(Arg) + 1; // Null terminator
// Tail allocate the space for the strings.
auto Action =
new ((CXExternalAction *)malloc(sizeof(CXExternalAction) + ArgSpace))
CXExternalAction;
Action->ArgC = Args.size();
Action->ArgV = reinterpret_cast<const char **>(Action + 1);
Action->ArgV[Args.size()] = nullptr;
char *StrTable = ((char *)Action) + sizeof(CXExternalAction) +
(Args.size() + 1) * sizeof(const char *);
int I = 0;
for (auto &&Arg : Args) {
Action->ArgV[I++] = strcpy(StrTable, Arg);
StrTable += strlen(Arg) + 1;
}
Actions[AI++] = Action;
}
return new CXExternalActionList{(int)Jobs.size(), Actions};
}
void clang_Driver_ExternalActionList_dispose(CXExternalActionList *EAL) {
if (!EAL)
return;
for (int I = 0; I < EAL->Count; ++I)
free(EAL->Actions[I]);
delete[] EAL->Actions;
delete EAL;
}