Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Reduce data definition length evaluation dependencies #239

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions parser_library/src/checking/data_definition/data_def_fields.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ struct data_def_address
using expr_or_address = std::variant<data_def_expr, data_def_address>;
using nominal_value_expressions = std::vector<expr_or_address>;
using nominal_value_t = data_def_field<std::variant<std::string, nominal_value_expressions>>;
using reduced_nominal_value_t = data_def_field<std::variant<std::string, size_t>>;
using scale_modifier_t = data_def_field<int16_t>;
using exponent_modifier_t = data_def_field<int32_t>;
using dupl_factor_modifier_t = data_def_field<int32_t>;
Expand All @@ -104,6 +105,26 @@ inline T round_up(T n, T m)
return ((n + m - 1) / m) * m;
}

inline reduced_nominal_value_t reduce_nominal_value(const nominal_value_t& n)
{
struct
{
std::variant<std::string, size_t> operator()(const std::string& s) const { return s; }
std::variant<std::string, size_t> operator()(const nominal_value_expressions& e) const { return e.size(); }
} visitor;
return reduced_nominal_value_t(n.present, std::visit(visitor, n.value), n.rng);
}

inline reduced_nominal_value_t reduce_nominal_value(nominal_value_t&& n)
{
struct
{
std::variant<std::string, size_t> operator()(std::string&& s) const { return std::move(s); }
std::variant<std::string, size_t> operator()(nominal_value_expressions&& e) const { return e.size(); }
} visitor;
return reduced_nominal_value_t(n.present, std::visit(visitor, std::move(n.value)), n.rng);
}

} // namespace hlasm_plugin::parser_library::checking

