Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Transforms/Utils/SymbolRewriter.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- SymbolRewriter.cpp - Symbol Rewriter -------------------------------===//
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
// SymbolRewriter is a LLVM pass which can rewrite symbols transparently within
10
// existing code.  It is implemented as a compiler pass and is configured via a
11
// YAML configuration file.
12
//
13
// The YAML configuration file format is as follows:
14
//
15
// RewriteMapFile := RewriteDescriptors
16
// RewriteDescriptors := RewriteDescriptor | RewriteDescriptors
17
// RewriteDescriptor := RewriteDescriptorType ':' '{' RewriteDescriptorFields '}'
18
// RewriteDescriptorFields := RewriteDescriptorField | RewriteDescriptorFields
19
// RewriteDescriptorField := FieldIdentifier ':' FieldValue ','
20
// RewriteDescriptorType := Identifier
21
// FieldIdentifier := Identifier
22
// FieldValue := Identifier
23
// Identifier := [0-9a-zA-Z]+
24
//
25
// Currently, the following descriptor types are supported:
26
//
27
// - function:          (function rewriting)
28
//      + Source        (original name of the function)
29
//      + Target        (explicit transformation)
30
//      + Transform     (pattern transformation)
31
//      + Naked         (boolean, whether the function is undecorated)
32
// - global variable:   (external linkage global variable rewriting)
33
//      + Source        (original name of externally visible variable)
34
//      + Target        (explicit transformation)
35
//      + Transform     (pattern transformation)
36
// - global alias:      (global alias rewriting)
37
//      + Source        (original name of the aliased name)
38
//      + Target        (explicit transformation)
39
//      + Transform     (pattern transformation)
40
//
41
// Note that source and exactly one of [Target, Transform] must be provided
42
//
43
// New rewrite descriptors can be created.  Addding a new rewrite descriptor
44
// involves:
45
//
46
//  a) extended the rewrite descriptor kind enumeration
47
//     (<anonymous>::RewriteDescriptor::RewriteDescriptorType)
48
//  b) implementing the new descriptor
49
//     (c.f. <anonymous>::ExplicitRewriteFunctionDescriptor)
50
//  c) extending the rewrite map parser
51
//     (<anonymous>::RewriteMapParser::parseEntry)
52
//
53
//  Specify to rewrite the symbols using the `-rewrite-symbols` option, and
54
//  specify the map file to use for the rewriting via the `-rewrite-map-file`
55
//  option.
56
//
57
//===----------------------------------------------------------------------===//
58
59
#include "llvm/Transforms/Utils/SymbolRewriter.h"
60
#include "llvm/ADT/STLExtras.h"
61
#include "llvm/ADT/SmallString.h"
62
#include "llvm/ADT/StringRef.h"
63
#include "llvm/ADT/ilist.h"
64
#include "llvm/ADT/iterator_range.h"
65
#include "llvm/IR/Comdat.h"
66
#include "llvm/IR/Function.h"
67
#include "llvm/IR/GlobalAlias.h"
68
#include "llvm/IR/GlobalObject.h"
69
#include "llvm/IR/GlobalVariable.h"
70
#include "llvm/IR/Module.h"
71
#include "llvm/IR/Value.h"
72
#include "llvm/Pass.h"
73
#include "llvm/Support/Casting.h"
74
#include "llvm/Support/CommandLine.h"
75
#include "llvm/Support/ErrorHandling.h"
76
#include "llvm/Support/ErrorOr.h"
77
#include "llvm/Support/MemoryBuffer.h"
78
#include "llvm/Support/Regex.h"
79
#include "llvm/Support/SourceMgr.h"
80
#include "llvm/Support/YAMLParser.h"
81
#include <memory>
82
#include <string>
83
#include <vector>
84
85
using namespace llvm;
86
using namespace SymbolRewriter;
87
88
#define DEBUG_TYPE "symbol-rewriter"
89
90
static cl::list<std::string> RewriteMapFiles("rewrite-map-file",
91
                                             cl::desc("Symbol Rewrite Map"),
92
                                             cl::value_desc("filename"),
93
                                             cl::Hidden);
