Skip to content

Commit fca3b2e

Browse files
committed
refactor(eh_guard): parse ExceptionUnwindContract via schema
The 12-field inner contract map now populates through parse_schema using EnumTextField for the four enum-valued fields (ExecutableEhStatus, CrossProtectedFrameUnwind, NativeBoundaryUnwindBehavior, ReservedTableStatus × 2). The existing EnumTextTraits specialisations cover every wire value. The nested-map walk to the contract sub-map (profile → correctness → contract) stays imperative because parse_schema doesn't have a NestedMapField descriptor; once the inner map is in hand, parse_schema takes it. semantic_contract_version sits on the correctness outer map and is still read via require_text. Dead helpers (parse_executable_eh_status / parse_cross_protected_frame_unwind / parse_native_boundary_unwind_behavior / parse_reserved_table_status) are removed.
1 parent 6e5626f commit fca3b2e

1 file changed

Lines changed: 58 additions & 129 deletions

File tree

runtime/src/eh_guard.cpp

Lines changed: 58 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <cstring>
44

5+
#include "cbor/schema.hpp"
56
#include "cbor/strict.hpp"
67

78
namespace VMPilot::Cbor {
@@ -10,6 +11,9 @@ struct CborConsumerTraits<VMPilot::Runtime::EH::ContractParseError> {
1011
using E = VMPilot::Runtime::EH::ContractParseError;
1112
static constexpr E missing_field = E::MissingField;
1213
static constexpr E wrong_field_type = E::WrongFieldType;
14+
static constexpr E bad_cbor = E::BadCbor;
15+
static constexpr E not_a_map = E::NotAMap;
16+
static constexpr E unknown_enum_value = E::UnknownEnumValue;
1317
};
1418
} // namespace VMPilot::Cbor
1519

@@ -71,50 +75,6 @@ require_map_field(const Value& map,
7175
return value;
7276
}
7377