#endif // !HLASMPLUGIN_PARSERLIBRARY_CHECKING_DATA_DEF_FIELDS_H
69 changes: 38 additions & 31 deletions parser_library/src/checking/data_definition/data_def_type_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ bool data_def_type::check(const data_definition_operand& op, const diagnostic_co
if (!ret)
return false;
// if operand is ok, we can call get_length and check if it is not too long
if (get_length(op) >= (1ll << 31) * 8)
if (get_length(op) >= ((1ll << 31) - 1) * 8)
{
add_diagnostic(diagnostic_op::error_D028(op.operand_range));
return false;
Expand Down Expand Up @@ -150,21 +150,21 @@ bool check_modifier(const data_def_field<field_val_T>& modifier,
return true;
}

uint64_t data_def_type::get_nominal_length(const nominal_value_t&) const
uint64_t data_def_type::get_nominal_length(const reduced_nominal_value_t&) const
{
// all types that have implicit length as needed must override this function
assert(false);
return uint64_t();
}

uint32_t data_def_type::get_nominal_length_attribute(const nominal_value_t&) const
uint32_t data_def_type::get_nominal_length_attribute(const reduced_nominal_value_t&) const
{
// all types that have implicit length as needed must override this function
assert(false);
return uint32_t();
}

int16_t data_def_type::get_implicit_scale(const nominal_value_t&) const
int16_t data_def_type::get_implicit_scale(const reduced_nominal_value_t&) const
{
// All types except P and Z have implicit scale 0.
return 0;
Expand Down Expand Up @@ -228,33 +228,33 @@ modifier_spec data_def_type::get_bit_length_spec() const
}

bool data_def_type::check_dupl_factor(
const data_definition_operand& op, const diagnostic_collector& add_diagnostic) const
const data_def_field<int32_t>& dupl_factor, const diagnostic_collector& add_diagnostic) const
{
if (op.dupl_factor.present)
if (op.dupl_factor.value < 0)
if (dupl_factor.present)
if (dupl_factor.value < 0)
{
// Duplication factor must be non negative
add_diagnostic(diagnostic_op::error_D011(op.dupl_factor.rng));
add_diagnostic(diagnostic_op::error_D011(dupl_factor.rng));
return false;
}
return true;
}

template<data_instr_type instr_type>
bool data_def_type::check_length(const data_definition_operand& op, const diagnostic_collector& add_diagnostic) const
bool data_def_type::check_length(const data_def_length_t& length, const diagnostic_collector& add_diagnostic) const
{
if (std::holds_alternative<n_a>(bit_length_spec_) && op.length.len_type == data_def_length_t::length_type::BIT)
if (std::holds_alternative<n_a>(bit_length_spec_) && length.len_type == data_def_length_t::length_type::BIT)
{
// bit length not allowed with this type
add_diagnostic(diagnostic_op::error_D007(op.length.rng, type_str));
add_diagnostic(diagnostic_op::error_D007(length.rng, type_str));
return false;
}
else
{
if (op.length.len_type == data_def_length_t::length_type::BIT)
return check_modifier(op.length, type_str, "bit length", get_bit_length_spec<instr_type>(), add_diagnostic);
if (length.len_type == data_def_length_t::length_type::BIT)
return check_modifier(length, type_str, "bit length", get_bit_length_spec<instr_type>(), add_diagnostic);
else
return check_modifier(op.length, type_str, "length", get_length_spec<instr_type>(), add_diagnostic);
return check_modifier(length, type_str, "length", get_length_spec<instr_type>(), add_diagnostic);
}
}

Expand Down Expand Up @@ -309,8 +309,8 @@ std::pair<bool, bool> data_def_type::check_base(
{
assert(op.type.value == type);
assert(op.extension.value == extension);
bool ret = check_dupl_factor(op, add_diagnostic);
ret &= check_length<instr_type>(op, add_diagnostic);
bool ret = check_dupl_factor(op.dupl_factor, add_diagnostic);
ret &= check_length<instr_type>(op.length, add_diagnostic);
ret &= check_modifier(op.scale, type_str, "scale", scale_spec_, add_diagnostic);
ret &= check_modifier(op.exponent, type_str, "exponent", exponent_spec_, add_diagnostic);

Expand All @@ -336,7 +336,7 @@ context::alignment data_def_type::get_alignment(bool length_present) const
return alignment_;
}

size_t data_def_type::get_number_of_values_in_nominal(const nominal_value_t& nom) const
size_t data_def_type::get_number_of_values_in_nominal(const reduced_nominal_value_t& nom) const
{
if (type == 'C' || type == 'G') // C and G do not support multiple nominal values
return 1;
Expand All @@ -346,36 +346,43 @@ size_t data_def_type::get_number_of_values_in_nominal(const nominal_value_t& nom
return std::count(s.begin(), s.end(), ',') + 1;
}
else
return std::get<nominal_value_expressions>(nom.value).size();
return std::get<size_t>(nom.value);
}

// this function assumes, that the operand is already checked and was OK
uint64_t data_def_type::get_length(const data_definition_operand& op) const
{
return get_length(op.dupl_factor, op.length, reduce_nominal_value(op.nominal_value));
}
uint64_t data_def_type::get_length(const data_def_field<int32_t>& dupl_factor,
const data_def_length_t& length,
const reduced_nominal_value_t& rnv) const
{
uint64_t len_in_bits;
if (op.length.present)
if (length.present)
{
uint64_t val_count = get_number_of_values_in_nominal(op.nominal_value);
len_in_bits = val_count * op.length.value;
uint64_t val_count = get_number_of_values_in_nominal(rnv);
len_in_bits = val_count * length.value;

if (op.length.len_type == data_def_length_t::BYTE)
if (length.len_type == data_def_length_t::BYTE)
len_in_bits *= 8;
}
else if (std::holds_alternative<as_needed>(implicit_length_))
len_in_bits = get_nominal_length(op.nominal_value) * 8;
else if (!op.nominal_value.present)
len_in_bits = get_nominal_length(rnv) * 8;
else if (!rnv.present)
len_in_bits = std::get<uint64_t>(implicit_length_) * 8;
else
{
uint64_t val_count = get_number_of_values_in_nominal(op.nominal_value);
uint64_t val_count = get_number_of_values_in_nominal(rnv);
len_in_bits = val_count * std::get<uint64_t>(implicit_length_) * 8;
}
if (op.dupl_factor.present)
len_in_bits *= (uint64_t)op.dupl_factor.value;
if (dupl_factor.present)
len_in_bits *= (uint64_t)dupl_factor.value;
return len_in_bits;
}

uint32_t data_def_type::get_length_attribute(const data_def_length_t& length, const nominal_value_t& nominal) const
uint32_t data_def_type::get_length_attribute(
const data_def_length_t& length, const reduced_nominal_value_t& nominal) const
{
if (length.present)
{
Expand All @@ -394,7 +401,7 @@ uint32_t data_def_type::get_length_attribute(const data_def_length_t& length, co
return (uint32_t)std::get<uint64_t>(implicit_length_);
}

int16_t data_def_type::get_scale_attribute(const scale_modifier_t& scale, const nominal_value_t& nominal) const
int16_t data_def_type::get_scale_attribute(const scale_modifier_t& scale, const reduced_nominal_value_t& nominal) const
{
if (scale.present)
return scale.value;
Expand All @@ -403,7 +410,7 @@ int16_t data_def_type::get_scale_attribute(const scale_modifier_t& scale, const
}

int32_t data_def_type::get_integer_attribute(
const data_def_length_t& length, const scale_modifier_t& scale, const nominal_value_t& nominal) const
const data_def_length_t& length, const scale_modifier_t& scale, const reduced_nominal_value_t& nominal) const
{
uint32_t L = get_length_attribute(length, nominal);
int32_t S = get_scale_attribute(scale, nominal);
Expand Down Expand Up @@ -462,7 +469,7 @@ const data_def_type* data_def_type::access_data_def_type(char type, char extensi
return found == types_and_extensions.end() ? nullptr : found->second.get();
}

data_def_type::~data_def_type() {}
data_def_type::~data_def_type() = default;

template bool data_def_type::check<data_instr_type::DC>(
const data_definition_operand& op, const diagnostic_collector& add_diagnostic) const;
Expand Down
30 changes: 17 additions & 13 deletions parser_library/src/checking/data_definition/data_def_type_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,32 +113,42 @@ class data_def_type
context::alignment get_alignment(bool length_present) const;
// returns length of the operand in bits
uint64_t get_length(const data_definition_operand& op) const;
uint64_t get_length(const data_def_field<int32_t>& dupl_factor,
const data_def_length_t& length,
const reduced_nominal_value_t& rnv) const;
// returns the length attribute of operand with specified length modifier and nominal value
uint32_t get_length_attribute(const data_def_length_t& length, const nominal_value_t& nominal) const;
uint32_t get_length_attribute(const data_def_length_t& length, const reduced_nominal_value_t& nominal) const;
// returns scale attribute of operand with specified scale modifier and nominal value
int16_t get_scale_attribute(const scale_modifier_t& scale, const nominal_value_t& nominal) const;
int16_t get_scale_attribute(const scale_modifier_t& scale, const reduced_nominal_value_t& nominal) const;
// returns length of operand with specified scale modifier and nominal value
int32_t get_integer_attribute(
const data_def_length_t& length, const scale_modifier_t& scale, const nominal_value_t& nominal) const;
const data_def_length_t& length, const scale_modifier_t& scale, const reduced_nominal_value_t& nominal) const;
// Returns type corresponding to specified type and extension.
static const data_def_type* access_data_def_type(char type, char extension);

static const std::map<std::pair<char, char>, std::unique_ptr<const data_def_type>> types_and_extensions;

virtual ~data_def_type() = 0;

// Checks duplication factor.
bool check_dupl_factor(const data_def_field<int32_t>& op, const diagnostic_collector& add_diagnostic) const;

// Checks the length modifier.
template<data_instr_type type>
bool check_length(const data_def_length_t& op, const diagnostic_collector& add_diagnostic) const;

protected:
char type;
char extension;
std::string type_str;

// When implicit length is "as needed" - it depends on nominal value, returns the implicit length in bytes.
// All types that have implicit length "as needed" must override this function.
virtual uint64_t get_nominal_length(const nominal_value_t& op) const;
virtual uint64_t get_nominal_length(const reduced_nominal_value_t& op) const;

virtual uint32_t get_nominal_length_attribute(const nominal_value_t& op) const;
virtual uint32_t get_nominal_length_attribute(const reduced_nominal_value_t& op) const;
// Gets the value of scale attribute when there is no scale modifier defined by user.
virtual int16_t get_implicit_scale(const nominal_value_t& op) const;
virtual int16_t get_implicit_scale(const reduced_nominal_value_t& op) const;

virtual int32_t get_integer_attribute_impl(uint32_t length, int32_t scale) const;

Expand All @@ -155,12 +165,6 @@ class data_def_type

// Concatenates the two characters and returns resulting string.
static std::string init_type_str(char type, char extension);
// Checks duplication factor.
bool check_dupl_factor(const data_definition_operand& op, const diagnostic_collector& add_diagnostic) const;

// Checks the length modifier.
template<data_instr_type type>
bool check_length(const data_definition_operand& op, const diagnostic_collector& add_diagnostic) const;

// Checks whether the nominal value is present when it is mandatory. Returns two booleans: the first one specifies
// whether there was an error, the second one specifies whether the nominal value is present and needs to be checked
Expand All @@ -172,7 +176,7 @@ class data_def_type
// Checks if nominal value has the right type and is safe to access. Expects that nominal type is present.
bool check_nominal_type(const data_definition_operand& op, const diagnostic_collector& add_diagnostic) const;

size_t get_number_of_values_in_nominal(const nominal_value_t& nom) const;
size_t get_number_of_values_in_nominal(const reduced_nominal_value_t& nom) const;

template<data_instr_type type>
modifier_spec get_length_spec() const;
Expand Down
30 changes: 15 additions & 15 deletions parser_library/src/checking/data_definition/data_def_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,17 @@ class data_def_type_B final : public data_def_type
const diagnostic_collector& add_diagnostic,
bool check_nominal) const override;

uint64_t get_nominal_length(const nominal_value_t& op) const override;
uint32_t get_nominal_length_attribute(const nominal_value_t& op) const override;
uint64_t get_nominal_length(const reduced_nominal_value_t& op) const override;
uint32_t get_nominal_length_attribute(const reduced_nominal_value_t& op) const override;
};

class data_def_type_CA_CE : public data_def_type
{
public:
data_def_type_CA_CE(char extension);

uint64_t get_nominal_length(const nominal_value_t& op) const override;
uint32_t get_nominal_length_attribute(const nominal_value_t& op) const override;
uint64_t get_nominal_length(const reduced_nominal_value_t& op) const override;
uint32_t get_nominal_length_attribute(const reduced_nominal_value_t& op) const override;
};

class data_def_type_C final : public data_def_type_CA_CE
Expand Down Expand Up @@ -71,8 +71,8 @@ class data_def_type_CU final : public data_def_type
const diagnostic_collector& add_diagnostic,
bool check_nominal) const override;

uint64_t get_nominal_length(const nominal_value_t& op) const override;
uint32_t get_nominal_length_attribute(const nominal_value_t& op) const override;
uint64_t get_nominal_length(const reduced_nominal_value_t& op) const override;
uint32_t get_nominal_length_attribute(const reduced_nominal_value_t& op) const override;
};

