~ubuntu-branches/ubuntu/wily/clamav/wily-proposed

« back to all changes in this revision

Viewing changes to libclamav/c++/llvm/lib/CodeGen/RenderMachineFunction.cpp

  • Committer: Package Import Robot
  • Author(s): Scott Kitterman, Sebastian Andrzej Siewior, Andreas Cadhalpun, Scott Kitterman, Javier Fernández-Sanguino
  • Date: 2015-01-28 00:25:13 UTC
  • mfrom: (0.48.14 sid)
  • Revision ID: package-import@ubuntu.com-20150128002513-lil2oi74cooy4lzr
Tags: 0.98.6+dfsg-1
[ Sebastian Andrzej Siewior ]
* update "fix-ssize_t-size_t-off_t-printf-modifier", include of misc.h was
  missing but was pulled in via the systemd patch.
* Don't leak return codes from libmspack to clamav API. (Closes: #774686).

[ Andreas Cadhalpun ]
* Add patch to avoid emitting incremental progress messages when not
  outputting to a terminal. (Closes: #767350)
* Update lintian-overrides for unused-file-paragraph-in-dep5-copyright.
* clamav-base.postinst: always chown /var/log/clamav and /var/lib/clamav
  to clamav:clamav, not only on fresh installations. (Closes: #775400)
* Adapt the clamav-daemon and clamav-freshclam logrotate scripts,
  so that they correctly work under systemd.
* Move the PidFile variable from the clamd/freshclam configuration files
  to the init scripts. This makes the init scripts more robust against
  misconfiguration and avoids error messages with systemd. (Closes: #767353)
* debian/copyright: drop files from Files-Excluded only present in github
  tarballs
* Drop Workaround-a-bug-in-libc-on-Hurd.patch, because hurd got fixed.
  (see #752237)
* debian/rules: Remove useless --with-system-tommath --without-included-ltdl
  configure options.

[ Scott Kitterman ]
* Stop stripping llvm when repacking the tarball as the system llvm on some
  releases is too old to use
* New upstream bugfix release
  - Library shared object revisions.
  - Includes a patch from Sebastian Andrzej Siewior making ClamAV pid files
    compatible with systemd.
  - Fix a heap out of bounds condition with crafted Yoda's crypter files.
    This issue was discovered by Felix Groebert of the Google Security Team.
  - Fix a heap out of bounds condition with crafted mew packer files. This
    issue was discovered by Felix Groebert of the Google Security Team.
  - Fix a heap out of bounds condition with crafted upx packer files. This
    issue was discovered by Kevin Szkudlapski of Quarkslab.
  - Fix a heap out of bounds condition with crafted upack packer files. This
    issue was discovered by Sebastian Andrzej Siewior. CVE-2014-9328.
  - Compensate a crash due to incorrect compiler optimization when handling
    crafted petite packer files. This issue was discovered by Sebastian
    Andrzej Siewior.
* Update lintian override for embedded zlib to match new so version

[ Javier Fernández-Sanguino ]
* Updated Spanish Debconf template translation (Closes: #773563)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//===-- llvm/CodeGen/RenderMachineFunction.cpp - MF->HTML -----s-----------===//
 
2
//
 
3
//                     The LLVM Compiler Infrastructure
 
4
//
 
5
// This file is distributed under the University of Illinois Open Source
 
6
// License. See LICENSE.TXT for details.
 
7
//
 
8
//===----------------------------------------------------------------------===//
 
9
 
 
10
#define DEBUG_TYPE "rendermf"
 
11
 
 
12
#include "RenderMachineFunction.h"
 
13
 
 
14
#include "VirtRegMap.h"
 
15
 
 
16
#include "llvm/Function.h"
 
17
#include "llvm/Module.h"
 
18
#include "llvm/ADT/SmallVector.h"
 
19
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
 
20
#include "llvm/CodeGen/MachineFunction.h"
 
21
#include "llvm/CodeGen/MachineInstr.h"
 
22
#include "llvm/CodeGen/MachineRegisterInfo.h"
 
23
#include "llvm/Support/CommandLine.h"
 
24
#include "llvm/Support/Debug.h"
 
25
#include "llvm/Support/raw_ostream.h"
 
26
#include "llvm/Target/TargetMachine.h"
 
27
 
 
28
#include <sstream>
 
29
 
 
30
using namespace llvm;
 
31
 
 
32
char RenderMachineFunction::ID = 0;
 
33
INITIALIZE_PASS(RenderMachineFunction, "rendermf",
 
34
                "Render machine functions (and related info) to HTML pages",
 
35
                false, false);
 
36
 
 
37
static cl::opt<std::string>
 
38
outputFileSuffix("rmf-file-suffix",
 
39
                 cl::desc("Appended to function name to get output file name "
 
40
                          "(default: \".html\")"),
 
41
                 cl::init(".html"), cl::Hidden);
 
42
 
 
43
static cl::opt<std::string>
 
44
machineFuncsToRender("rmf-funcs",
 
45
                     cl::desc("Coma seperated list of functions to render"
 
46
                              ", or \"*\"."),
 
47
                     cl::init(""), cl::Hidden);
 
48
 
 
49
static cl::opt<std::string>
 
50
pressureClasses("rmf-classes",
 
51
                cl::desc("Register classes to render pressure for."),
 
52
                cl::init(""), cl::Hidden);
 
53
 
 
54
static cl::opt<std::string>
 
55
showIntervals("rmf-intervals",
 
56
              cl::desc("Live intervals to show alongside code."),
 
57
              cl::init(""), cl::Hidden);
 
58
 
 
59
static cl::opt<bool>
 
60
filterEmpty("rmf-filter-empty-intervals",
 
61
            cl::desc("Don't display empty intervals."),
 
62
            cl::init(true), cl::Hidden);
 
63
 
 
64
static cl::opt<bool>
 
65
showEmptyIndexes("rmf-empty-indexes",
 
66
                 cl::desc("Render indexes not associated with instructions or "
 
67
                          "MBB starts."),
 
68
                 cl::init(false), cl::Hidden);
 
69
 
 
70
static cl::opt<bool>
 
71
useFancyVerticals("rmf-fancy-verts",
 
72
                  cl::desc("Use SVG for vertical text."),
 
73
                  cl::init(true), cl::Hidden);
 
74
 
 
75
static cl::opt<bool>
 
76
prettyHTML("rmf-pretty-html",
 
77
           cl::desc("Pretty print HTML. For debugging the renderer only.."),
 
78
           cl::init(false), cl::Hidden);
 
79
 
 
80
 
 
81
namespace llvm {
 
82
 
 
83
  bool MFRenderingOptions::renderingOptionsProcessed;
 
84
  std::set<std::string> MFRenderingOptions::mfNamesToRender;
 
85
  bool MFRenderingOptions::renderAllMFs = false;
 
86
 
 
87
  std::set<std::string> MFRenderingOptions::classNamesToRender;
 
88
  bool MFRenderingOptions::renderAllClasses = false;
 
89
 
 
90
  std::set<std::pair<unsigned, unsigned> >
 
91
    MFRenderingOptions::intervalNumsToRender;
 
92
  unsigned MFRenderingOptions::intervalTypesToRender = ExplicitOnly;
 
93
 
 
94
  template <typename OutputItr>
 
95
  void MFRenderingOptions::splitComaSeperatedList(const std::string &s,
 
96
                                                         OutputItr outItr) {
 
97
    std::string::const_iterator curPos = s.begin();
 
98
    std::string::const_iterator nextComa = std::find(curPos, s.end(), ',');
 
99
    while (nextComa != s.end()) {
 
100
      std::string elem;
 
101
      std::copy(curPos, nextComa, std::back_inserter(elem));
 
102
      *outItr = elem;
 
103
      ++outItr;
 
104
      curPos = llvm::next(nextComa);
 
105
      nextComa = std::find(curPos, s.end(), ',');
 
106
    }
 
107
 
 
108
    if (curPos != s.end()) {
 
109
      std::string elem;
 
110
      std::copy(curPos, s.end(), std::back_inserter(elem));
 
111
      *outItr = elem;
 
112
      ++outItr;
 
113
    }
 
114
  }
 
115
 
 
116
  void MFRenderingOptions::processOptions() {
 
117
    if (!renderingOptionsProcessed) {
 
118
      processFuncNames();
 
119
      processRegClassNames();
 
120
      processIntervalNumbers();
 
121
      renderingOptionsProcessed = true;
 
122
    }
 
123
  }
 
124
 
 
125
  void MFRenderingOptions::processFuncNames() {
 
126
    if (machineFuncsToRender == "*") {
 
127
      renderAllMFs = true;
 
128
    } else {
 
129
      splitComaSeperatedList(machineFuncsToRender,
 
130
                             std::inserter(mfNamesToRender,
 
131
                                           mfNamesToRender.begin()));
 
132
    }
 
133
  }
 
134
 
 
135
  void MFRenderingOptions::processRegClassNames() {
 
136
    if (pressureClasses == "*") {
 
137
      renderAllClasses = true;
 
138
    } else {
 
139
      splitComaSeperatedList(pressureClasses,
 
140
                             std::inserter(classNamesToRender,
 
141
                                           classNamesToRender.begin()));
 
142
    }
 
143
  }
 
144
 
 
145
  void MFRenderingOptions::processIntervalNumbers() {
 
146
    std::set<std::string> intervalRanges;
 
147
    splitComaSeperatedList(showIntervals,
 
148
                           std::inserter(intervalRanges,
 
149
                                         intervalRanges.begin()));
 
150
    std::for_each(intervalRanges.begin(), intervalRanges.end(),
 
151
                  processIntervalRange);
 
152
  }
 
153
 
 
154
  void MFRenderingOptions::processIntervalRange(
 
155
                                          const std::string &intervalRangeStr) {
 
156
    if (intervalRangeStr == "*") {
 
157
      intervalTypesToRender |= All;
 
158
    } else if (intervalRangeStr == "virt-nospills*") {
 
159
      intervalTypesToRender |= VirtNoSpills;
 
160
    } else if (intervalRangeStr == "spills*") {
 
161
      intervalTypesToRender |= VirtSpills;
 
162
    } else if (intervalRangeStr == "virt*") {
 
163
      intervalTypesToRender |= AllVirt;
 
164
    } else if (intervalRangeStr == "phys*") {
 
165
      intervalTypesToRender |= AllPhys;
 
166
    } else {
 
167
      std::istringstream iss(intervalRangeStr);
 
168
      unsigned reg1, reg2;
 
169
      if ((iss >> reg1 >> std::ws)) {
 
170
        if (iss.eof()) {
 
171
          intervalNumsToRender.insert(std::make_pair(reg1, reg1 + 1));
 
172
        } else {
 
173
          char c;
 
174
          iss >> c;
 
175
          if (c == '-' && (iss >> reg2)) {
 
176
            intervalNumsToRender.insert(std::make_pair(reg1, reg2 + 1));
 
177
          } else {
 
178
            dbgs() << "Warning: Invalid interval range \""
 
179
                   << intervalRangeStr << "\" in -rmf-intervals. Skipping.\n";
 
180
          }
 
181
        }
 
182
      } else {
 
183
        dbgs() << "Warning: Invalid interval number \""
 
184
               << intervalRangeStr << "\" in -rmf-intervals. Skipping.\n";
 
185
      }
 
186
    }
 
187
  }
 
188
 
 
189
  void MFRenderingOptions::setup(MachineFunction *mf,
 
190
                                 const TargetRegisterInfo *tri,
 
191
                                 LiveIntervals *lis,
 
192
                                 const RenderMachineFunction *rmf) {
 
193
    this->mf = mf;
 
194
    this->tri = tri;
 
195
    this->lis = lis;
 
196
    this->rmf = rmf;
 
197
 
 
198
    clear();
 
199
  }
 
200
 
 
201
  void MFRenderingOptions::clear() {
 
202
    regClassesTranslatedToCurrentFunction = false;
 
203
    regClassSet.clear();
 
204
 
 
205
    intervalsTranslatedToCurrentFunction = false;
 
206
    intervalSet.clear();
 
207
  }
 
208
 
 
209
  void MFRenderingOptions::resetRenderSpecificOptions() {
 
210
    intervalSet.clear();
 
211
    intervalsTranslatedToCurrentFunction = false;
 
212
  }
 
213
 
 
214
  bool MFRenderingOptions::shouldRenderCurrentMachineFunction() const {
 
215
    processOptions();
 
216
 
 
217
    return (renderAllMFs ||
 
218
            mfNamesToRender.find(mf->getFunction()->getName()) !=
 
219
              mfNamesToRender.end());    
 
220
  }
 
221
 
 
222
  const MFRenderingOptions::RegClassSet& MFRenderingOptions::regClasses() const{
 
223
    translateRegClassNamesToCurrentFunction();
 
224
    return regClassSet;
 
225
  }
 
226
 
 
227
  const MFRenderingOptions::IntervalSet& MFRenderingOptions::intervals() const {
 
228
    translateIntervalNumbersToCurrentFunction();
 
229
    return intervalSet;
 
230
  }
 
231
 
 
232
  bool MFRenderingOptions::renderEmptyIndexes() const {
 
233
    return showEmptyIndexes;
 
234
  }
 
235
 
 
236
  bool MFRenderingOptions::fancyVerticals() const {
 
237
    return useFancyVerticals;
 
238
  }
 
239
 
 
240
  void MFRenderingOptions::translateRegClassNamesToCurrentFunction() const {
 
241
    if (!regClassesTranslatedToCurrentFunction) {
 
242
      processOptions();
 
243
      for (TargetRegisterInfo::regclass_iterator rcItr = tri->regclass_begin(),
 
244
                                                 rcEnd = tri->regclass_end();
 
245
           rcItr != rcEnd; ++rcItr) {
 
246
        const TargetRegisterClass *trc = *rcItr;
 
247
        if (renderAllClasses ||
 
248
            classNamesToRender.find(trc->getName()) !=
 
249
              classNamesToRender.end()) {
 
250
          regClassSet.insert(trc);
 
251
        }
 
252
      }
 
253
      regClassesTranslatedToCurrentFunction = true;
 
254
    }
 
255
  }
 
256
 
 
257
  void MFRenderingOptions::translateIntervalNumbersToCurrentFunction() const {
 
258
    if (!intervalsTranslatedToCurrentFunction) {
 
259
      processOptions();
 
260
 
 
261
      // If we're not just doing explicit then do a copy over all matching
 
262
      // types.
 
263
      if (intervalTypesToRender != ExplicitOnly) {
 
264
        for (LiveIntervals::iterator liItr = lis->begin(), liEnd = lis->end();
 
265
             liItr != liEnd; ++liItr) {
 
266
          LiveInterval *li = liItr->second;
 
267
 
 
268
          if (filterEmpty && li->empty())
 
269
            continue;
 
270
 
 
271
          if ((TargetRegisterInfo::isPhysicalRegister(li->reg) &&
 
272
               (intervalTypesToRender & AllPhys))) {
 
273
            intervalSet.insert(li);
 
274
          } else if (TargetRegisterInfo::isVirtualRegister(li->reg)) {
 
275
            if (((intervalTypesToRender & VirtNoSpills) && !rmf->isSpill(li)) || 
 
276
                ((intervalTypesToRender & VirtSpills) && rmf->isSpill(li))) {
 
277
              intervalSet.insert(li);
 
278
            }
 
279
          }
 
280
        }
 
281
      }
 
282
 
 
283
      // If we need to process the explicit list...
 
284
      if (intervalTypesToRender != All) {
 
285
        for (std::set<std::pair<unsigned, unsigned> >::const_iterator
 
286
               regRangeItr = intervalNumsToRender.begin(),
 
287
               regRangeEnd = intervalNumsToRender.end();
 
288
             regRangeItr != regRangeEnd; ++regRangeItr) {
 
289
          const std::pair<unsigned, unsigned> &range = *regRangeItr;
 
290
          for (unsigned reg = range.first; reg != range.second; ++reg) {
 
291
            if (lis->hasInterval(reg)) {
 
292
              intervalSet.insert(&lis->getInterval(reg));
 
293
            }
 
294
          }
 
295
        }
 
296
      }
 
297
 
 
298
      intervalsTranslatedToCurrentFunction = true;
 
299
    }
 
300
  }
 
301
 
 
302
  // ---------- TargetRegisterExtraInformation implementation ----------
 
303
 
 
304
  TargetRegisterExtraInfo::TargetRegisterExtraInfo()
 
305
    : mapsPopulated(false) {
 
306
  }
 
307
 
 
308
  void TargetRegisterExtraInfo::setup(MachineFunction *mf,
 
309
                                      MachineRegisterInfo *mri,
 
310
                                      const TargetRegisterInfo *tri,
 
311
                                      LiveIntervals *lis) {
 
312
    this->mf = mf;
 
313
    this->mri = mri;
 
314
    this->tri = tri;
 
315
    this->lis = lis;
 
316
  }
 
317
 
 
318
  void TargetRegisterExtraInfo::reset() {
 
319
    if (!mapsPopulated) {
 
320
      initWorst();
 
321
      //initBounds();
 
322
      initCapacity();
 
323
      mapsPopulated = true;
 
324
    }
 
325
 
 
326
    resetPressureAndLiveStates();
 
327
  }
 
328
 
 
329
  void TargetRegisterExtraInfo::clear() {
 
330
    prWorst.clear();
 
331
    vrWorst.clear();
 
332
    capacityMap.clear();
 
333
    pressureMap.clear();
 
334
    //liveStatesMap.clear();
 
335
    mapsPopulated = false;
 
336
  }
 
337
 
 
338
  void TargetRegisterExtraInfo::initWorst() {
 
339
    assert(!mapsPopulated && prWorst.empty() && vrWorst.empty() &&
 
340
           "Worst map already initialised?");
 
341
 
 
342
    // Start with the physical registers.
 
343
    for (unsigned preg = 1; preg < tri->getNumRegs(); ++preg) {
 
344
      WorstMapLine &pregLine = prWorst[preg];
 
345
 
 
346
      for (TargetRegisterInfo::regclass_iterator rcItr = tri->regclass_begin(),
 
347
                                                 rcEnd = tri->regclass_end();
 
348
           rcItr != rcEnd; ++rcItr) {
 
349
        const TargetRegisterClass *trc = *rcItr;
 
350
 
 
351
        unsigned numOverlaps = 0;
 
352
        for (TargetRegisterClass::iterator rItr = trc->begin(),
 
353
                                           rEnd = trc->end();
 
354
             rItr != rEnd; ++rItr) {
 
355
          unsigned trcPReg = *rItr;
 
356
          if (tri->regsOverlap(preg, trcPReg))
 
357
            ++numOverlaps;
 
358
        }
 
359
        
 
360
        pregLine[trc] = numOverlaps;
 
361
      }
 
362
    }
 
363
 
 
364
    // Now the register classes.
 
365
    for (TargetRegisterInfo::regclass_iterator rc1Itr = tri->regclass_begin(),
 
366
                                               rcEnd = tri->regclass_end();
 
367
         rc1Itr != rcEnd; ++rc1Itr) {
 
368
      const TargetRegisterClass *trc1 = *rc1Itr;
 
369
      WorstMapLine &classLine = vrWorst[trc1];
 
370
 
 
371
      for (TargetRegisterInfo::regclass_iterator rc2Itr = tri->regclass_begin();
 
372
           rc2Itr != rcEnd; ++rc2Itr) {
 
373
        const TargetRegisterClass *trc2 = *rc2Itr;
 
374
 
 
375
        unsigned worst = 0;
 
376
 
 
377
        for (TargetRegisterClass::iterator trc1Itr = trc1->begin(),
 
378
                                           trc1End = trc1->end();
 
379
             trc1Itr != trc1End; ++trc1Itr) {
 
380
          unsigned trc1Reg = *trc1Itr;
 
381
          unsigned trc1RegWorst = 0;
 
382
 
 
383
          for (TargetRegisterClass::iterator trc2Itr = trc2->begin(),
 
384
                                             trc2End = trc2->end();
 
385
               trc2Itr != trc2End; ++trc2Itr) {
 
386
            unsigned trc2Reg = *trc2Itr;
 
387
            if (tri->regsOverlap(trc1Reg, trc2Reg))
 
388
              ++trc1RegWorst;
 
389
          }
 
390
          if (trc1RegWorst > worst) {
 
391
            worst = trc1RegWorst;
 
392
          }    
 
393
        }
 
394
 
 
395
        if (worst != 0) {
 
396
          classLine[trc2] = worst;
 
397
        }
 
398
      }
 
399
    }
 
400
  }
 
401
 
 
402
  unsigned TargetRegisterExtraInfo::getWorst(
 
403
                                        unsigned reg,
 
404
                                        const TargetRegisterClass *trc) const {
 
405
    const WorstMapLine *wml = 0;
 
406
    if (TargetRegisterInfo::isPhysicalRegister(reg)) {
 
407
      PRWorstMap::const_iterator prwItr = prWorst.find(reg);
 
408
      assert(prwItr != prWorst.end() && "Missing prWorst entry.");
 
409
      wml = &prwItr->second;
 
410
    } else {
 
411
      const TargetRegisterClass *regTRC = mri->getRegClass(reg);
 
412
      VRWorstMap::const_iterator vrwItr = vrWorst.find(regTRC);
 
413
      assert(vrwItr != vrWorst.end() && "Missing vrWorst entry.");
 
414
      wml = &vrwItr->second;
 
415
    }
 
416
    
 
417
    WorstMapLine::const_iterator wmlItr = wml->find(trc);
 
418
    if (wmlItr == wml->end())
 
419
      return 0;
 
420
 
 
421
    return wmlItr->second;
 
422
  }
 
423
 
 
424
  void TargetRegisterExtraInfo::initCapacity() {
 
425
    assert(!mapsPopulated && capacityMap.empty() &&
 
426
           "Capacity map already initialised?");
 
427
 
 
428
    for (TargetRegisterInfo::regclass_iterator rcItr = tri->regclass_begin(),
 
429
           rcEnd = tri->regclass_end();
 
430
         rcItr != rcEnd; ++rcItr) {
 
431
      const TargetRegisterClass *trc = *rcItr;
 
432
      unsigned capacity = std::distance(trc->allocation_order_begin(*mf),
 
433
                                        trc->allocation_order_end(*mf));
 
434
 
 
435
      if (capacity != 0)
 
436
        capacityMap[trc] = capacity;
 
437
    }
 
438
  }
 
439
 
 
440
  unsigned TargetRegisterExtraInfo::getCapacity(
 
441
                                         const TargetRegisterClass *trc) const {
 
442
    CapacityMap::const_iterator cmItr = capacityMap.find(trc);
 
443
    assert(cmItr != capacityMap.end() &&
 
444
           "vreg with unallocable register class");
 
445
    return cmItr->second;
 
446
  }
 
447
 
 
448
  void TargetRegisterExtraInfo::resetPressureAndLiveStates() {
 
449
    pressureMap.clear();
 
450
    //liveStatesMap.clear();
 
451
 
 
452
    // Iterate over all slots.
 
453
    
 
454
 
 
455
    // Iterate over all live intervals.
 
456
    for (LiveIntervals::iterator liItr = lis->begin(),
 
457
           liEnd = lis->end();
 
458
         liItr != liEnd; ++liItr) {
 
459
      LiveInterval *li = liItr->second;
 
460
 
 
461
      const TargetRegisterClass *liTRC;
 
462
 
 
463
      if (TargetRegisterInfo::isPhysicalRegister(li->reg))
 
464
        continue;
 
465
      
 
466
      liTRC = mri->getRegClass(li->reg);
 
467
     
 
468
 
 
469
      // For all ranges in the current interal.
 
470
      for (LiveInterval::iterator lrItr = li->begin(),
 
471
             lrEnd = li->end();
 
472
           lrItr != lrEnd; ++lrItr) {
 
473
        LiveRange *lr = &*lrItr;
 
474
        
 
475
        // For all slots in the current range.
 
476
        for (SlotIndex i = lr->start; i != lr->end; i = i.getNextSlot()) {
 
477
 
 
478
          // Record increased pressure at index for all overlapping classes.
 
479
          for (TargetRegisterInfo::regclass_iterator
 
480
                 rcItr = tri->regclass_begin(),
 
481
                 rcEnd = tri->regclass_end();
 
482
               rcItr != rcEnd; ++rcItr) {
 
483
            const TargetRegisterClass *trc = *rcItr;
 
484
 
 
485
            if (trc->allocation_order_begin(*mf) ==
 
486
                trc->allocation_order_end(*mf))
 
487
              continue;
 
488
 
 
489
            unsigned worstAtI = getWorst(li->reg, trc);
 
490
 
 
491
            if (worstAtI != 0) {
 
492
              pressureMap[i][trc] += worstAtI;
 
493
            }
 
494
          }
 
495
        }
 
496
      }
 
497
    } 
 
498
  }
 
499
 
 
500
  unsigned TargetRegisterExtraInfo::getPressureAtSlot(
 
501
                                                 const TargetRegisterClass *trc,
 
502
                                                 SlotIndex i) const {
 
503
    PressureMap::const_iterator pmItr = pressureMap.find(i);
 
504
    if (pmItr == pressureMap.end())
 
505
      return 0;
 
506
    const PressureMapLine &pmLine = pmItr->second;
 
507
    PressureMapLine::const_iterator pmlItr = pmLine.find(trc);
 
508
    if (pmlItr == pmLine.end())
 
509
      return 0;
 
510
    return pmlItr->second;
 
511
  }
 
512
 
 
513
  bool TargetRegisterExtraInfo::classOverCapacityAtSlot(
 
514
                                                 const TargetRegisterClass *trc,
 
515
                                                 SlotIndex i) const {
 
516
    return (getPressureAtSlot(trc, i) > getCapacity(trc));
 
517
  }
 
518
 
 
519
  // ---------- MachineFunctionRenderer implementation ----------
 
520
 
 
521
  void RenderMachineFunction::Spacer::print(raw_ostream &os) const {
 
522
    if (!prettyHTML)
 
523
      return;
 
524
    for (unsigned i = 0; i < ns; ++i) {
 
525
      os << " ";
 
526
    }
 
527
  }
 
528
 
 
529
  RenderMachineFunction::Spacer RenderMachineFunction::s(unsigned ns) const {
 
530
    return Spacer(ns);
 
531
  }
 
532
 
 
533
  raw_ostream& operator<<(raw_ostream &os, const RenderMachineFunction::Spacer &s) {
 
534
    s.print(os);
 
535
    return os;
 
536
  }
 
537
 
 
538
  template <typename Iterator>
 
539
  std::string RenderMachineFunction::escapeChars(Iterator sBegin, Iterator sEnd) const {
 
540
    std::string r;
 
541
 
 
542
    for (Iterator sItr = sBegin; sItr != sEnd; ++sItr) {
 
543
      char c = *sItr;
 
544
 
 
545
      switch (c) {
 
546
        case '<': r.append("&lt;"); break;
 
547
        case '>': r.append("&gt;"); break;
 
548
        case '&': r.append("&amp;"); break;
 
549
        case ' ': r.append("&nbsp;"); break;
 
550
        case '\"': r.append("&quot;"); break;
 
551
        default: r.push_back(c); break;
 
552
      }
 
553
    }
 
554
 
 
555
    return r;
 
556
  }
 
557
 
 
558
  RenderMachineFunction::LiveState
 
559
  RenderMachineFunction::getLiveStateAt(const LiveInterval *li,
 
560
                                        SlotIndex i) const {
 
561
    const MachineInstr *mi = sis->getInstructionFromIndex(i);
 
562
 
 
563
    // For uses/defs recorded use/def indexes override current liveness and
 
564
    // instruction operands (Only for the interval which records the indexes).
 
565
    if (i.isUse() || i.isDef()) {
 
566
      UseDefs::const_iterator udItr = useDefs.find(li);
 
567
      if (udItr != useDefs.end()) {
 
568
        const SlotSet &slotSet = udItr->second;
 
569
        if (slotSet.count(i)) {
 
570
          if (i.isUse()) {
 
571
            return Used;
 
572
          }
 
573
          // else
 
574
          return Defined;
 
575
        }
 
576
      }
 
577
    }
 
578
 
 
579
    // If the slot is a load/store, or there's no info in the use/def set then
 
580
    // use liveness and instruction operand info.
 
581
    if (li->liveAt(i)) {
 
582
 
 
583
      if (mi == 0) {
 
584
        if (vrm == 0 || 
 
585
            (vrm->getStackSlot(li->reg) == VirtRegMap::NO_STACK_SLOT)) {
 
586
          return AliveReg;
 
587
        } else {
 
588
          return AliveStack;
 
589
        }
 
590
      } else {
 
591
        if (i.isDef() && mi->definesRegister(li->reg, tri)) {
 
592
          return Defined;
 
593
        } else if (i.isUse() && mi->readsRegister(li->reg)) {
 
594
          return Used;
 
595
        } else {
 
596
          if (vrm == 0 || 
 
597
              (vrm->getStackSlot(li->reg) == VirtRegMap::NO_STACK_SLOT)) {
 
598
            return AliveReg;
 
599
          } else {
 
600
            return AliveStack;
 
601
          }
 
602
        }
 
603
      }
 
604
    }
 
605
    return Dead;
 
606
  }
 
607
 
 
608
  RenderMachineFunction::PressureState
 
609
  RenderMachineFunction::getPressureStateAt(const TargetRegisterClass *trc,
 
610
                                              SlotIndex i) const {
 
611
    if (trei.getPressureAtSlot(trc, i) == 0) {
 
612
      return Zero;
 
613
    } else if (trei.classOverCapacityAtSlot(trc, i)){
 
614
      return High;
 
615
    }
 
616
    return Low;
 
617
  }
 
618
 
 
619
  /// \brief Render a machine instruction.
 
620
  void RenderMachineFunction::renderMachineInstr(raw_ostream &os,
 
621
                                                 const MachineInstr *mi) const {
 
622
    std::string s;
 
623
    raw_string_ostream oss(s);
 
624
    oss << *mi;
 
625
 
 
626
    os << escapeChars(oss.str());
 
627
  }
 
628
 
 
629
  template <typename T>
 
630
  void RenderMachineFunction::renderVertical(const Spacer &indent,
 
631
                                             raw_ostream &os,
 
632
                                             const T &t) const {
 
633
    if (ro.fancyVerticals()) {
 
634
      os << indent << "<object\n"
 
635
         << indent + s(2) << "class=\"obj\"\n"
 
636
         << indent + s(2) << "type=\"image/svg+xml\"\n"
 
637
         << indent + s(2) << "width=\"14px\"\n"
 
638
         << indent + s(2) << "height=\"55px\"\n"
 
639
         << indent + s(2) << "data=\"data:image/svg+xml,\n"
 
640
         << indent + s(4) << "<svg xmlns='http://www.w3.org/2000/svg'>\n"
 
641
         << indent + s(6) << "<text x='-55' y='10' "
 
642
                             "font-family='Courier' font-size='12' "
 
643
                             "transform='rotate(-90)' "
 
644
                             "text-rendering='optimizeSpeed' "
 
645
                             "fill='#000'>" << t << "</text>\n"
 
646
         << indent + s(4) << "</svg>\">\n"
 
647
         << indent << "</object>\n";
 
648
    } else {
 
649
      std::ostringstream oss;
 
650
      oss << t;
 
651
      std::string tStr(oss.str());
 
652
 
 
653
      os << indent;
 
654
      for (std::string::iterator tStrItr = tStr.begin(), tStrEnd = tStr.end();
 
655
           tStrItr != tStrEnd; ++tStrItr) {
 
656
        os << *tStrItr << "<br/>";
 
657
      }
 
658
      os << "\n";
 
659
    }
 
660
  }
 
661
 
 
662
  void RenderMachineFunction::insertCSS(const Spacer &indent,
 
663
                                        raw_ostream &os) const {
 
664
    os << indent << "<style type=\"text/css\">\n"
 
665
       << indent + s(2) << "body { font-color: black; }\n"
 
666
       << indent + s(2) << "table.code td { font-family: monospace; "
 
667
                    "border-width: 0px; border-style: solid; "
 
668
                    "border-bottom: 1px solid #dddddd; white-space: nowrap; }\n"
 
669
       << indent + s(2) << "table.code td.p-z { background-color: #000000; }\n"
 
670
       << indent + s(2) << "table.code td.p-l { background-color: #00ff00; }\n"
 
671
       << indent + s(2) << "table.code td.p-h { background-color: #ff0000; }\n"
 
672
       << indent + s(2) << "table.code td.l-n { background-color: #ffffff; }\n"
 
673
       << indent + s(2) << "table.code td.l-d { background-color: #ff0000; }\n"
 
674
       << indent + s(2) << "table.code td.l-u { background-color: #ffff00; }\n"
 
675
       << indent + s(2) << "table.code td.l-r { background-color: #000000; }\n"
 
676
       << indent + s(2) << "table.code td.l-s { background-color: #770000; }\n"
 
677
       << indent + s(2) << "table.code th { border-width: 0px; "
 
678
                    "border-style: solid; }\n"
 
679
       << indent << "</style>\n";
 
680
  }
 
681
 
 
682
  void RenderMachineFunction::renderFunctionSummary(
 
683
                                    const Spacer &indent, raw_ostream &os,
 
684
                                    const char * const renderContextStr) const {
 
685
    os << indent << "<h1>Function: " << mf->getFunction()->getName()
 
686
                 << "</h1>\n"
 
687
       << indent << "<h2>Rendering context: " << renderContextStr << "</h2>\n";
 
688
  }
 
689
 
 
690
 
 
691
  void RenderMachineFunction::renderPressureTableLegend(
 
692
                                                      const Spacer &indent,
 
693
                                                      raw_ostream &os) const {
 
694
    os << indent << "<h2>Rendering Pressure Legend:</h2>\n"
 
695
       << indent << "<table class=\"code\">\n"
 
696
       << indent + s(2) << "<tr>\n"
 
697
       << indent + s(4) << "<th>Pressure</th><th>Description</th>"
 
698
                    "<th>Appearance</th>\n"
 
699
       << indent + s(2) << "</tr>\n"
 
700
       << indent + s(2) << "<tr>\n"
 
701
       << indent + s(4) << "<td>No Pressure</td>"
 
702
                    "<td>No physical registers of this class requested.</td>"
 
703
                    "<td class=\"p-z\">&nbsp;&nbsp;</td>\n"
 
704
       << indent + s(2) << "</tr>\n"
 
705
       << indent + s(2) << "<tr>\n"
 
706
       << indent + s(4) << "<td>Low Pressure</td>"
 
707
                    "<td>Sufficient physical registers to meet demand.</td>"
 
708
                    "<td class=\"p-l\">&nbsp;&nbsp;</td>\n"
 
709
       << indent + s(2) << "</tr>\n"
 
710
       << indent + s(2) << "<tr>\n"
 
711
       << indent + s(4) << "<td>High Pressure</td>"
 
712
                    "<td>Potentially insufficient physical registers to meet demand.</td>"
 
713
                    "<td class=\"p-h\">&nbsp;&nbsp;</td>\n"
 
714
       << indent + s(2) << "</tr>\n"
 
715
       << indent << "</table>\n";
 
716
  }
 
717
 
 
718
  template <typename CellType>
 
719
  void RenderMachineFunction::renderCellsWithRLE(
 
720
                   const Spacer &indent, raw_ostream &os,
 
721
                   const std::pair<CellType, unsigned> &rleAccumulator,
 
722
                   const std::map<CellType, std::string> &cellTypeStrs) const {
 
723
 
 
724
    if (rleAccumulator.second == 0)
 
725
      return; 
 
726
 
 
727
    typename std::map<CellType, std::string>::const_iterator ctsItr =
 
728
      cellTypeStrs.find(rleAccumulator.first);
 
729
 
 
730
    assert(ctsItr != cellTypeStrs.end() && "No string for given cell type.");
 
731
 
 
732
    os << indent + s(4) << "<td class=\"" << ctsItr->second << "\"";
 
733
    if (rleAccumulator.second > 1)
 
734
      os << " colspan=" << rleAccumulator.second;
 
735
    os << "></td>\n";
 
736
  }
 
737
 
 
738
 
 
739
  void RenderMachineFunction::renderCodeTablePlusPI(const Spacer &indent,
 
740
                                                    raw_ostream &os) const {
 
741
 
 
742
    std::map<LiveState, std::string> lsStrs;
 
743
    lsStrs[Dead] = "l-n";
 
744
    lsStrs[Defined] = "l-d";
 
745
    lsStrs[Used] = "l-u";
 
746
    lsStrs[AliveReg] = "l-r";
 
747
    lsStrs[AliveStack] = "l-s";
 
748
 
 
749
    std::map<PressureState, std::string> psStrs;
 
750
    psStrs[Zero] = "p-z";
 
751
    psStrs[Low] = "p-l";
 
752
    psStrs[High] = "p-h";
 
753
 
 
754
    // Open the table... 
 
755
 
 
756
    os << indent << "<table cellpadding=0 cellspacing=0 class=\"code\">\n"
 
757
       << indent + s(2) << "<tr>\n";
 
758
 
 
759
    // Render the header row...
 
760
 
 
761
    os << indent + s(4) << "<th>index</th>\n"
 
762
       << indent + s(4) << "<th>instr</th>\n";
 
763
 
 
764
    // Render class names if necessary...
 
765
    if (!ro.regClasses().empty()) {
 
766
      for (MFRenderingOptions::RegClassSet::const_iterator
 
767
             rcItr = ro.regClasses().begin(),
 
768
             rcEnd = ro.regClasses().end();
 
769
           rcItr != rcEnd; ++rcItr) {
 
770
        const TargetRegisterClass *trc = *rcItr;
 
771
        os << indent + s(4) << "<th>\n";
 
772
        renderVertical(indent + s(6), os, trc->getName());
 
773
        os << indent + s(4) << "</th>\n";
 
774
      }
 
775
    }
 
776
 
 
777
    // FIXME: Is there a nicer way to insert space between columns in HTML?
 
778
    if (!ro.regClasses().empty() && !ro.intervals().empty())
 
779
      os << indent + s(4) << "<th>&nbsp;&nbsp;</th>\n";
 
780
 
 
781
    // Render interval numbers if necessary...
 
782
    if (!ro.intervals().empty()) {
 
783
      for (MFRenderingOptions::IntervalSet::const_iterator
 
784
             liItr = ro.intervals().begin(),
 
785
             liEnd = ro.intervals().end();
 
786
           liItr != liEnd; ++liItr) {
 
787
 
 
788
        const LiveInterval *li = *liItr;
 
789
        os << indent + s(4) << "<th>\n";
 
790
        renderVertical(indent + s(6), os, li->reg);
 
791
        os << indent + s(4) << "</th>\n";
 
792
      }
 
793
    }
 
794
 
 
795
    os << indent + s(2) << "</tr>\n";
 
796
 
 
797
    // End header row, start with the data rows...
 
798
 
 
799
    MachineInstr *mi = 0;
 
800
 
 
801
    // Data rows:
 
802
    for (SlotIndex i = sis->getZeroIndex(); i != sis->getLastIndex();
 
803
         i = i.getNextSlot()) {
 
804
     
 
805
      // Render the slot column. 
 
806
      os << indent + s(2) << "<tr height=6ex>\n";
 
807
      
 
808
      // Render the code column.
 
809
      if (i.isLoad()) {
 
810
        MachineBasicBlock *mbb = sis->getMBBFromIndex(i);
 
811
        mi = sis->getInstructionFromIndex(i);
 
812
 
 
813
        if (i == sis->getMBBStartIdx(mbb) || mi != 0 ||
 
814
            ro.renderEmptyIndexes()) {
 
815
          os << indent + s(4) << "<td rowspan=4>" << i << "&nbsp;</td>\n"
 
816
             << indent + s(4) << "<td rowspan=4>\n";
 
817
 
 
818
          if (i == sis->getMBBStartIdx(mbb)) {
 
819
            os << indent + s(6) << "BB#" << mbb->getNumber() << ":&nbsp;\n";
 
820
          } else if (mi != 0) {
 
821
            os << indent + s(6) << "&nbsp;&nbsp;";
 
822
            renderMachineInstr(os, mi);
 
823
          } else {
 
824
            // Empty interval - leave blank.
 
825
          }
 
826
          os << indent + s(4) << "</td>\n";
 
827
        } else {
 
828
          i = i.getStoreIndex(); // <- Will be incremented to the next index.
 
829
          continue;
 
830
        }
 
831
      }
 
832
 
 
833
      // Render the class columns.
 
834
      if (!ro.regClasses().empty()) {
 
835
        std::pair<PressureState, unsigned> psRLEAccumulator(Zero, 0);
 
836
        for (MFRenderingOptions::RegClassSet::const_iterator
 
837
               rcItr = ro.regClasses().begin(),
 
838
               rcEnd = ro.regClasses().end();
 
839
             rcItr != rcEnd; ++rcItr) {
 
840
          const TargetRegisterClass *trc = *rcItr;
 
841
          PressureState newPressure = getPressureStateAt(trc, i);
 
842
 
 
843
          if (newPressure == psRLEAccumulator.first) {
 
844
            ++psRLEAccumulator.second;
 
845
          } else {
 
846
            renderCellsWithRLE(indent + s(4), os, psRLEAccumulator, psStrs);
 
847
            psRLEAccumulator.first = newPressure;
 
848
            psRLEAccumulator.second = 1;
 
849
          }
 
850
        }
 
851
        renderCellsWithRLE(indent + s(4), os, psRLEAccumulator, psStrs);
 
852
      }
 
853
  
 
854
      // FIXME: Is there a nicer way to insert space between columns in HTML?
 
855
      if (!ro.regClasses().empty() && !ro.intervals().empty())
 
856
        os << indent + s(4) << "<td width=2em></td>\n";
 
857
 
 
858
      if (!ro.intervals().empty()) {
 
859
        std::pair<LiveState, unsigned> lsRLEAccumulator(Dead, 0);
 
860
        for (MFRenderingOptions::IntervalSet::const_iterator
 
861
               liItr = ro.intervals().begin(),
 
862
               liEnd = ro.intervals().end();
 
863
             liItr != liEnd; ++liItr) {
 
864
          const LiveInterval *li = *liItr;
 
865
          LiveState newLiveness = getLiveStateAt(li, i);
 
866
 
 
867
          if (newLiveness == lsRLEAccumulator.first) {
 
868
            ++lsRLEAccumulator.second;
 
869
          } else {
 
870
            renderCellsWithRLE(indent + s(4), os, lsRLEAccumulator, lsStrs);
 
871
            lsRLEAccumulator.first = newLiveness;
 
872
            lsRLEAccumulator.second = 1;
 
873
          }
 
874
        }
 
875
        renderCellsWithRLE(indent + s(4), os, lsRLEAccumulator, lsStrs);
 
876
      }
 
877
      os << indent + s(2) << "</tr>\n";
 
878
    }
 
879
 
 
880
    os << indent << "</table>\n";
 
881
 
 
882
    if (!ro.regClasses().empty())
 
883
      renderPressureTableLegend(indent, os);
 
884
  }
 
885
 
 
886
  void RenderMachineFunction::renderFunctionPage(
 
887
                                    raw_ostream &os,
 
888
                                    const char * const renderContextStr) const {
 
889
    os << "<html>\n"
 
890
       << s(2) << "<head>\n"
 
891
       << s(4) << "<title>" << fqn << "</title>\n";
 
892
 
 
893
    insertCSS(s(4), os);
 
894
 
 
895
    os << s(2) << "<head>\n"
 
896
       << s(2) << "<body >\n";
 
897
 
 
898
    renderFunctionSummary(s(4), os, renderContextStr);
 
899
 
 
900
    os << s(4) << "<br/><br/><br/>\n";
 
901
 
 
902
    //renderLiveIntervalInfoTable("    ", os);
 
903
 
 
904
    os << s(4) << "<br/><br/><br/>\n";
 
905
 
 
906
    renderCodeTablePlusPI(s(4), os);
 
907
 
 
908
    os << s(2) << "</body>\n"
 
909
       << "</html>\n";
 
910
  }
 
911
 
 
912
  void RenderMachineFunction::getAnalysisUsage(AnalysisUsage &au) const {
 
913
    au.addRequired<SlotIndexes>();
 
914
    au.addRequired<LiveIntervals>();
 
915
    au.setPreservesAll();
 
916
    MachineFunctionPass::getAnalysisUsage(au);
 
917
  }
 
918
 
 
919
  bool RenderMachineFunction::runOnMachineFunction(MachineFunction &fn) {
 
920
 
 
921
    mf = &fn;
 
922
    mri = &mf->getRegInfo();
 
923
    tri = mf->getTarget().getRegisterInfo();
 
924
    lis = &getAnalysis<LiveIntervals>();
 
925
    sis = &getAnalysis<SlotIndexes>();
 
926
 
 
927
    trei.setup(mf, mri, tri, lis);
 
928
    ro.setup(mf, tri, lis, this);
 
929
    spillIntervals.clear();
 
930
    spillFor.clear();
 
931
    useDefs.clear();
 
932
 
 
933
    fqn = mf->getFunction()->getParent()->getModuleIdentifier() + "." +
 
934
          mf->getFunction()->getName().str();
 
935
 
 
936
    return false;
 
937
  }
 
938
 
 
939
  void RenderMachineFunction::releaseMemory() {
 
940
    trei.clear();
 
941
    ro.clear();
 
942
    spillIntervals.clear();
 
943
    spillFor.clear();
 
944
    useDefs.clear();
 
945
  }
 
946
 
 
947
  void RenderMachineFunction::rememberUseDefs(const LiveInterval *li) {
 
948
 
 
949
    if (!ro.shouldRenderCurrentMachineFunction())
 
950
      return; 
 
951
 
 
952
    for (MachineRegisterInfo::reg_iterator rItr = mri->reg_begin(li->reg),
 
953
                                           rEnd = mri->reg_end();
 
954
         rItr != rEnd; ++rItr) {
 
955
      const MachineInstr *mi = &*rItr;
 
956
      if (mi->readsRegister(li->reg)) {
 
957
        useDefs[li].insert(lis->getInstructionIndex(mi).getUseIndex());
 
958
      }
 
959
      if (mi->definesRegister(li->reg)) {
 
960
        useDefs[li].insert(lis->getInstructionIndex(mi).getDefIndex());
 
961
      }
 
962
    }
 
963
  }
 
964
 
 
965
  void RenderMachineFunction::rememberSpills(
 
966
                                     const LiveInterval *li,
 
967
                                     const std::vector<LiveInterval*> &spills) {
 
968
 
 
969
    if (!ro.shouldRenderCurrentMachineFunction())
 
970
      return; 
 
971
 
 
972
    for (std::vector<LiveInterval*>::const_iterator siItr = spills.begin(),
 
973
                                                    siEnd = spills.end();
 
974
         siItr != siEnd; ++siItr) {
 
975
      const LiveInterval *spill = *siItr;
 
976
      spillIntervals[li].insert(spill);
 
977
      spillFor[spill] = li;
 
978
    }
 
979
  }
 
980
 
 
981
  bool RenderMachineFunction::isSpill(const LiveInterval *li) const {
 
982
    SpillForMap::const_iterator sfItr = spillFor.find(li);
 
983
    if (sfItr == spillFor.end())
 
984
      return false;
 
985
    return true;
 
986
  }
 
987
 
 
988
  void RenderMachineFunction::renderMachineFunction(
 
989
                                                   const char *renderContextStr,
 
990
                                                   const VirtRegMap *vrm,
 
991
                                                   const char *renderSuffix) {
 
992
    if (!ro.shouldRenderCurrentMachineFunction())
 
993
      return; 
 
994
 
 
995
    this->vrm = vrm;
 
996
    trei.reset();
 
997
 
 
998
    std::string rpFileName(mf->getFunction()->getName().str() +
 
999
                           (renderSuffix ? renderSuffix : "") +
 
1000
                           outputFileSuffix);
 
1001
 
 
1002
    std::string errMsg;
 
1003
    raw_fd_ostream outFile(rpFileName.c_str(), errMsg, raw_fd_ostream::F_Binary);
 
1004
 
 
1005
    renderFunctionPage(outFile, renderContextStr);
 
1006
 
 
1007
    ro.resetRenderSpecificOptions();
 
1008
  }
 
1009
 
 
1010
  std::string RenderMachineFunction::escapeChars(const std::string &s) const {
 
1011
    return escapeChars(s.begin(), s.end());
 
1012
  }
 
1013
 
 
1014
}