74-
tl::expected<ExecutableEhStatus, ContractParseError>
75-
parse_executable_eh_status(std::string_view text) noexcept {
76-
if (text == "reserved_disabled_v1") {
77-
return ExecutableEhStatus::ReservedDisabledV1;
78-
}
79-
if (text == "executable_v1_1") {
80-
return ExecutableEhStatus::ExecutableV1_1;
81-
}
82-
return parse_err(ContractParseError::UnknownEnumValue);
83-
}
84-
85-
tl::expected<CrossProtectedFrameUnwind, ContractParseError>
86-
parse_cross_protected_frame_unwind(std::string_view text) noexcept {
87-
if (text == "forbidden") {
88-
return CrossProtectedFrameUnwind::Forbidden;
89-
}
90-
if (text == "permitted_by_profile") {
91-
return CrossProtectedFrameUnwind::PermittedByProfile;
92-
}
93-
return parse_err(ContractParseError::UnknownEnumValue);
94-
}
95-
96-
tl::expected<NativeBoundaryUnwindBehavior, ContractParseError>
97-
parse_native_boundary_unwind_behavior(std::string_view text) noexcept {
98-
if (text == "translate_to_trap_or_fail_closed") {
99-
return NativeBoundaryUnwindBehavior::TranslateToTrapOrFailClosed;
100-
}
101-
if (text == "profile-upgraded") {
102-
return NativeBoundaryUnwindBehavior::ProfileUpgraded;
103-
}
104-
return parse_err(ContractParseError::UnknownEnumValue);
105-
}
106-
107-
tl::expected<ReservedTableStatus, ContractParseError>
108-
parse_reserved_table_status(std::string_view text) noexcept {
109-
if (text == "reserved_empty") {
110-
return ReservedTableStatus::ReservedEmpty;
111-
}
112-
if (text == "profile-specific") {
113-
return ReservedTableStatus::ProfileSpecific;
114-
}
115-
return parse_err(ContractParseError::UnknownEnumValue);
116-
}
117-
11878
bool contract_has_unknown_extension(const Value& map) noexcept {
11979
for (std::size_t index = 0; index < map.map_size(); ++index) {
12080
const Value& key = map.map_key_at(index);
@@ -324,91 +284,60 @@ parse_exception_unwind_contract(const std::uint8_t* data,
324284
return parse_err(ContractParseError::UnknownCriticalExtension);
325285
}
326286

327-
auto eh_contract_version = require_text(contract, kEh_EhContractVersion);
328-
auto executable_eh_status_text =
329-
require_text(contract, kEh_ExecutableEhStatus);
330-
auto planned_executable_eh_epoch =
331-
require_text(contract, kEh_PlannedExecutableEhEpoch);
332-
auto cross_protected_frame_unwind_text =
333-
require_text(contract, kEh_CrossProtectedFrameUnwind);
334-
auto native_boundary_unwind_behavior_text =
335-
require_text(contract, kEh_NativeBoundaryUnwindBehavior);
336-
auto handler_table_status_text =
337-
require_text(contract, kEh_HandlerTableStatus);
338-
auto cleanup_table_status_text =
339-
require_text(contract, kEh_CleanupTableStatus);
340-
auto frame_contract_ref = require_text(contract, kEh_FrameContractRef);
341-
auto stackmap_contract_ref = require_text(contract, kEh_StackmapContractRef);
342-
auto resume_contract_ref = require_text(contract, kEh_ResumeContractRef);
343-
auto verifier_rules_ref = require_text(contract, kEh_VerifierRulesRef);
344-
auto family_specific_unwind_surface_ref =
345-
require_text(contract, kEh_FamilySpecificUnwindSurfaceRef);
346-
347-
if (!eh_contract_version) return parse_err(eh_contract_version.error());
348-
if (!executable_eh_status_text) {
349-
return parse_err(executable_eh_status_text.error());
350-
}
351-
if (!planned_executable_eh_epoch) {
352-
return parse_err(planned_executable_eh_epoch.error());
353-
}
354-
if (!cross_protected_frame_unwind_text) {
355-
return parse_err(cross_protected_frame_unwind_text.error());
356-
}
357-
if (!native_boundary_unwind_behavior_text) {
358-
return parse_err(native_boundary_unwind_behavior_text.error());
359-
}
360-
if (!handler_table_status_text) {
361-
return parse_err(handler_table_status_text.error());
362-
}
363-
if (!cleanup_table_status_text) {
364-
return parse_err(cleanup_table_status_text.error());
365-
}
366-
if (!frame_contract_ref) return parse_err(frame_contract_ref.error());
367-
if (!stackmap_contract_ref) return parse_err(stackmap_contract_ref.error());
368-
if (!resume_contract_ref) return parse_err(resume_contract_ref.error());
369-
if (!verifier_rules_ref) return parse_err(verifier_rules_ref.error());
370-
if (!family_specific_unwind_surface_ref) {
371-
return parse_err(family_specific_unwind_surface_ref.error());
372-
}
373-
374-
auto executable_eh_status =
375-
parse_executable_eh_status(*executable_eh_status_text);
376-
auto cross_protected_frame_unwind =
377-
parse_cross_protected_frame_unwind(*cross_protected_frame_unwind_text);
378-
auto native_boundary_unwind_behavior =
379-
parse_native_boundary_unwind_behavior(
380-
*native_boundary_unwind_behavior_text);
381-
auto handler_table_status =
382-
parse_reserved_table_status(*handler_table_status_text);
383-
auto cleanup_table_status =
384-
parse_reserved_table_status(*cleanup_table_status_text);
385-
386-
if (!executable_eh_status) return parse_err(executable_eh_status.error());
387-
if (!cross_protected_frame_unwind) {
388-
return parse_err(cross_protected_frame_unwind.error());
389-
}
390-
if (!native_boundary_unwind_behavior) {
391-
return parse_err(native_boundary_unwind_behavior.error());
392-
}
393-
if (!handler_table_status) return parse_err(handler_table_status.error());
394-
if (!cleanup_table_status) return parse_err(cleanup_table_status.error());
395-
396-
ExceptionUnwindContract out;
397-
out.semantic_contract_version = std::move(*semantic_contract_version);
398-
out.eh_contract_version = std::move(*eh_contract_version);
399-
out.executable_eh_status = *executable_eh_status;
400-
out.planned_executable_eh_epoch = std::move(*planned_executable_eh_epoch);
401-
out.cross_protected_frame_unwind = *cross_protected_frame_unwind;
402-
out.native_boundary_unwind_behavior = *native_boundary_unwind_behavior;
403-
out.handler_table_status = *handler_table_status;
404-
out.cleanup_table_status = *cleanup_table_status;
405-
out.frame_contract_ref = std::move(*frame_contract_ref);
406-
out.stackmap_contract_ref = std::move(*stackmap_contract_ref);
407-
out.resume_contract_ref = std::move(*resume_contract_ref);
408-
out.verifier_rules_ref = std::move(*verifier_rules_ref);
409-
out.family_specific_unwind_surface_ref =
410-
std::move(*family_specific_unwind_surface_ref);
411-
return out;
287+
using namespace VMPilot::Cbor::Schema;
288+
const auto schema = std::make_tuple(
289+
TextField<ExceptionUnwindContract>{
290+
kEh_EhContractVersion,
291+
&ExceptionUnwindContract::eh_contract_version},
292+
EnumTextField<ExceptionUnwindContract, ExecutableEhStatus,
293+
ContractParseError>{
294+
kEh_ExecutableEhStatus,
295+
&ExceptionUnwindContract::executable_eh_status,
296+
ContractParseError::UnknownEnumValue},
297+
TextField<ExceptionUnwindContract>{
298+
kEh_PlannedExecutableEhEpoch,
299+
&ExceptionUnwindContract::planned_executable_eh_epoch},
300+
EnumTextField<ExceptionUnwindContract, CrossProtectedFrameUnwind,
301+
ContractParseError>{
302+
kEh_CrossProtectedFrameUnwind,
303+
&ExceptionUnwindContract::cross_protected_frame_unwind,
304+
ContractParseError::UnknownEnumValue},
305+
EnumTextField<ExceptionUnwindContract, NativeBoundaryUnwindBehavior,
306+
ContractParseError>{
307+
kEh_NativeBoundaryUnwindBehavior,
308+
&ExceptionUnwindContract::native_boundary_unwind_behavior,
309+
ContractParseError::UnknownEnumValue},
310+
EnumTextField<ExceptionUnwindContract, ReservedTableStatus,
311+
ContractParseError>{
312+
kEh_HandlerTableStatus,
313+
&ExceptionUnwindContract::handler_table_status,
314+
ContractParseError::UnknownEnumValue},
315+
EnumTextField<ExceptionUnwindContract, ReservedTableStatus,
316+
ContractParseError>{
317+
kEh_CleanupTableStatus,
318+
&ExceptionUnwindContract::cleanup_table_status,
319+
ContractParseError::UnknownEnumValue},
320+
TextField<ExceptionUnwindContract>{
321+
kEh_FrameContractRef,
322+
&ExceptionUnwindContract::frame_contract_ref},
323+
TextField<ExceptionUnwindContract>{
324+
kEh_StackmapContractRef,
325+
&ExceptionUnwindContract::stackmap_contract_ref},
326+
TextField<ExceptionUnwindContract>{
327+
kEh_ResumeContractRef,
328+
&ExceptionUnwindContract::resume_contract_ref},
329+
TextField<ExceptionUnwindContract>{
330+
kEh_VerifierRulesRef,
331+
&ExceptionUnwindContract::verifier_rules_ref},
332+
TextField<ExceptionUnwindContract>{
333+
kEh_FamilySpecificUnwindSurfaceRef,
334+
&ExceptionUnwindContract::family_specific_unwind_surface_ref}
335+
);
336+
auto parsed =
337+
parse_schema<ExceptionUnwindContract, ContractParseError>(contract, schema);
338+
if (!parsed) return parse_err(parsed.error());
339+
parsed->semantic_contract_version = std::move(*semantic_contract_version);
340+
return parsed;
412341
}
413342

414343
tl::expected<ExceptionUnwindContract, ContractVerifyError>

0 commit comments

Comments
 (0)