94
95
static void rewriteComdat(Module &M, GlobalObject *GO,
96
                          const std::string &Source,
97
24
                          const std::string &Target) {
98
24
  if (Comdat *CD = GO->getComdat()) {
99
8
    auto &Comdats = M.getComdatSymbolTable();
100
8
101
8
    Comdat *C = M.getOrInsertComdat(Target);
102
8
    C->setSelectionKind(CD->getSelectionKind());
103
8
    GO->setComdat(C);
104
8
105
8
    Comdats.erase(Comdats.find(Source));
106
8
  }
107
24
}
108
109
namespace {
110
111
template <RewriteDescriptor::Type DT, typename ValueType,
112
          ValueType *(Module::*Get)(StringRef) const>
113
class ExplicitRewriteDescriptor : public RewriteDescriptor {
114
public:
115
  const std::string Source;
116
  const std::string Target;
117
118
  ExplicitRewriteDescriptor(StringRef S, StringRef T, const bool Naked)
119
      : RewriteDescriptor(DT), Source(Naked ? StringRef("\01" + S.str()) : S),
120
18
        Target(T) {}
SymbolRewriter.cpp:(anonymous namespace)::ExplicitRewriteDescriptor<(llvm::SymbolRewriter::RewriteDescriptor::Type)1, llvm::Function, &(llvm::Module::getFunction(llvm::StringRef) const)>::ExplicitRewriteDescriptor(llvm::StringRef, llvm::StringRef, bool)
Line
Count
Source
120
12
        Target(T) {}
SymbolRewriter.cpp:(anonymous namespace)::ExplicitRewriteDescriptor<(llvm::SymbolRewriter::RewriteDescriptor::Type)2, llvm::GlobalVariable, &(llvm::Module::getGlobalVariable(llvm::StringRef) const)>::ExplicitRewriteDescriptor(llvm::StringRef, llvm::StringRef, bool)
Line
Count
Source
120
4
        Target(T) {}
SymbolRewriter.cpp:(anonymous namespace)::ExplicitRewriteDescriptor<(llvm::SymbolRewriter::RewriteDescriptor::Type)3, llvm::GlobalAlias, &(llvm::Module::getNamedAlias(llvm::StringRef) const)>::ExplicitRewriteDescriptor(llvm::StringRef, llvm::StringRef, bool)
Line
Count
Source
120
2
        Target(T) {}
121
122
  bool performOnModule(Module &M) override;
123
124
  static bool classof(const RewriteDescriptor *RD) {
125
    return RD->getType() == DT;
126
  }
127
};
128
129
} // end anonymous namespace
130
131
template <RewriteDescriptor::Type DT, typename ValueType,
132
          ValueType *(Module::*Get)(StringRef) const>
