77
77
#include " llvm/Pass.h"
78
78
#include " llvm/Support/Casting.h"
79
79
#include " llvm/Support/ErrorHandling.h"
80
+ #include " llvm/Support/ManagedStatic.h"
80
81
#include " llvm/Support/MathExtras.h"
81
82
#include " llvm/Support/ModRef.h"
83
+ #include " llvm/Support/Mutex.h"
82
84
#include " llvm/Support/raw_ostream.h"
83
85
#include " llvm/Target/TargetMachine.h"
84
86
#include < algorithm>
@@ -93,21 +95,31 @@ using namespace llvm;
93
95
94
96
namespace {
95
97
98
+ // / Used the by the ReportedErrors class to guarantee only one error is reported
99
+ // / at one time.
100
+ static ManagedStatic<sys::SmartMutex<true >> ReportedErrorsLock;
101
+
96
102
struct MachineVerifier {
97
103
MachineVerifier (MachineFunctionAnalysisManager &MFAM, const char *b,
98
- raw_ostream *OS)
99
- : MFAM(&MFAM), OS(OS ? *OS : nulls()), Banner(b) {}
104
+ raw_ostream *OS, bool AbortOnError = true )
105
+ : MFAM(&MFAM), OS(OS ? *OS : nulls()), Banner(b),
106
+ ReportedErrs (AbortOnError) {}
100
107
101
- MachineVerifier (Pass *pass, const char *b, raw_ostream *OS)
102
- : PASS(pass), OS(OS ? *OS : nulls()), Banner(b) {}
108
+ MachineVerifier (Pass *pass, const char *b, raw_ostream *OS,
109
+ bool AbortOnError = true )
110
+ : PASS(pass), OS(OS ? *OS : nulls()), Banner(b),
111
+ ReportedErrs(AbortOnError) {}
103
112
104
113
MachineVerifier (const char *b, LiveVariables *LiveVars,
105
114
LiveIntervals *LiveInts, LiveStacks *LiveStks,
106
- SlotIndexes *Indexes, raw_ostream *OS)
115
+ SlotIndexes *Indexes, raw_ostream *OS,
116
+ bool AbortOnError = true )
107
117
: OS(OS ? *OS : nulls()), Banner(b), LiveVars(LiveVars),
108
- LiveInts (LiveInts), LiveStks(LiveStks), Indexes(Indexes) {}
118
+ LiveInts(LiveInts), LiveStks(LiveStks), Indexes(Indexes),
119
+ ReportedErrs(AbortOnError) {}
109
120
110
- unsigned verify (const MachineFunction &MF);
121
+ // / \returns true if no problems were found.
122
+ bool verify (const MachineFunction &MF);
111
123
112
124
MachineFunctionAnalysisManager *MFAM = nullptr ;
113
125
Pass *const PASS = nullptr ;
@@ -120,8 +132,6 @@ struct MachineVerifier {
120
132
const MachineRegisterInfo *MRI = nullptr ;
121
133
const RegisterBankInfo *RBI = nullptr ;
122
134
123
- unsigned foundErrors = 0 ;
124
-
125
135
// Avoid querying the MachineFunctionProperties for each operand.
126
136
bool isFunctionRegBankSelected = false ;
127
137
bool isFunctionSelected = false ;
@@ -231,6 +241,44 @@ struct MachineVerifier {
231
241
LiveStacks *LiveStks = nullptr ;
232
242
SlotIndexes *Indexes = nullptr ;
233
243
244
+ // / A class to track the number of reported error and to guarantee that only
245
+ // / one error is reported at one time.
246
+ class ReportedErrors {
247
+ unsigned NumReported = 0 ;
248
+ bool AbortOnError;
249
+
250
+ public:
251
+ // / \param AbortOnError -- If set, abort after printing the first error.
252
+ ReportedErrors (bool AbortOnError) : AbortOnError(AbortOnError) {}
253
+
254
+ ~ReportedErrors () {
255
+ if (!hasError ())
256
+ return ;
257
+ if (AbortOnError)
258
+ report_fatal_error (" Found " + Twine (NumReported) +
259
+ " machine code errors." );
260
+ // Since we haven't aborted, release the lock to allow other threads to
261
+ // report errors.
262
+ ReportedErrorsLock->unlock ();
263
+ }
264
+
265
+ // / Increment the number of reported errors.
266
+ // / \returns true if this is the first reported error.
267
+ bool increment () {
268
+ // If this is the first error this thread has encountered, grab the lock
269
+ // to prevent other threads from reporting errors at the same time.
270
+ // Otherwise we assume we already have the lock.
271
+ if (!hasError ())
272
+ ReportedErrorsLock->lock ();
273
+ ++NumReported;
274
+ return NumReported == 1 ;
275
+ }
276
+
277
+ // / \returns true if an error was reported.
278
+ bool hasError () { return NumReported; }
279
+ };
280
+ ReportedErrors ReportedErrs;
281
+
234
282
// This is calculated only when trying to verify convergence control tokens.
235
283
// Similar to the LLVM IR verifier, we calculate this locally instead of
236
284
// relying on the pass manager.
@@ -337,11 +385,7 @@ struct MachineVerifierLegacyPass : public MachineFunctionPass {
337
385
MachineFunctionProperties::Property::FailsVerification))
338
386
return false ;
339
387
340
- unsigned FoundErrors =
341
- MachineVerifier (this , Banner.c_str (), &errs ()).verify (MF);
342
- if (FoundErrors)
343
- report_fatal_error (" Found " + Twine (FoundErrors) +
344
- " machine code errors." );
388
+ MachineVerifier (this , Banner.c_str (), &errs ()).verify (MF);
345
389
return false ;
346
390
}
347
391
};
@@ -357,10 +401,7 @@ MachineVerifierPass::run(MachineFunction &MF,
357
401
if (MF.getProperties ().hasProperty (
358
402
MachineFunctionProperties::Property::FailsVerification))
359
403
return PreservedAnalyses::all ();
360
- unsigned FoundErrors =
361
- MachineVerifier (MFAM, Banner.c_str (), &errs ()).verify (MF);
362
- if (FoundErrors)
363
- report_fatal_error (" Found " + Twine (FoundErrors) + " machine code errors." );
404
+ MachineVerifier (MFAM, Banner.c_str (), &errs ()).verify (MF);
364
405
return PreservedAnalyses::all ();
365
406
}
366
407
@@ -380,31 +421,20 @@ void llvm::verifyMachineFunction(const std::string &Banner,
380
421
// LiveIntervals *LiveInts;
381
422
// LiveStacks *LiveStks;
382
423
// SlotIndexes *Indexes;
383
- unsigned FoundErrors =
384
- MachineVerifier (nullptr , Banner.c_str (), &errs ()).verify (MF);
385
- if (FoundErrors)
386
- report_fatal_error (" Found " + Twine (FoundErrors) + " machine code errors." );
424
+ MachineVerifier (nullptr , Banner.c_str (), &errs ()).verify (MF);
387
425
}
388
426
389
427
bool MachineFunction::verify (Pass *p, const char *Banner, raw_ostream *OS,
390
- bool AbortOnErrors) const {
391
- MachineFunction &MF = const_cast <MachineFunction&>(*this );
392
- unsigned FoundErrors = MachineVerifier (p, Banner, OS).verify (MF);
393
- if (AbortOnErrors && FoundErrors)
394
- report_fatal_error (" Found " +Twine (FoundErrors)+" machine code errors." );
395
- return FoundErrors == 0 ;
428
+ bool AbortOnError) const {
429
+ return MachineVerifier (p, Banner, OS, AbortOnError).verify (*this );
396
430
}
397
431
398
432
bool MachineFunction::verify (LiveIntervals *LiveInts, SlotIndexes *Indexes,
399
433
const char *Banner, raw_ostream *OS,
400
- bool AbortOnErrors) const {
401
- MachineFunction &MF = const_cast <MachineFunction &>(*this );
402
- unsigned FoundErrors =
403
- MachineVerifier (Banner, nullptr , LiveInts, nullptr , Indexes, OS)
404
- .verify (MF);
405
- if (AbortOnErrors && FoundErrors)
406
- report_fatal_error (" Found " + Twine (FoundErrors) + " machine code errors." );
407
- return FoundErrors == 0 ;
434
+ bool AbortOnError) const {
435
+ return MachineVerifier (Banner, /* LiveVars=*/ nullptr , LiveInts,
436
+ /* LiveStks=*/ nullptr , Indexes, OS, AbortOnError)
437
+ .verify (*this );
408
438
}
409
439
410
440
void MachineVerifier::verifySlotIndexes () const {
@@ -430,9 +460,7 @@ void MachineVerifier::verifyProperties(const MachineFunction &MF) {
430
460
report (" Function has NoVRegs property but there are VReg operands" , &MF);
431
461
}
432
462
433
- unsigned MachineVerifier::verify (const MachineFunction &MF) {
434
- foundErrors = 0 ;
435
-
463
+ bool MachineVerifier::verify (const MachineFunction &MF) {
436
464
this ->MF = &MF;
437
465
TM = &MF.getTarget ();
438
466
TII = MF.getSubtarget ().getInstrInfo ();
@@ -447,7 +475,7 @@ unsigned MachineVerifier::verify(const MachineFunction &MF) {
447
475
// it's expected that the MIR is somewhat broken but that's ok since we'll
448
476
// reset it and clear the FailedISel attribute in ResetMachineFunctions.
449
477
if (isFunctionFailedISel)
450
- return foundErrors ;
478
+ return true ;
451
479
452
480
isFunctionRegBankSelected = MF.getProperties ().hasProperty (
453
481
MachineFunctionProperties::Property::RegBankSelected);
@@ -544,13 +572,13 @@ unsigned MachineVerifier::verify(const MachineFunction &MF) {
544
572
regMasks.clear ();
545
573
MBBInfoMap.clear ();
546
574
547
- return foundErrors ;
575
+ return !ReportedErrs. hasError () ;
548
576
}
549
577
550
578
void MachineVerifier::report (const char *msg, const MachineFunction *MF) {
551
579
assert (MF);
552
580
OS << ' \n ' ;
553
- if (!foundErrors++ ) {
581
+ if (ReportedErrs. increment () ) {
554
582
if (Banner)
555
583
OS << " # " << Banner << ' \n ' ;
556
584
0 commit comments