aboutsummaryrefslogtreecommitdiff
path: root/backend/utils/TableGen/Common/CodeGenSchedule.cpp
blob: 56dbb5d7c580728a065fd4906e94a046b168ed3f (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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// SPDX-License-Identifier: GPL-3.0-or-later

#include "Common/CodeGenTarget.h"

#include <ranges>
#include <string>
#include <unordered_set>

namespace rcc::targetgen {

[[nodiscard]] bool CodeGenTarget::normalizeSchedulingClasses(NormalizedTargetModel &Result) {
  if (Input.SchedulingClasses.empty()) {
    fail(Input.Target.Range, "target description requires at least one scheduling class");
    return false;
  }
  std::unordered_set<std::uint32_t> IDs;
  std::unordered_set<std::string> Symbols;
  std::unordered_set<std::string> Names;
  for (const SourceSchedulingClass &Class : Input.SchedulingClasses) {
    if (Class.ID == 0 || !isIdentifier(Class.Symbol) || Class.Name.empty() || Class.MicroOps == 0 ||
        Class.Latency == 0 || !IDs.insert(Class.ID).second ||
        !Symbols.insert(Class.Symbol).second || !Names.insert(Class.Name).second) {
      fail(Class.Range,
           "scheduling classes require nonzero unique IDs, symbols, names, micro-op counts, "
           "and latencies");
      return false;
    }
    SchedulingClassBySymbol.emplace(Class.Symbol, Class.ID);
    Result.SchedulingClasses.push_back({
        .ID = Class.ID,
        .Symbol = Class.Symbol,
        .Name = Class.Name,
        .MicroOps = Class.MicroOps,
        .Latency = Class.Latency,
    });
  }
  return true;
}

[[nodiscard]] bool CodeGenTarget::normalizeEncodingCategories(NormalizedTargetModel &Result) {
  if (Input.EncodingCategories.empty()) {
    fail(Input.Target.Range, "target description requires at least one encoding category");
    return false;
  }
  std::unordered_set<std::uint32_t> IDs;
  std::unordered_set<std::string> Symbols;
  std::unordered_set<std::string> Names;
  for (const SourceEncodingCategory &Category : Input.EncodingCategories) {
    if (Category.ID == 0 || !isIdentifier(Category.Symbol) || Category.Name.empty() ||
        Category.SizeInBytes == 0 || !IDs.insert(Category.ID).second ||
        !Symbols.insert(Category.Symbol).second || !Names.insert(Category.Name).second) {
      fail(Category.Range,
           "encoding categories require nonzero unique IDs, symbols, names, and sizes");
      return false;
    }
    EncodingCategoryBySymbol.emplace(Category.Symbol, Category.ID);
    Result.EncodingCategories.push_back({
        .ID = Category.ID,
        .Symbol = Category.Symbol,
        .Name = Category.Name,
        .SizeInBytes = Category.SizeInBytes,
    });
  }
  return true;
}

[[nodiscard]] bool CodeGenTarget::normalizeAssemblyFormats(NormalizedTargetModel &Result) {
  if (Input.AssemblyFormats.empty()) {
    fail(Input.Target.Range, "target description requires at least one assembly format");
    return false;
  }
  std::unordered_set<std::uint32_t> IDs;
  std::unordered_set<std::string> Symbols;
  std::unordered_set<std::string> Names;
  for (const SourceAssemblyFormat &Format : Input.AssemblyFormats) {
    if (Format.ID == 0 || !isIdentifier(Format.Symbol) || Format.Name.empty() ||
        !IDs.insert(Format.ID).second || !Symbols.insert(Format.Symbol).second ||
        !Names.insert(Format.Name).second) {
      fail(Format.Range, "assembly formats require nonzero unique IDs, symbols, and names");
      return false;
    }
    AssemblyFormatBySymbol.emplace(Format.Symbol, Format.ID);
    Result.AssemblyFormats.push_back({
        .ID = Format.ID,
        .Symbol = Format.Symbol,
        .Name = Format.Name,
    });
  }
  return true;
}

} // namespace rcc::targetgen