133
18
bool ExplicitRewriteDescriptor<DT, ValueType, Get>::performOnModule(Module &M) {
134
18
  bool Changed = false;
135
18
  if (ValueType *S = (M.*Get)(Source)) {
136
14
    if (GlobalObject *GO = dyn_cast<GlobalObject>(S))
137
12
      rewriteComdat(M, GO, Source, Target);
138
14
139
14
    if (Value *T = (M.*Get)(Target))
140
0
      S->setValueName(T->getValueName());
141
14
    else
142
14
      S->setName(Target);
143
14
144
14
    Changed = true;
145
14
  }
146
18
  return Changed;
147
18
}
SymbolRewriter.cpp:(anonymous namespace)::ExplicitRewriteDescriptor<(llvm::SymbolRewriter::RewriteDescriptor::Type)1, llvm::Function, &(llvm::Module::getFunction(llvm::StringRef) const)>::performOnModule(llvm::Module&)
Line
Count
Source
133
12
bool ExplicitRewriteDescriptor<DT, ValueType, Get>::performOnModule(Module &M) {
134
12
  bool Changed = false;
135
12
  if (ValueType *S = (M.*Get)(Source)) {
136
8
    if (GlobalObject *GO = dyn_cast<GlobalObject>(S))
137
8
      rewriteComdat(M, GO, Source, Target);
138
8
139
8
    if (Value *T = (M.*Get)(Target))
140
0
      S->setValueName(T->getValueName());
141
8
    else
142
8
      S->setName(Target);
143
8
144
8
    Changed = true;
145
8
  }
146
12
  return Changed;
147
12
}
SymbolRewriter.cpp:(anonymous namespace)::ExplicitRewriteDescriptor<(llvm::SymbolRewriter::RewriteDescriptor::Type)2, llvm::GlobalVariable, &(llvm::Module::getGlobalVariable(llvm::StringRef) const)>::performOnModule(llvm::Module&)
Line
Count
Source
133
4
bool ExplicitRewriteDescriptor<DT, ValueType, Get>::performOnModule(Module &M) {
134
4
  bool Changed = false;
135
4
  if (ValueType *S = (M.*Get)(Source)) {
136
4
    if (GlobalObject *GO = dyn_cast<GlobalObject>(S))
137
4
      rewriteComdat(M, GO, Source, Target);
138
4
139
4
    if (Value *T = (M.*Get)(Target))
140
0
      S->setValueName(T->getValueName());
141
4
    else
142
4
      S->setName(Target);
143
4
144
4
    Changed = true;
145
4
  }
146
4
  return Changed;
147
4
}
SymbolRewriter.cpp:(anonymous namespace)::ExplicitRewriteDescriptor<(llvm::SymbolRewriter::RewriteDescriptor::Type)3, llvm::GlobalAlias, &(llvm::Module::getNamedAlias(llvm::StringRef) const)>::performOnModule(llvm::Module&)
Line
Count
Source
133
2
bool ExplicitRewriteDescriptor<DT, ValueType, Get>::performOnModule(Module &M) {
134
2
  bool Changed = false;
135
2
  if (ValueType *S = (M.*Get)(Source)) {
136
2
    if (GlobalObject *GO = dyn_cast<GlobalObject>(S))
137
0
      rewriteComdat(M, GO, Source, Target);
138
2
139
2
    if (Value *T = (M.*Get)(Target))
140
0
      S->setValueName(T->getValueName());
141
2
    else
142
2
      S->setName(Target);
143
2
144
2
    Changed = true;
145
2
  }
146
2
  return Changed;
147
2
}
148
149
namespace {
150
151
template <RewriteDescriptor::Type DT, typename ValueType,
152
          ValueType *(Module::*Get)(StringRef) const,
153
          iterator_range<typename iplist<ValueType>::iterator>
154
          (Module::*Iterator)()>
155
class PatternRewriteDescriptor : public RewriteDescriptor {
156
public:
157
  const std::string Pattern;
158
  const std::string Transform;
159
160
  PatternRewriteDescriptor(StringRef P, StringRef T)
161
8
    : RewriteDescriptor(DT), Pattern(P), Transform(T) { }
SymbolRewriter.cpp:(anonymous namespace)::PatternRewriteDescriptor<(llvm::SymbolRewriter::RewriteDescriptor::Type)1, llvm::Function, &(llvm::Module::getFunction(llvm::StringRef) const), &(llvm::Module::functions())>::PatternRewriteDescriptor(llvm::StringRef, llvm::StringRef)
Line
Count
Source
161
4
    : RewriteDescriptor(DT), Pattern(P), Transform(T) { }
SymbolRewriter.cpp:(anonymous namespace)::PatternRewriteDescriptor<(llvm::SymbolRewriter::RewriteDescriptor::Type)2, llvm::GlobalVariable, &(llvm::Module::getGlobalVariable(llvm::StringRef) const), &(llvm::Module::globals())>::PatternRewriteDescriptor(llvm::StringRef, llvm::StringRef)
Line
Count
Source
161
4
    : RewriteDescriptor(DT), Pattern(P), Transform(T) { }
Unexecuted instantiation: SymbolRewriter.cpp:(anonymous namespace)::PatternRewriteDescriptor<(llvm::SymbolRewriter::RewriteDescriptor::Type)3, llvm::GlobalAlias, &(llvm::Module::getNamedAlias(llvm::StringRef) const), &(llvm::Module::aliases())>::PatternRewriteDescriptor(llvm::StringRef, llvm::StringRef)
162
163
  bool performOnModule(Module &M) override;
164
165
  static bool classof(const RewriteDescriptor *RD) {
166
    return RD->getType() == DT;
167
  }
168
};
169
170
} // end anonymous namespace
171
172
template <RewriteDescriptor::Type DT, typename ValueType,
173
          ValueType *(Module::*Get)(StringRef) const,
