aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard-Qin-X <richard.qin.001@gmail.com>2026-08-28 23:56:19 +0800
committerRichard-Qin-X <richard.qin.001@gmail.com>2026-08-28 23:56:19 +0800
commit7ee5d1913c7cfd0261f86b0ff7be6968b8c07d84 (patch)
tree446dafb95e2f792fee922602b74709c5b9e0777c
parentf0cfb240d80cb9f4444fb996350c1f88bc69a142 (diff)
downloadrcc-project-7ee5d1913c7cfd0261f86b0ff7be6968b8c07d84.tar.gz
rcc-project-7ee5d1913c7cfd0261f86b0ff7be6968b8c07d84.tar.xz
[Support] Use standard power-of-two checks
-rw-r--r--backend/lib/CodeGen/TargetRegisterInfo.cpp8
-rw-r--r--backend/lib/MC/ELFObjectWriter.cpp13
-rw-r--r--backend/lib/MC/MCAssembler.cpp11
-rw-r--r--backend/lib/MC/MCSection.cpp7
-rw-r--r--backend/lib/MC/MCStreamer.cpp7
-rw-r--r--backend/utils/TableGen/Common/CodeGenInstruction.cpp3
-rw-r--r--backend/utils/TableGen/Common/CodeGenTarget.cpp9
-rw-r--r--backend/utils/TableGen/Common/CodeGenTarget.h1
8 files changed, 20 insertions, 39 deletions
diff --git a/backend/lib/CodeGen/TargetRegisterInfo.cpp b/backend/lib/CodeGen/TargetRegisterInfo.cpp
index 7ddf676..b6631eb 100644
--- a/backend/lib/CodeGen/TargetRegisterInfo.cpp
+++ b/backend/lib/CodeGen/TargetRegisterInfo.cpp
@@ -22,10 +22,6 @@ namespace {
"target register description: " + std::move(Message));
}
-[[nodiscard]] bool isPowerOfTwo(std::uint32_t Value) noexcept {
- return Value != 0 && std::has_single_bit(Value);
-}
-
[[nodiscard]] std::string lowerASCII(std::string_view Name) {
std::string Result(Name);
for (char &Character : Result) {
@@ -274,8 +270,8 @@ Expected<TargetRegisterInfo> TargetRegisterInfo::create(TargetRegisterInfoDesc D
for (const RegisterClassDesc &Class : Result.Description.RegisterClasses) {
if (Class.Registers.empty() || Class.SizeInBits == 0 ||
- Class.SpillSizeInBits < Class.SizeInBits || !isPowerOfTwo(Class.SpillAlignmentInBits) ||
- Class.Lanes.empty()) {
+ Class.SpillSizeInBits < Class.SizeInBits ||
+ !std::has_single_bit(Class.SpillAlignmentInBits) || Class.Lanes.empty()) {
return invalidDescription(
"register class requires members, sizes, power-of-two spill alignment, and lanes");
}
diff --git a/backend/lib/MC/ELFObjectWriter.cpp b/backend/lib/MC/ELFObjectWriter.cpp
index 730ef72..96ec234 100644
--- a/backend/lib/MC/ELFObjectWriter.cpp
+++ b/backend/lib/MC/ELFObjectWriter.cpp
@@ -3,6 +3,7 @@
#include "rcc/MC/ELFObjectWriter.h"
#include <algorithm>
+#include <bit>
#include <cstddef>
#include <cstdint>
#include <limits>
@@ -98,10 +99,6 @@ struct OutputSection final {
MCSymbolRef GroupSignature;
};
-[[nodiscard]] bool isPowerOfTwo(std::uint64_t Value) noexcept {
- return Value != 0 && (Value & (Value - 1U)) == 0;
-}
-
[[nodiscard]] bool isWriterManagedSectionType(std::uint32_t Type) noexcept {
switch (Type) {
case SHTNull:
@@ -127,7 +124,7 @@ struct OutputSection final {
}
[[nodiscard]] Expected<std::uint64_t> alignTo(std::uint64_t Value, std::uint64_t Alignment) {
- if (!isPowerOfTwo(Alignment))
+ if (!std::has_single_bit(Alignment))
return makeUnexpected(ErrorCode::ObjectWritingFailed, "ELF alignment is not a power of two");
auto Adjusted = checkedAdd(Value, Alignment - 1U, "ELF file offset overflows");
if (!Adjusted)
@@ -290,7 +287,7 @@ ELF64LEObjectWriter::writeObject(const MCAssembledObject &Object) const {
return std::unexpected(DescriptionVerification.error());
const bool NoBits =
Description.Kind == MCSectionKind::BSS || Description.Kind == MCSectionKind::TLSBSS;
- if (!isPowerOfTwo(Input.Alignment) || Input.Alignment < Description.Alignment) {
+ if (!std::has_single_bit(Input.Alignment) || Input.Alignment < Description.Alignment) {
return makeUnexpected(ErrorCode::ObjectWritingFailed,
"ELF input section has an invalid effective alignment");
}
@@ -324,7 +321,7 @@ ELF64LEObjectWriter::writeObject(const MCAssembledObject &Object) const {
for (const ELFExtraSection &Extra : Target.ExtraSections) {
if (Extra.Name.empty() || isWriterManagedSectionType(Extra.Type) ||
- !isPowerOfTwo(Extra.Alignment) || (Extra.Flags & (SHFInfoLink | SHFGroup)) != 0 ||
+ !std::has_single_bit(Extra.Alignment) || (Extra.Flags & (SHFInfoLink | SHFGroup)) != 0 ||
(Extra.EntrySize != 0 && Extra.Contents.size() % Extra.EntrySize != 0)) {
return makeUnexpected(ErrorCode::ObjectWritingFailed,
"ELF extra section has an invalid description");
@@ -365,7 +362,7 @@ ELF64LEObjectWriter::writeObject(const MCAssembledObject &Object) const {
std::uint16_t Section = SHNUndefined;
std::uint64_t Value = Input.Value;
if (Input.CommonAlignment != 0) {
- if (!isPowerOfTwo(Input.CommonAlignment) || Input.Size == 0 || Input.SectionIndex ||
+ if (!std::has_single_bit(Input.CommonAlignment) || Input.Size == 0 || Input.SectionIndex ||
Input.Binding == MCObjectSymbolBinding::Local || Input.Value != Input.CommonAlignment) {
return makeUnexpected(ErrorCode::ObjectWritingFailed,
"ELF common symbol has an invalid definition");
diff --git a/backend/lib/MC/MCAssembler.cpp b/backend/lib/MC/MCAssembler.cpp
index 0f92edb..e1eb8e0 100644
--- a/backend/lib/MC/MCAssembler.cpp
+++ b/backend/lib/MC/MCAssembler.cpp
@@ -3,6 +3,7 @@
#include "rcc/MC/MCAssembler.h"
#include <algorithm>
+#include <bit>
#include <cstddef>
#include <cstdint>
#include <limits>
@@ -12,10 +13,6 @@
namespace rcc::mc {
namespace {
-[[nodiscard]] bool isPowerOfTwo(std::uint64_t Value) noexcept {
- return Value != 0 && (Value & (Value - 1U)) == 0;
-}
-
[[nodiscard]] Expected<std::uint64_t> checkedAdd(std::uint64_t Left, std::uint64_t Right,
std::string_view Message) {
std::uint64_t Result = 0;
@@ -48,7 +45,7 @@ namespace {
[[nodiscard]] Expected<std::uint64_t> alignmentPadding(std::uint64_t Offset,
std::uint64_t Alignment) {
- if (!isPowerOfTwo(Alignment))
+ if (!std::has_single_bit(Alignment))
return makeUnexpected(ErrorCode::InvalidArgument, "MC alignment is not a power of two");
const std::uint64_t Mask = Alignment - 1U;
auto Adjusted = checkedAdd(Offset, Mask, "MC section alignment overflows");
@@ -230,7 +227,7 @@ Expected<void> MCAssembler::emitAlignment(std::uint64_t Alignment, std::uint8_t
auto SectionIndex = currentSectionIndex();
if (!SectionIndex)
return std::unexpected(SectionIndex.error());
- if (!isPowerOfTwo(Alignment))
+ if (!std::has_single_bit(Alignment))
return makeUnexpected(ErrorCode::InvalidArgument, "MC alignment is not a power of two");
Sections[*SectionIndex].Fragments.push_back(Fragment{
.Payload =
@@ -296,7 +293,7 @@ Expected<void> MCAssembler::emitCommonSymbol(MCSymbolRef Symbol, std::uint64_t S
std::uint64_t Alignment) {
if (WasAssembled)
return makeUnexpected(ErrorCode::ObjectWritingFailed, "MC assembler is already finalized");
- if (!Symbol || Size == 0 || !isPowerOfTwo(Alignment)) {
+ if (!Symbol || Size == 0 || !std::has_single_bit(Alignment)) {
return makeUnexpected(ErrorCode::InvalidArgument,
"common symbol requires a size and power-of-two alignment");
}
diff --git a/backend/lib/MC/MCSection.cpp b/backend/lib/MC/MCSection.cpp
index 21ba410..464dcc6 100644
--- a/backend/lib/MC/MCSection.cpp
+++ b/backend/lib/MC/MCSection.cpp
@@ -2,6 +2,7 @@
#include "rcc/MC/MCSection.h"
+#include <bit>
#include <cstdint>
#include <string_view>
@@ -19,16 +20,12 @@ namespace {
return true;
}
-[[nodiscard]] bool isPowerOfTwo(std::uint64_t Value) noexcept {
- return Value != 0 && (Value & (Value - 1U)) == 0;
-}
-
} // namespace
Expected<void> MCSectionDesc::verify() const {
if (!isValidAssemblyName(Name))
return makeUnexpected(ErrorCode::InvalidArgument, "MC section has an invalid name");
- if (!isPowerOfTwo(Alignment)) {
+ if (!std::has_single_bit(Alignment)) {
return makeUnexpected(ErrorCode::InvalidArgument,
"MC section alignment must be a nonzero power of two");
}
diff --git a/backend/lib/MC/MCStreamer.cpp b/backend/lib/MC/MCStreamer.cpp
index 56c3f96..709dccc 100644
--- a/backend/lib/MC/MCStreamer.cpp
+++ b/backend/lib/MC/MCStreamer.cpp
@@ -4,6 +4,7 @@
#include <algorithm>
#include <array>
+#include <bit>
#include <cctype>
#include <cstddef>
#include <cstdint>
@@ -23,10 +24,6 @@ namespace {
Text.find('\r') != std::string_view::npos;
}
-[[nodiscard]] bool isPowerOfTwo(std::uint64_t Value) noexcept {
- return Value != 0 && (Value & (Value - 1U)) == 0;
-}
-
[[nodiscard]] unsigned log2Exact(std::uint64_t Value) noexcept {
unsigned Result = 0;
while (Value > 1) {
@@ -282,7 +279,7 @@ Expected<void> AsmTextStreamer::emitAlignment(std::uint64_t Alignment, std::uint
auto Active = requireActiveSection();
if (!Active)
return std::unexpected(Active.error());
- if (!isPowerOfTwo(Alignment)) {
+ if (!std::has_single_bit(Alignment)) {
return makeUnexpected(ErrorCode::InvalidArgument,
"assembly alignment must be a nonzero power of two");
}
diff --git a/backend/utils/TableGen/Common/CodeGenInstruction.cpp b/backend/utils/TableGen/Common/CodeGenInstruction.cpp
index a34f5ab..e7f5ddc 100644
--- a/backend/utils/TableGen/Common/CodeGenInstruction.cpp
+++ b/backend/utils/TableGen/Common/CodeGenInstruction.cpp
@@ -4,6 +4,7 @@
#include <algorithm>
#include <array>
+#include <bit>
#include <cstdint>
#include <limits>
#include <ranges>
@@ -218,7 +219,7 @@ pipelineStageEnumerator(std::string_view Value) noexcept {
const bool IsUnsigned = Predicate.Kind == "unsigned";
if (Predicate.ID == 0 || !isIdentifier(Predicate.Symbol) || Predicate.Name.empty() ||
(!IsSigned && !IsUnsigned) || Predicate.Bits == 0 || Predicate.Bits > 63 ||
- !isPowerOfTwo(Predicate.Alignment) || !IDs.insert(Predicate.ID).second ||
+ !std::has_single_bit(Predicate.Alignment) || !IDs.insert(Predicate.ID).second ||
!Symbols.insert(Predicate.Symbol).second || !Names.insert(Predicate.Name).second) {
fail(Predicate.Range,
"immediate predicates require nonzero unique IDs, symbols, names, a signed or "
diff --git a/backend/utils/TableGen/Common/CodeGenTarget.cpp b/backend/utils/TableGen/Common/CodeGenTarget.cpp
index d4c9795..478457c 100644
--- a/backend/utils/TableGen/Common/CodeGenTarget.cpp
+++ b/backend/utils/TableGen/Common/CodeGenTarget.cpp
@@ -6,6 +6,7 @@
#include "rcc/TableGen/Parser.h"
#include <algorithm>
+#include <bit>
#include <cstddef>
#include <ranges>
#include <string>
@@ -15,10 +16,6 @@
namespace rcc::targetgen {
-[[nodiscard]] bool isPowerOfTwo(std::uint64_t Value) noexcept {
- return Value != 0 && (Value & (Value - 1U)) == 0;
-}
-
CodeGenTarget::CodeGenTarget(const DescriptionAST &Input, std::string SourceName)
: Input(Input), SourceName(std::move(SourceName)) {}
@@ -105,8 +102,8 @@ void CodeGenTarget::fail(TextRange Range, std::string Message) {
IntegerClass == ClassBySymbol.end() || FloatingClass == ClassBySymbol.end() ||
PreservedMask == Result.RegisterMasks.end() || Convention.StackAlignmentBytes == 0 ||
Convention.StackArgumentAlignmentBytes == 0 ||
- !isPowerOfTwo(Convention.StackAlignmentBytes) ||
- !isPowerOfTwo(Convention.StackArgumentAlignmentBytes) ||
+ !std::has_single_bit(Convention.StackAlignmentBytes) ||
+ !std::has_single_bit(Convention.StackArgumentAlignmentBytes) ||
Convention.StackAlignmentBytes % Convention.StackArgumentAlignmentBytes != 0 ||
Convention.ShadowSpaceBytes % Convention.StackArgumentAlignmentBytes != 0 ||
!IDs.insert(Convention.ID).second || !Symbols.insert(Convention.Symbol).second ||
diff --git a/backend/utils/TableGen/Common/CodeGenTarget.h b/backend/utils/TableGen/Common/CodeGenTarget.h
index 2ab6db1..a2aed7c 100644
--- a/backend/utils/TableGen/Common/CodeGenTarget.h
+++ b/backend/utils/TableGen/Common/CodeGenTarget.h
@@ -426,7 +426,6 @@ instructionFlagEnumerator(std::string_view Value) noexcept;
pseudoOwnerEnumerator(std::string_view Value) noexcept;
[[nodiscard]] std::optional<std::string_view>
pipelineStageEnumerator(std::string_view Value) noexcept;
-[[nodiscard]] bool isPowerOfTwo(std::uint64_t Value) noexcept;
class CodeGenTarget final {
public: