// SPDX-License-Identifier: GPL-3.0-or-later #include "rcc/Target/RISCV/RISCVFunctionInfo.h" #include "rcc/CodeGen/TargetMIRTextInfo.h" #include #include #include #include #include #include #include #include #include #include namespace rcc::riscv { namespace { [[nodiscard]] Expected parseSignedField(const MIRTargetNode &Node, std::string_view Name) { if (Node.Kind != MIRTargetNodeKind::Scalar) return makeUnexpected(ErrorCode::ParseError, "RISC-V machineFunctionInfo field '" + std::string(Name) + "' must be a scalar"); std::int32_t Value = 0; const auto Result = std::from_chars(Node.Scalar.data(), Node.Scalar.data() + Node.Scalar.size(), Value, 10); if (Result.ec != std::errc{} || Result.ptr != Node.Scalar.data() + Node.Scalar.size()) { return makeUnexpected(ErrorCode::ParseError, "RISC-V machineFunctionInfo field '" + std::string(Name) + "' must be a 32-bit signed integer"); } return Value; } [[nodiscard]] Expected parseFunctionInfo(const MIRTargetNode &Node) { if (Node.Kind != MIRTargetNodeKind::Mapping) return makeUnexpected(ErrorCode::ParseError, "RISC-V machineFunctionInfo must be a mapping"); std::int32_t VarArgsFrameIndex = 0; std::int32_t VarArgsSaveSize = 0; for (const MIRTargetMappingEntry &Entry : Node.Mapping) { if (Entry.Key == "varArgsFrameIndex") { auto Value = parseSignedField(Entry.Value, Entry.Key); if (!Value) return std::unexpected(Value.error()); VarArgsFrameIndex = *Value; continue; } if (Entry.Key == "varArgsSaveSize") { auto Value = parseSignedField(Entry.Value, Entry.Key); if (!Value) return std::unexpected(Value.error()); VarArgsSaveSize = *Value; continue; } return makeUnexpected(ErrorCode::ParseError, "unknown RISC-V machineFunctionInfo field '" + Entry.Key + "'"); } return TargetFunctionState::create(RISCVFunctionInfo(VarArgsFrameIndex, VarArgsSaveSize)); } [[nodiscard]] Expected printFunctionInfo(const TargetFunctionState &State) { const auto *Info = State.getIf(); if (Info == nullptr) return makeUnexpected(ErrorCode::InvalidArgument, "target function state is not RISC-V function information"); std::vector Entries; Entries.push_back( {"varArgsFrameIndex", MIRTargetNode::scalar(std::to_string(Info->varArgsFrameIndex()))}); Entries.push_back( {"varArgsSaveSize", MIRTargetNode::scalar(std::to_string(Info->varArgsSaveSize()))}); return MIRTargetNode::mapping(std::move(Entries)); } void appendWord(std::vector &Payload, std::int32_t Value) { const std::uint32_t Bits = std::bit_cast(Value); for (std::uint32_t Shift = 0; Shift != 32; Shift += 8) Payload.push_back(static_cast((Bits >> Shift) & 0xFFU)); } [[nodiscard]] std::int32_t readWord(std::span Payload, std::size_t Offset) noexcept { std::uint32_t Bits = 0; for (std::uint32_t Byte = 0; Byte != 4; ++Byte) { Bits |= std::to_integer(Payload[Offset + Byte]) << (Byte * 8U); } return std::bit_cast(Bits); } } // namespace Expected RISCVFunctionInfo::verify() const { return {}; } Expected RISCVFunctionInfo::clone(const MachineFunctionCloneContext &) const { return RISCVFunctionInfo(VarArgsFrameIndex, VarArgsSaveSize); } std::string RISCVFunctionInfo::print() const { return "riscv-varargs:" + std::to_string(VarArgsFrameIndex) + ":" + std::to_string(VarArgsSaveSize); } Expected> RISCVFunctionInfo::encode() const { std::vector Payload; Payload.reserve(8); appendWord(Payload, VarArgsFrameIndex); appendWord(Payload, VarArgsSaveSize); return Payload; } Expected RISCVFunctionInfo::decode(std::uint32_t Version, std::span Payload) { if (Version != schemaVersion()) return makeUnexpected(ErrorCode::ParseError, "unsupported RISC-V function-info schema version"); if (Payload.size() != 8) return makeUnexpected(ErrorCode::ParseError, "RISC-V function-info payload must contain eight bytes"); return RISCVFunctionInfo(readWord(Payload, 0), readWord(Payload, 4)); } void configureFunctionInfoMIRSchema(TargetMIRTextInfoDesc &Description) { Description.FunctionStateType = RISCVFunctionInfo::stableTypeID(); Description.ParseFunctionState = parseFunctionInfo; Description.PrintFunctionState = printFunctionInfo; } } // namespace rcc::riscv