174
          iterator_range<typename iplist<ValueType>::iterator>
175
          (Module::*Iterator)()>
176
bool PatternRewriteDescriptor<DT, ValueType, Get, Iterator>::
177
8
performOnModule(Module &M) {
178
8
  bool Changed = false;
179
64
  for (auto &C : (M.*Iterator)()) {
180
64
    std::string Error;
181
64
182
64
    std::string Name = Regex(Pattern).sub(Transform, C.getName(), &Error);
183
64
    if (!Error.empty())
184
0
      report_fatal_error("unable to transforn " + C.getName() + " in " +
185
0
                         M.getModuleIdentifier() + ": " + Error);
186
64
187
64
    if (C.getName() == Name)
188
52
      continue;
189
12
190
12
    if (GlobalObject *GO = dyn_cast<GlobalObject>(&C))
191
12
      rewriteComdat(M, GO, C.getName(), Name);
192
12
193
12
    if (Value *V = (M.*Get)(Name))
194
0
      C.setValueName(V->getValueName());
195
12
    else
196
12
      C.setName(Name);
197
12
198
12
    Changed = true;
199
12
  }
200
8
  return Changed;
201
8
}
SymbolRewriter.cpp:(anonymous namespace)::PatternRewriteDescriptor<(llvm::SymbolRewriter::RewriteDescriptor::Type)1, llvm::Function, &(llvm::Module::getFunction(llvm::StringRef) const), &(llvm::Module::functions())>::performOnModule(llvm::Module&)
Line
Count
Source
177
4
performOnModule(Module &M) {
178
4
  bool Changed = false;
179
44
  for (auto &C : (M.*Iterator)()) {
180
44
    std::string Error;
181
44
182
44
    std::string Name = Regex(Pattern).sub(Transform, C.getName(), &Error);
183
44
    if (!Error.empty())
184
0
      report_fatal_error("unable to transforn " + C.getName() + " in " +
185
0
                         M.getModuleIdentifier() + ": " + Error);
186
44
187
44
    if (C.getName() == Name)
188
38
      continue;
189
6
190
6
    if (GlobalObject *GO = dyn_cast<GlobalObject>(&C))
191
6
      rewriteComdat(M, GO, C.getName(), Name);
192
6
193
6
    if (Value *V = (M.*Get)(Name))
194
0
      C.setValueName(V->getValueName());
195
6
    else
196
6
      C.setName(Name);
197
6
198
6
    Changed = true;
199
6
  }
200
4
  return Changed;
201
4
}
SymbolRewriter.cpp:(anonymous namespace)::PatternRewriteDescriptor<(llvm::SymbolRewriter::RewriteDescriptor::Type)2, llvm::GlobalVariable, &(llvm::Module::getGlobalVariable(llvm::StringRef) const), &(llvm::Module::globals())>::performOnModule(llvm::Module&)
Line
Count
Source
177
4
performOnModule(Module &M) {
178
4
  bool Changed = false;
179
20
  for (auto &C : (M.*Iterator)()) {
180
20
    std::string Error;
181
20
182
20
    std::string Name = Regex(Pattern).sub(Transform, C.getName(), &Error);
183
20
    if (!Error.empty())
184
0
      report_fatal_error("unable to transforn " + C.getName() + " in " +
185
0
                         M.getModuleIdentifier() + ": " + Error);
186
20
187
20
    if (C.getName() == Name)
188
14
      continue;
189
6
190
6
    if (GlobalObject *GO = dyn_cast<GlobalObject>(&C))
191
6
      rewriteComdat(M, GO, C.getName(), Name);
192
6
193
6
    if (Value *V = (M.*Get)(Name))
194
0
      C.setValueName(V->getValueName());
195
6
    else
196
6
      C.setName(Name);
197
6
198
6
    Changed = true;
199
6
  }
200
4
  return Changed;
201
4
}
Unexecuted instantiation: SymbolRewriter.cpp:(anonymous namespace)::PatternRewriteDescriptor<(llvm::SymbolRewriter::RewriteDescriptor::Type)3, llvm::GlobalAlias, &(llvm::Module::getNamedAlias(llvm::StringRef) const), &(llvm::Module::aliases())>::performOnModule(llvm::Module&)
202
203
namespace {
204
205
/// Represents a rewrite for an explicitly named (function) symbol.  Both the
206
/// source function name and target function name of the transformation are
207
/// explicitly spelt out.
208
using ExplicitRewriteFunctionDescriptor =
209
    ExplicitRewriteDescriptor<RewriteDescriptor::Type::Function, Function,
210
                              &Module::getFunction>;
211
212
/// Represents a rewrite for an explicitly named (global variable) symbol.  Both
213
/// the source variable name and target variable name are spelt out.  This
214
/// applies only to module level variables.
215
using ExplicitRewriteGlobalVariableDescriptor =
216
    ExplicitRewriteDescriptor<RewriteDescriptor::Type::GlobalVariable,
217
                              GlobalVariable, &Module::getGlobalVariable>;
218
219
/// Represents a rewrite for an explicitly named global alias.  Both the source
220
/// and target name are explicitly spelt out.
221
using ExplicitRewriteNamedAliasDescriptor =
222
    ExplicitRewriteDescriptor<RewriteDescriptor::Type::NamedAlias, GlobalAlias,
223
                              &Module::getNamedAlias>;
224
225
/// Represents a rewrite for a regular expression based pattern for functions.
226
/// A pattern for the function name is provided and a transformation for that
227
/// pattern to determine the target function name create the rewrite rule.
228
using PatternRewriteFunctionDescriptor =
229
    PatternRewriteDescriptor<RewriteDescriptor::Type::Function, Function,
230
                             &Module::getFunction, &Module::functions>;
231
232
/// Represents a rewrite for a global variable based upon a matching pattern.
233
/// Each global variable matching the provided pattern will be transformed as
234
/// described in the transformation pattern for the target.  Applies only to
235
/// module level variables.
236
using PatternRewriteGlobalVariableDescriptor =
237
    PatternRewriteDescriptor<RewriteDescriptor::Type::GlobalVariable,
238
                             GlobalVariable, &Module::getGlobalVariable,
239
                             &Module::globals>;
240
241
/// PatternRewriteNamedAliasDescriptor - represents a rewrite for global
242
/// aliases which match a given pattern.  The provided transformation will be
243
/// applied to each of the matching names.
244
using PatternRewriteNamedAliasDescriptor =
245
    PatternRewriteDescriptor<RewriteDescriptor::Type::NamedAlias, GlobalAlias,
246
                             &Module::getNamedAlias, &Module::aliases>;
247
248
} // end anonymous namespace
249
250
bool RewriteMapParser::parse(const std::string &MapFile,
251
2
                             RewriteDescriptorList *DL) {
252
2
  ErrorOr<std::unique_ptr<MemoryBuffer>> Mapping =
253
2
      MemoryBuffer::getFile(MapFile);
254
2
255
2
  if (!Mapping)
256
0
    report_fatal_error("unable to read rewrite map '" + MapFile + "': " +
257
0
                       Mapping.getError().message());
258
2
259
2
  if (!parse(*Mapping, DL))
260
0
    report_fatal_error("unable to parse rewrite map '" + MapFile + "'");
261
2
262
2
  return true;
263
2
}
264
265
bool RewriteMapParser::parse(std::unique_ptr<MemoryBuffer> &MapFile,
266
2
                             RewriteDescriptorList *DL) {
267
2
  SourceMgr SM;
268
2
  yaml::Stream YS(MapFile->getBuffer(), SM);
269
2
270
2
  for (auto &Document : YS) {
271
2
    yaml::MappingNode *DescriptorList;
272
2
273
2
    // ignore empty documents
274
2
    if (isa<yaml::NullNode>(Document.getRoot()))
275
0
      continue;
276
2
277
2
    DescriptorList = dyn_cast<yaml::MappingNode>(Document.getRoot());
278
2
    if (!DescriptorList) {
279
0
      YS.printError(Document.getRoot(), "DescriptorList node must be a map");
280
0
      return false;
281
0
    }
282
2
283
2
    for (auto &Descriptor : *DescriptorList)
284
26
      if (!parseEntry(YS, Descriptor, DL))
285
0
        return false;
286
2
  }
287
2
288
2
  return true;
289
2
}
290
291
bool RewriteMapParser::parseEntry(yaml::Stream &YS, yaml::KeyValueNode &Entry,
292
26
                                  RewriteDescriptorList *DL) {
293
26
  yaml::ScalarNode *Key;
294
26
  yaml::MappingNode *Value;
295
26
  SmallString<32> KeyStorage;
296
26
  StringRef RewriteType;
297
26
298
26
  Key = dyn_cast<yaml::ScalarNode>(Entry.getKey());
299
26
  if (!Key) {
300
0
    YS.printError(Entry.getKey(), "rewrite type must be a scalar");
301
0
    return false;
302
0
  }
303
26
304
26
  Value = dyn_cast<yaml::MappingNode>(Entry.getValue());
305
26
  if (!Value) {
306
0
    YS.printError(Entry.getValue(), "rewrite descriptor must be a map");
307
0
    return false;
308
0
  }
309
26
310
26
  RewriteType = Key->getValue(KeyStorage);
311
26
  if (RewriteType.equals("function"))
312
16
    return parseRewriteFunctionDescriptor(YS, Key, Value, DL);
313
10
  else if (RewriteType.equals("global variable"))
314
8
    return parseRewriteGlobalVariableDescriptor(YS, Key, Value, DL);
315
2
  else if (RewriteType.equals("global alias"))
316
2
    return parseRewriteGlobalAliasDescriptor(YS, Key, Value, DL);
317
0
318
0
  YS.printError(Entry.getKey(), "unknown rewrite type");
319
0
  return false;
320
0
}
321
322
bool RewriteMapParser::
323
parseRewriteFunctionDescriptor(yaml::Stream &YS, yaml::ScalarNode *K,
324
                               yaml::MappingNode *Descriptor,
325
16
                               RewriteDescriptorList *DL) {
326
16
  bool Naked = false;
327
16
  std::string Source;
328
16
  std::string Target;
329
16
  std::string Transform;
330
16
331
34
  for (auto &Field : *Descriptor) {
332
34
    yaml::ScalarNode *Key;
333
34
    yaml::ScalarNode *Value;
334
34
    SmallString<32> KeyStorage;
335
34
    SmallString<32> ValueStorage;
336
34
    StringRef KeyValue;
337
34
338
34
    Key = dyn_cast<yaml::ScalarNode>(Field.getKey());
339
34
    if (!Key) {
340
0
      YS.printError(Field.getKey(), "descriptor key must be a scalar");
341
0
      return false;
342
0
    }
343
34
344
34
    Value = dyn_cast<yaml::ScalarNode>(Field.getValue());
345
34
    if (!Value) {
346
0
      YS.printError(Field.getValue(), "descriptor value must be a scalar");
347
0
      return false;
348
0
    }
349
34
350
34
    KeyValue = Key->getValue(KeyStorage);
351
34
    if (KeyValue.equals("source")) {
352
16
      std::string Error;
353
16
354
16
      Source = Value->getValue(ValueStorage);
355
16
      if (!Regex(Source).isValid(Error)) {
356
0
        YS.printError(Field.getKey(), "invalid regex: " + Error);
357
0
        return false;
358
0
      }
359
18
    } else if (KeyValue.equals("target")) {
360
12
      Target = Value->getValue(ValueStorage);
361
12
    } else 
if (6
KeyValue.equals("transform")6
) {
362
4
      Transform = Value->getValue(ValueStorage);
363
4
    } else 
if (2
KeyValue.equals("naked")2
) {
364
2
      std::string Undecorated;
365
2
366
2
      Undecorated = Value->getValue(ValueStorage);
367
2
      Naked = StringRef(Undecorated).lower() == "true" || 
Undecorated == "1"0
;
368
2
    } else {
369
0
      YS.printError(Field.getKey(), "unknown key for function");
370
0
      return false;
371
0
    }
372
34
  }
373
16
374
16
  if (Transform.empty() == Target.empty()) {
375
0
    YS.printError(Descriptor,
376
0
                  "exactly one of transform or target must be specified");
377
0
    return false;
378
0
  }
379
16
380
16
  // TODO see if there is a more elegant solution to selecting the rewrite
381
16
  // descriptor type
382
16
  if (!Target.empty())
383
12
    DL->push_back(llvm::make_unique<ExplicitRewriteFunctionDescriptor>(
384
12
        Source, Target, Naked));
385
4
  else
386
4
    DL->push_back(
387
4
        llvm::make_unique<PatternRewriteFunctionDescriptor>(Source, Transform));
388
16
389
16
  return true;
390
16
}
391
392
bool RewriteMapParser::
393
parseRewriteGlobalVariableDescriptor(yaml::Stream &YS, yaml::ScalarNode *K,
394
                                     yaml::MappingNode *Descriptor,
395
8
                                     RewriteDescriptorList *DL) {
396
8
  std::string Source;
397
8
  std::string Target;
398
8
  std::string Transform;
399
8
400
16
  for (auto &Field : *Descriptor) {
401
16
    yaml::ScalarNode *Key;
402
16
    yaml::ScalarNode *Value;
403
16
    SmallString<32> KeyStorage;
404
16
    SmallString<32> ValueStorage;
405
16
    StringRef KeyValue;
406
16
407
16
    Key = dyn_cast<yaml::ScalarNode>(Field.getKey());
408
16
    if (!Key) {
409
0
      YS.printError(Field.getKey(), "descriptor Key must be a scalar");
410
0
      return false;
411
0
    }
412
16
413
16
    Value = dyn_cast<yaml::ScalarNode>(Field.getValue());
414
16
    if (!Value) {
415
0
      YS.printError(Field.getValue(), "descriptor value must be a scalar");
416
0
      return false;
417
0
    }
418
16
419
16
    KeyValue = Key->getValue(KeyStorage);
420
16
    if (KeyValue.equals("source")) {
421
8
      std::string Error;
422
8
423
8
      Source = Value->getValue(ValueStorage);
424
8
      if (!Regex(Source).isValid(Error)) {
425
0
        YS.printError(Field.getKey(), "invalid regex: " + Error);
426
0
        return false;
427
0
      }
428
8
    } else if (KeyValue.equals("target")) {
429
4
      Target = Value->getValue(ValueStorage);
430
4
    } else if (KeyValue.equals("transform")) {
431
4
      Transform = Value->getValue(ValueStorage);
432
4
    } else {
433
0
      YS.printError(Field.getKey(), "unknown Key for Global Variable");
434
0
      return false;
435
0
    }
436
16
  }
437
8
438
8
  if (Transform.empty() == Target.empty()) {
439
0
    YS.printError(Descriptor,
440
0
                  "exactly one of transform or target must be specified");
441
0
    return false;
442
0
  }
443
8
444
8
  if (!Target.empty())
445
4
    DL->push_back(llvm::make_unique<ExplicitRewriteGlobalVariableDescriptor>(
446
4
        Source, Target,
447
4
        /*Naked*/ false));
448
4
  else
449
4
    DL->push_back(llvm::make_unique<PatternRewriteGlobalVariableDescriptor>(
450
4
        Source, Transform));
451
8
452
8
  return true;
453
8
}
454
455
bool RewriteMapParser::
456
parseRewriteGlobalAliasDescriptor(yaml::Stream &YS, yaml::ScalarNode *K,
457
                                  yaml::MappingNode *Descriptor,
458
2
                                  RewriteDescriptorList *DL) {
459
2
  std::string Source;
460
2
  std::string Target;
461
2
  std::string Transform;
462
2
463
4
  for (auto &Field : *Descriptor) {
464
4
    yaml::ScalarNode *Key;
465
4
    yaml::ScalarNode *Value;
466
4
    SmallString<32> KeyStorage;
467
4
    SmallString<32> ValueStorage;
468
4
    StringRef KeyValue;
469
4
470
4
    Key = dyn_cast<yaml::ScalarNode>(Field.getKey());
471
4
    if (!Key) {
472
0
      YS.printError(Field.getKey(), "descriptor key must be a scalar");
473
0
      return false;
474
0
    }
475
4
476
4
    Value = dyn_cast<yaml::ScalarNode>(Field.getValue());
477
4
    if (!Value) {
478
0
      YS.printError(Field.getValue(), "descriptor value must be a scalar");
479
0
      return false;
480
0
    }
481
4
482
4
    KeyValue = Key->getValue(KeyStorage);
483
4
    if (KeyValue.equals("source")) {
484
2
      std::string Error;
485
2
486
2
      Source = Value->getValue(ValueStorage);
487
2
      if (!Regex(Source).isValid(Error)) {
488
0
        YS.printError(Field.getKey(), "invalid regex: " + Error);
489
0
        return false;
490
0
      }
491
2
    } else if (KeyValue.equals("target")) {
492
2
      Target = Value->getValue(ValueStorage);
493
2
    } else 
if (0
KeyValue.equals("transform")0
) {
494
0
      Transform = Value->getValue(ValueStorage);
495
0
    } else {
496
0
      YS.printError(Field.getKey(), "unknown key for Global Alias");
497
0
      return false;
498
0
    }
499
4
  }
500
2
501
2
  if (Transform.empty() == Target.empty()) {
502
0
    YS.printError(Descriptor,
503
0
                  "exactly one of transform or target must be specified");
504
0
    return false;
505
0
  }
506
2
507
2
  if (!Target.empty())
508
2
    DL->push_back(llvm::make_unique<ExplicitRewriteNamedAliasDescriptor>(
509
2
        Source, Target,
510
2
        /*Naked*/ false));
511
0
  else
512
0
    DL->push_back(llvm::make_unique<PatternRewriteNamedAliasDescriptor>(
513
0
        Source, Transform));
514
2
515
2
  return true;
516
2
}
517
518
namespace {
519
520
class RewriteSymbolsLegacyPass : public ModulePass {
521
public:
522
  static char ID; // Pass identification, replacement for typeid
523
524
  RewriteSymbolsLegacyPass();
525
  RewriteSymbolsLegacyPass(SymbolRewriter::RewriteDescriptorList &DL);
526
527
  bool runOnModule(Module &M) override;
528
529
private:
530
  RewriteSymbolPass Impl;
531
};
532
533
} // end anonymous namespace
534
535
char RewriteSymbolsLegacyPass::ID = 0;
536
537
36.3k
RewriteSymbolsLegacyPass::RewriteSymbolsLegacyPass() : ModulePass(ID) {
538
36.3k
  initializeRewriteSymbolsLegacyPassPass(*PassRegistry::getPassRegistry());
539
36.3k
}
540
541
RewriteSymbolsLegacyPass::RewriteSymbolsLegacyPass(
542
    SymbolRewriter::RewriteDescriptorList &DL)
