Skip to content

Commit

Permalink
fix: Avoid duplicate collection of CA instructions in macros
Browse files Browse the repository at this point in the history
  • Loading branch information
slavek-kucera authored Feb 7, 2024
1 parent 8de6e4d commit c628cce
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 72 deletions.
2 changes: 1 addition & 1 deletion parser_library/src/context/literal_pool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ class literal_pool::literal_postponed_statement : public context::postponed_stat
const std::shared_ptr<const expressions::data_definition>& dd, const literal_pool::literal_details& details)
: details(&details)
, op(details.r, {})
, op_code(context::id_index("DC"), instruction_type::ASM)
, op_code(context::id_index("DC"), instruction_type::ASM, nullptr)
{
op.value.push_back(std::make_unique<semantics::data_def_operand_shared>(dd, details.r));
}
Expand Down
1 change: 1 addition & 0 deletions parser_library/src/context/special_instructions.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ inline bool instruction_resolved_during_macro_parsing(id_index name)
id_storage::well_known::AREAD,
id_storage::well_known::ACTR,
id_storage::well_known::AGO,
id_storage::well_known::ANOP,
};

return std::find(std::begin(cached_instr), std::end(cached_instr), name) != std::end(cached_instr);
Expand Down
24 changes: 18 additions & 6 deletions parser_library/src/lsp/symbol_occurrence.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,26 @@ namespace hlasm_plugin::parser_library::lsp {

enum class occurrence_kind : unsigned char
{
ORD,
VAR,
SEQ,
INSTR,
INSTR_LIKE,
COPY_OP,
ORD = 1,
VAR = 2,
SEQ = 4,
INSTR = 8,
INSTR_LIKE = 16,
COPY_OP = 32,
};

constexpr occurrence_kind operator|(occurrence_kind l, occurrence_kind r) noexcept
{
return static_cast<occurrence_kind>(static_cast<unsigned char>(l) | static_cast<unsigned char>(r));
}

constexpr occurrence_kind operator&(occurrence_kind l, occurrence_kind r) noexcept
{
return static_cast<occurrence_kind>(static_cast<unsigned char>(l) & static_cast<unsigned char>(r));
}

constexpr bool any(occurrence_kind e) { return e != occurrence_kind(); }

struct symbol_occurrence
{
occurrence_kind kind;
Expand Down
10 changes: 8 additions & 2 deletions parser_library/src/processing/op_code.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@

#include <utility>

#include "context/id_storage.h"
#include "context/id_index.h"
#include "context/instruction_type.h"
#include "processing_format.h"

namespace hlasm_plugin::parser_library::context {
class macro_definition;
} // namespace hlasm_plugin::parser_library::context

namespace hlasm_plugin::parser_library::processing {

// structure holding resolved operation code of the instruction (solving OPSYNs and so on)
Expand All @@ -29,12 +33,14 @@ struct op_code
op_code()
: type(context::instruction_type::UNDEF)
{}
op_code(context::id_index value, context::instruction_type type)
op_code(context::id_index value, context::instruction_type type, const context::macro_definition* mac_def)
: value(value)
, mac_def(mac_def)
, type(type)
{}

context::id_index value;
const context::macro_definition* mac_def = nullptr;
context::instruction_type type;
};

Expand Down
71 changes: 43 additions & 28 deletions parser_library/src/processing/statement_analyzers/lsp_analyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,44 +81,54 @@ bool lsp_analyzer::analyze(const context::hlasm_statement& statement,
processing_kind proc_kind,
bool evaluated_model)
{
using enum lsp::occurrence_kind;
auto collection_info = get_active_collection(hlasm_ctx_.current_statement_source(), evaluated_model);

const auto* resolved_stmt = statement.access_resolved();
switch (proc_kind)
{
case processing_kind::ORDINARY:
collect_occurrences(lsp::occurrence_kind::ORD, statement, collection_info);
collect_occurrences(lsp::occurrence_kind::INSTR, statement, collection_info);
if (prov_kind != statement_provider_kind::MACRO) // macros already processed during macro def processing
case processing_kind::ORDINARY: {
lsp::occurrence_kind kind = ORD;
if (prov_kind == statement_provider_kind::MACRO)
{
collect_occurrences(lsp::occurrence_kind::VAR, statement, collection_info);
collect_occurrences(lsp::occurrence_kind::SEQ, statement, collection_info);
if (resolved_stmt)
{
collect_var_definition(*resolved_stmt);
collect_copy_operands(*resolved_stmt, collection_info);
}
if (!resolved_stmt)
kind = kind | INSTR;
else if (const auto& instr = resolved_stmt->instruction_ref();
instr.type == semantics::instruction_si_type::ORD
&& !context::instruction_resolved_during_macro_parsing(resolved_stmt->opcode_ref().value))
kind = kind | INSTR;
}
else
kind = kind | INSTR | VAR | SEQ;

collect_occurrences(kind, statement, collection_info);
if (prov_kind != statement_provider_kind::MACRO && resolved_stmt)
{ // macros already processed during macro def processing
collect_var_definition(*resolved_stmt);
collect_copy_operands(*resolved_stmt, collection_info);
}
break;
case processing_kind::MACRO:
}
case processing_kind::MACRO: {
if (resolved_stmt)
update_macro_nest(*resolved_stmt);
if (macro_nest_ > 1)
break; // Do not collect occurrences in nested macros to avoid collecting occurrences multiple times
lsp::occurrence_kind kind {};
if (statement.kind == context::statement_kind::DEFERRED)
collect_occurrences(lsp::occurrence_kind::INSTR_LIKE, statement, collection_info);
kind = INSTR_LIKE;
else if (resolved_stmt)
{
if (const auto& instr = statement.access_resolved()->instruction_ref();
if (const auto& instr = resolved_stmt->instruction_ref();
instr.type == semantics::instruction_si_type::ORD
&& context::instruction_resolved_during_macro_parsing(std::get<context::id_index>(instr.value)))
collect_occurrences(lsp::occurrence_kind::INSTR, statement, collection_info);
&& context::instruction_resolved_during_macro_parsing(resolved_stmt->opcode_ref().value))
kind = INSTR;
}
collect_occurrences(lsp::occurrence_kind::VAR, statement, collection_info);
collect_occurrences(lsp::occurrence_kind::SEQ, statement, collection_info);
collect_occurrences(kind | VAR | SEQ, statement, collection_info);
if (resolved_stmt)
collect_copy_operands(*resolved_stmt, collection_info);
break;
}
default:
break;
}
Expand Down Expand Up @@ -157,7 +167,7 @@ void lsp_analyzer::analyze(const semantics::preprocessor_statement_si& statement
lsp::line_occurence_details& lsp_analyzer::line_details(const range& r, const collection_info_t& ci)
{
if (r.start.line >= ci.line_details->size())
ci.line_details->insert(ci.line_details->end(), r.start.line + 1 - ci.line_details->size(), {});
ci.line_details->resize(r.start.line + 1);
return (*ci.line_details)[r.start.line];
}

Expand Down Expand Up @@ -249,7 +259,7 @@ void lsp_analyzer::collect_occurrences(
}

collect_occurrence(def_stmt->label_ref(), collector);
collect_occurrence(def_stmt->instruction_ref(), collector);
collect_occurrence(def_stmt->instruction_ref(), collector, nullptr);
collect_occurrence(def_stmt->deferred_ref(), collector);
}
else if (auto res_stmt = statement.access_resolved())
Expand All @@ -263,7 +273,7 @@ void lsp_analyzer::collect_occurrences(
}

collect_occurrence(res_stmt->label_ref(), collector);
collect_occurrence(res_stmt->instruction_ref(), collector);
collect_occurrence(res_stmt->instruction_ref(), collector, &res_stmt->opcode_ref());
collect_occurrence(res_stmt->operands_ref(), collector);
}
}
Expand Down Expand Up @@ -308,20 +318,25 @@ void lsp_analyzer::collect_occurrence(const semantics::label_si& label, occurren
}
}