class data_def_type_G final : public data_def_type
Expand All @@ -84,8 +84,8 @@ class data_def_type_G final : public data_def_type
const diagnostic_collector& add_diagnostic,
bool check_nominal) const override;

uint64_t get_nominal_length(const nominal_value_t& op) const override;
uint32_t get_nominal_length_attribute(const nominal_value_t& op) const override;
uint64_t get_nominal_length(const reduced_nominal_value_t& op) const override;
uint32_t get_nominal_length_attribute(const reduced_nominal_value_t& op) const override;
};

class data_def_type_X final : public data_def_type
Expand All @@ -97,8 +97,8 @@ class data_def_type_X final : public data_def_type
const diagnostic_collector& add_diagnostic,
bool check_nominal) const override;

uint64_t get_nominal_length(const nominal_value_t& op) const override;
uint32_t get_nominal_length_attribute(const nominal_value_t& op) const override;
uint64_t get_nominal_length(const reduced_nominal_value_t& op) const override;
uint32_t get_nominal_length_attribute(const reduced_nominal_value_t& op) const override;
};

//************* fixed point types *****************
Expand Down Expand Up @@ -143,7 +143,7 @@ class data_def_type_P_Z : public data_def_type
bool check(const data_definition_operand& op,
const diagnostic_collector& add_diagnostic,
bool check_nominal) const override;
int16_t get_implicit_scale(const nominal_value_t& op) const override;
int16_t get_implicit_scale(const reduced_nominal_value_t& op) const override;
};

class data_def_type_P final : public data_def_type_P_Z
Expand All @@ -152,8 +152,8 @@ class data_def_type_P final : public data_def_type_P_Z
data_def_type_P();

protected:
uint64_t get_nominal_length(const nominal_value_t& op) const override;
uint32_t get_nominal_length_attribute(const nominal_value_t& op) const override;
uint64_t get_nominal_length(const reduced_nominal_value_t& op) const override;
uint32_t get_nominal_length_attribute(const reduced_nominal_value_t& op) const override;


int32_t get_integer_attribute_impl(uint32_t length, int32_t scale) const override;
Expand All @@ -165,8 +165,8 @@ class data_def_type_Z final : public data_def_type_P_Z
data_def_type_Z();

protected:
uint64_t get_nominal_length(const nominal_value_t& op) const override;
uint32_t get_nominal_length_attribute(const nominal_value_t& op) const override;
uint64_t get_nominal_length(const reduced_nominal_value_t& op) const override;
uint32_t get_nominal_length_attribute(const reduced_nominal_value_t& op) const override;
int32_t get_integer_attribute_impl(uint32_t length, int32_t scale) const override;
};

Expand Down
Loading