543
0
    : ModulePass(ID), Impl(DL) {}
544
545
36.1k
bool RewriteSymbolsLegacyPass::runOnModule(Module &M) {
546
36.1k
  return Impl.runImpl(M);
547
36.1k
}
548
549
1
PreservedAnalyses RewriteSymbolPass::run(Module &M, ModuleAnalysisManager &AM) {
550
1
  if (!runImpl(M))
551
0
    return PreservedAnalyses::all();
552
1
553
1
  return PreservedAnalyses::none();
554
1
}
555
556
36.1k
bool RewriteSymbolPass::runImpl(Module &M) {
557
36.1k
  bool Changed;
558
36.1k
559
36.1k
  Changed = false;
560
36.1k
  for (auto &Descriptor : Descriptors)
561
26
    Changed |= Descriptor->performOnModule(M);
562
36.1k
563
36.1k
  return Changed;
564
36.1k
}
565
566
36.3k
void RewriteSymbolPass::loadAndParseMapFiles() {
567
36.3k
  const std::vector<std::string> MapFiles(RewriteMapFiles);
568
36.3k
  SymbolRewriter::RewriteMapParser Parser;
569
36.3k
570
36.3k
  for (const auto &MapFile : MapFiles)
571
2
    Parser.parse(MapFile, &Descriptors);
572
36.3k
}
573
574
INITIALIZE_PASS(RewriteSymbolsLegacyPass, "rewrite-symbols", "Rewrite Symbols",
575
                false, false)
576
577
36.3k
ModulePass *llvm::createRewriteSymbolsPass() {
578
36.3k
  return new RewriteSymbolsLegacyPass();
579
36.3k
}
580
581
ModulePass *
582
0
llvm::createRewriteSymbolsPass(SymbolRewriter::RewriteDescriptorList &DL) {
583
0
  return new RewriteSymbolsLegacyPass(DL);
584
0
}