aboutsummaryrefslogtreecommitdiff
path: root/backend/lib/MC/MCCFI.cpp
blob: aa66e0f7131c797fcc6f6e952de507559b7b0811 (plain)
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
// SPDX-License-Identifier: GPL-3.0-or-later

#include "rcc/MC/MCCFI.h"

#include <cstddef>

namespace rcc::mc {

Expected<void> MCCFIInstruction::verify() const {
  std::size_t ExpectedOperands = 0;
  bool RequiresBytes = false;
  bool RequiresSymbol = false;

  switch (Operation) {
  case MCCFIOperation::StartProc:
  case MCCFIOperation::EndProc:
  case MCCFIOperation::Sections:
  case MCCFIOperation::SignalFrame:
  case MCCFIOperation::RememberState:
  case MCCFIOperation::RestoreState:
  case MCCFIOperation::WindowSave:
  case MCCFIOperation::NegateReturnAddressState:
  case MCCFIOperation::NegateReturnAddressStateWithPC:
    break;
  case MCCFIOperation::Personality:
  case MCCFIOperation::LSDA:
    ExpectedOperands = 1;
    RequiresSymbol = true;
    break;
  case MCCFIOperation::ReturnColumn:
  case MCCFIOperation::SameValue:
  case MCCFIOperation::DefCFARegister:
  case MCCFIOperation::DefCFAOffset:
  case MCCFIOperation::AdjustCFAOffset:
  case MCCFIOperation::Restore:
  case MCCFIOperation::Undefined:
  case MCCFIOperation::GNUArgsSize:
    ExpectedOperands = 1;
    break;
  case MCCFIOperation::Offset:
  case MCCFIOperation::DefCFA:
  case MCCFIOperation::RelativeOffset:
  case MCCFIOperation::Register:
  case MCCFIOperation::ValueOffset:
    ExpectedOperands = 2;
    break;
  case MCCFIOperation::Escape:
    RequiresBytes = true;
    break;
  case MCCFIOperation::Label:
    RequiresSymbol = true;
    break;
  }

  if (Operands.size() != ExpectedOperands)
    return makeUnexpected(ErrorCode::InvalidArgument, "MC CFI event has an invalid operand count");
  if (RequiresBytes != !Bytes.empty()) {
    return makeUnexpected(ErrorCode::InvalidArgument,
                          RequiresBytes ? "MC CFI escape event requires bytes"
                                        : "non-escape MC CFI event cannot contain bytes");
  }
  if (RequiresSymbol != static_cast<bool>(Symbol)) {
    return makeUnexpected(ErrorCode::InvalidArgument, RequiresSymbol
                                                          ? "MC CFI event requires a symbol"
                                                          : "MC CFI event cannot contain a symbol");
  }
  return {};
}

} // namespace rcc::mc