void lsp_analyzer::collect_occurrence(const semantics::instruction_si& instruction, occurrence_collector& collector)
void lsp_analyzer::collect_occurrence(
const semantics::instruction_si& instruction, occurrence_collector& collector, const op_code* op)
{
if (instruction.type == semantics::instruction_si_type::CONC)
collector.get_occurrence(std::get<semantics::concat_chain>(instruction.value));
else if (instruction.type == semantics::instruction_si_type::ORD
&& collector.collector_kind == lsp::occurrence_kind::INSTR)
&& any(collector.collector_kind & lsp::occurrence_kind::INSTR))
{
auto opcode = hlasm_ctx_.get_operation_code(
std::get<context::id_index>(instruction.value)); // TODO: collect the instruction at the right time
if (!opcode.opcode.empty() || opcode.is_macro())
collector.occurrences.emplace_back(opcode.opcode, opcode.get_macro_details(), instruction.field_range);
if (!op)
{
auto opcode = hlasm_ctx_.get_operation_code(std::get<context::id_index>(instruction.value));
if (!opcode.opcode.empty() || opcode.is_macro())
collector.occurrences.emplace_back(opcode.opcode, opcode.get_macro_details(), instruction.field_range);
}
else if (!op->value.empty() && op->type != context::instruction_type::MAC || op->mac_def)
collector.occurrences.emplace_back(op->value, op->mac_def, instruction.field_range);
}
else if (instruction.type == semantics::instruction_si_type::ORD
&& collector.collector_kind == lsp::occurrence_kind::INSTR_LIKE)
&& any(collector.collector_kind & lsp::occurrence_kind::INSTR_LIKE))
{
if (const auto& op = std::get<context::id_index>(instruction.value); !op.empty())
collector.occurrences.emplace_back(lsp::occurrence_kind::INSTR_LIKE, op, instruction.field_range, false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ class lsp_analyzer : public statement_analyzer
void collect_section(const range& r, const collection_info_t& collection_info);

void collect_occurrence(const semantics::label_si& label, occurrence_collector& collector);
void collect_occurrence(const semantics::instruction_si& instruction, occurrence_collector& collector);
void collect_occurrence(
const semantics::instruction_si& instruction, occurrence_collector& collector, const op_code* op);
void collect_occurrence(const semantics::operands_si& operands, occurrence_collector& collector);
void collect_occurrence(const semantics::deferred_operands_si& operands, occurrence_collector& collector);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,25 +99,22 @@ void occurrence_collector::visit(const semantics::macro_operand_string&) {}

void occurrence_collector::get_occurrence(const semantics::variable_symbol& var)
{
if (collector_kind == lsp::occurrence_kind::VAR)
{
if (var.created)
get_occurrence(var.access_created()->created_name);
else
occurrences.emplace_back(
lsp::occurrence_kind::VAR, var.access_basic()->name, var.symbol_range, evaluated_model);
}
if (var.created)
get_occurrence(var.access_created()->created_name);
else if (any(collector_kind & lsp::occurrence_kind::VAR))
occurrences.emplace_back(
lsp::occurrence_kind::VAR, var.access_basic()->name, var.symbol_range, evaluated_model);
}

void occurrence_collector::get_occurrence(const semantics::seq_sym& seq)
{
if (collector_kind == lsp::occurrence_kind::SEQ)
if (any(collector_kind & lsp::occurrence_kind::SEQ))
occurrences.emplace_back(lsp::occurrence_kind::SEQ, seq.name, seq.symbol_range, evaluated_model);
}

void occurrence_collector::get_occurrence(context::id_index ord, const range& ord_range)
{
if (collector_kind == lsp::occurrence_kind::ORD)
if (any(collector_kind & lsp::occurrence_kind::ORD))
occurrences.emplace_back(lsp::occurrence_kind::ORD, ord, ord_range, evaluated_model);
}

Expand All @@ -127,7 +124,7 @@ void occurrence_collector::get_occurrence(const semantics::concat_chain& chain)
{
if (const auto* str = std::get_if<semantics::char_str_conc>(&point.value))
{
if (collector_kind == lsp::occurrence_kind::ORD)
if (any(collector_kind & lsp::occurrence_kind::ORD))
{
auto [valid, name] = hlasm_ctx.try_get_symbol_name(str->value);
if (valid)
Expand All @@ -136,8 +133,7 @@ void occurrence_collector::get_occurrence(const semantics::concat_chain& chain)
}
else if (const auto* var = std::get_if<semantics::var_sym_conc>(&point.value))
{
if (collector_kind == lsp::occurrence_kind::VAR)
get_occurrence(*var->symbol);
get_occurrence(*var->symbol);
}
else if (const auto* sub = std::get_if<semantics::sublist_conc>(&point.value))
{
Expand All @@ -148,7 +144,7 @@ void occurrence_collector::get_occurrence(const semantics::concat_chain& chain)
}
void occurrence_collector::get_occurrence(const semantics::literal_si& lit)
{
if (collector_kind == lsp::occurrence_kind::ORD)
if (any(collector_kind & lsp::occurrence_kind::ORD))
{
lit->get_dd().apply(*this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ class hlasm_context;

namespace hlasm_plugin::parser_library::processing {

class occurrence_collector : public semantics::operand_visitor,
public expressions::mach_expr_visitor,
public expressions::ca_expr_visitor
class occurrence_collector final : public semantics::operand_visitor,
public expressions::mach_expr_visitor,
public expressions::ca_expr_visitor
{
public:
lsp::occurrence_kind collector_kind;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ std::optional<processing_status> macrodef_processor::get_processing_status(
{
id = *instruction;
}
return std::make_pair(format, op_code(id, context::instruction_type::MAC));
return std::make_pair(format, op_code(id, context::instruction_type::MAC, nullptr));
}
else
{
Expand Down Expand Up @@ -131,21 +131,21 @@ processing_status macrodef_processor::get_macro_processing_status(
processing_form::CA,
(*ca_instr)->operandless() ? operand_occurrence::ABSENT : operand_occurrence::PRESENT);

return std::make_pair(format, op_code(code.opcode, context::instruction_type::CA));
return std::make_pair(format, op_code(code.opcode, context::instruction_type::CA, nullptr));
}
else if (code.opcode == context::id_storage::well_known::COPY)
{
processing_format format(processing_kind::MACRO, processing_form::ASM, operand_occurrence::PRESENT);

return std::make_pair(format, op_code(code.opcode, context::instruction_type::ASM));
return std::make_pair(format, op_code(code.opcode, context::instruction_type::ASM, nullptr));
}
}

if (instruction && instruction->empty())
{
processing_format format(processing_kind::MACRO, processing_form::CA, operand_occurrence::ABSENT);

return std::make_pair(format, op_code(context::id_index(), context::instruction_type::CA));
return std::make_pair(format, op_code(context::id_index(), context::instruction_type::CA, nullptr));
}

processing_format format(processing_kind::MACRO, processing_form::DEFERRED);
Expand Down Expand Up @@ -402,7 +402,7 @@ bool macrodef_processor::process_COPY(const resolved_statement& statement)

auto empty = std::make_unique<resolved_statement_impl>(std::move(empty_sem),
processing_status(processing_format(processing_kind::ORDINARY, processing_form::CA, operand_occurrence::ABSENT),
op_code(context::id_storage::well_known::ANOP, context::instruction_type::CA)));
op_code(context::id_storage::well_known::ANOP, context::instruction_type::CA, nullptr)));

result_.definition.push_back(std::move(empty));
add_correct_copy_nest();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,19 +74,19 @@ std::optional<processing_status> ordinary_processor::get_processing_status(
if (!found.has_value())
return std::nullopt;

processing_form f;
context::instruction_type t;
processing_form f = processing_form::UNKNOWN;
context::instruction_type t = context::instruction_type::UNDEF;
const context::macro_definition* mac_ptr = nullptr;
if (found.value())
{
f = processing_form::MAC;
t = hlasm_ctx.find_macro(id) ? context::instruction_type::MAC : context::instruction_type::UNDEF;
}
else
{
f = processing_form::UNKNOWN;
t = context::instruction_type::UNDEF;
if (auto mp = hlasm_ctx.find_macro(id))
{
t = context::instruction_type::MAC;
mac_ptr = mp->get();
}
}
return std::make_pair(processing_format(processing_kind::ORDINARY, f), op_code(id, t));
return std::make_pair(processing_format(processing_kind::ORDINARY, f), op_code(id, t, mac_ptr));
}

void ordinary_processor::process_statement(context::shared_stmt_ptr s)
Expand Down Expand Up @@ -196,7 +196,7 @@ struct processing_status_visitor

processing_status return_value(processing_form f, operand_occurrence o, context::instruction_type t) const
{
return std::make_pair(processing_format(processing_kind::ORDINARY, f, o), op_code(id, t));
return std::make_pair(processing_format(processing_kind::ORDINARY, f, o), op_code(id, t, nullptr));
}

processing_status operator()(const context::assembler_instruction* i) const
Expand Down Expand Up @@ -241,15 +241,15 @@ std::optional<processing_status> ordinary_processor::get_instruction_processing_
if (code.is_macro())
{
return std::make_pair(processing_format(processing_kind::ORDINARY, processing_form::MAC),
op_code(instruction, context::instruction_type::MAC));
op_code(instruction, context::instruction_type::MAC, code.get_macro_details()));
}

if (code.opcode.empty())
{
if (instruction.empty())
return std::make_pair(
processing_format(processing_kind::ORDINARY, processing_form::CA, operand_occurrence::ABSENT),
op_code(context::id_index(), context::instruction_type::CA));
op_code(context::id_index(), context::instruction_type::CA, nullptr));
else
return std::nullopt;
}
Expand Down

0 comments on commit c628cce

Please sign in to comment.