diff options
| author | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-09 18:31:49 +0800 |
|---|---|---|
| committer | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-09 18:31:49 +0800 |
| commit | 379ff50dcc7ccf977379aee68fa9d10f69065d23 (patch) | |
| tree | e0fac3952d46d0bbcaea32bcfc6087c95fff2992 /backend/lib/MC/MCContext.cpp | |
| parent | 495c675771f43cfa12ab7a426a538be72fec1805 (diff) | |
| download | rcc-project-379ff50dcc7ccf977379aee68fa9d10f69065d23.tar.gz rcc-project-379ff50dcc7ccf977379aee68fa9d10f69065d23.tar.xz | |
[MC] Implement RV64GC assembly emission
Diffstat (limited to 'backend/lib/MC/MCContext.cpp')
| -rw-r--r-- | backend/lib/MC/MCContext.cpp | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/backend/lib/MC/MCContext.cpp b/backend/lib/MC/MCContext.cpp new file mode 100644 index 0000000..2aa4c0e --- /dev/null +++ b/backend/lib/MC/MCContext.cpp @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "rcc/MC/MCContext.h" + +#include <cstdint> +#include <limits> +#include <memory> +#include <string> +#include <string_view> +#include <utility> + +namespace rcc::mc { +namespace { + +[[nodiscard]] bool isValidName(std::string_view Name) noexcept { + if (Name.empty()) + return false; + for (const char RawCharacter : Name) { + const auto Character = static_cast<unsigned char>(RawCharacter); + if (Character == 0 || Character == '\n' || Character == '\r' || Character == 0x7fU) + return false; + } + return true; +} + +} // namespace + +Expected<MCSymbolRef> MCContext::getOrCreateSymbol(std::string Name, MCSymbolKind Kind) { + if (!isValidName(Name)) + return makeUnexpected(ErrorCode::InvalidArgument, "MC symbol has an invalid name"); + + const auto Position = Symbols.find(Name); + if (Position != Symbols.end()) { + const MCSymbolKind ExistingKind = Position->second->kind(); + if (Kind != MCSymbolKind::Generic && ExistingKind != MCSymbolKind::Generic && + ExistingKind != Kind) { + return makeUnexpected(ErrorCode::InvalidArgument, + "MC symbol name is already used by a different symbol kind"); + } + return Position->second; + } + + MCSymbolRef Result(new MCSymbol(std::move(Name), Kind)); + Symbols.emplace(std::string(Result->name()), Result); + return Result; +} + +Expected<MCSymbolRef> MCContext::createTemporarySymbol(std::string_view Prefix) { + if (!isValidName(Prefix)) + return makeUnexpected(ErrorCode::InvalidArgument, "temporary MC symbol prefix is invalid"); + if (NextTemporarySymbol == std::numeric_limits<std::uint64_t>::max()) { + return makeUnexpected(ErrorCode::InternalError, "temporary MC symbol sequence is exhausted"); + } + + while (true) { + std::string Name(Prefix); + Name += std::to_string(NextTemporarySymbol++); + if (Symbols.contains(Name)) + continue; + return getOrCreateSymbol(std::move(Name), MCSymbolKind::Temporary); + } +} + +MCSymbolRef MCContext::symbol(std::string_view Name) const noexcept { + const auto Position = Symbols.find(Name); + return Position == Symbols.end() ? MCSymbolRef{} : Position->second; +} + +Expected<MCSectionRef> MCContext::getOrCreateSection(MCSectionDesc Description) { + auto Verification = Description.verify(); + if (!Verification) + return std::unexpected(Verification.error()); + + const auto Position = Sections.find(Description.Name); + if (Position != Sections.end()) { + MCSectionDesc ExistingDescription = Position->second->description(); + ExistingDescription.Alignment = Description.Alignment; + if (ExistingDescription != Description) { + return makeUnexpected(ErrorCode::InvalidArgument, + "MC section name is already used by a different description"); + } + return Position->second; + } + + MCSectionRef Result(new MCSection(std::move(Description))); + Sections.emplace(std::string(Result->name()), Result); + return Result; +} + +MCSectionRef MCContext::section(std::string_view Name) const noexcept { + const auto Position = Sections.find(Name); + return Position == Sections.end() ? MCSectionRef{} : Position->second; +} + +} // namespace rcc::mc |
