Skip to content

Commit

Permalink
constexpr all the instructions
Browse files Browse the repository at this point in the history
  • Loading branch information
slavek-kucera committed Feb 7, 2022
1 parent 2d0a11e commit 88b1328
Show file tree
Hide file tree
Showing 15 changed files with 1,357 additions and 1,182 deletions.
2 changes: 1 addition & 1 deletion parser_library/src/checking/instruction_checker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ bool machine_checker::check(std::string_view instruction_name,

// instruction is a mnemonic instruction
if (auto m = context::instruction::find_mnemonic_codes(instruction_name))
mach_name = m->instruction->name();
mach_name = m->instruction()->name();

return context::instruction::get_machine_instructions(mach_name).check(
instruction_name, ops, stmt_range, add_diagnostic);
Expand Down
10 changes: 5 additions & 5 deletions parser_library/src/context/hlasm_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,19 @@ hlasm_context::instruction_storage hlasm_context::init_instruction_map()
auto id = ids().add(std::string(instr.name()));
instr_map.emplace(id, &instr);
}
for (const auto& [name, instr] : instruction::all_assembler_instructions())
for (const auto& instr : instruction::all_assembler_instructions())
{
auto id = ids().add(std::string(name));
auto id = ids().add(std::string(instr.name()));
instr_map.emplace(id, &instr);
}
for (const auto& instr : instruction::all_ca_instructions())
{
auto id = ids().add(std::string(instr.name));
auto id = ids().add(std::string(instr.name()));
instr_map.emplace(id, &instr);
}
for (const auto& [name, instr] : instruction::all_mnemonic_codes())
for (const auto& instr : instruction::all_mnemonic_codes())
{
auto id = ids().add(std::string(name));
auto id = ids().add(std::string(instr.name()));
instr_map.emplace(id, &instr);
}
return instr_map;
Expand Down
2,324 changes: 1,215 additions & 1,109 deletions parser_library/src/context/instruction.cpp

Large diffs are not rendered by default.

128 changes: 98 additions & 30 deletions parser_library/src/context/instruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -341,49 +341,117 @@ class machine_instruction
const diagnostic_collector& add_diagnostic) const; // input vector is the vector of the actual incoming values
};

struct ca_instruction
class ca_instruction
{
std::string_view name;
bool operandless;
inline_string<6> m_name;
bool m_operandless;

public:
constexpr ca_instruction(std::string_view n, bool opless)
: m_name(n)
, m_operandless(opless)
{}

constexpr auto name() const { return m_name.to_string_view(); }
constexpr auto operandless() const { return m_operandless; }
};

// representation of mnemonic codes for machine instructions
struct mnemonic_code
class mnemonic_code
{
static unsigned char generate_reladdr_bitmask(
const machine_instruction* instruction, const std::vector<std::pair<size_t, size_t>>& replaced);
const machine_instruction* m_instruction;

mnemonic_code(const machine_instruction* instr, std::vector<std::pair<size_t, size_t>> replaced)
: instruction(instr)
, replaced(replaced)
, reladdr_mask(generate_reladdr_bitmask(instr, replaced)) {};
// first goes place, then value
std::array<std::pair<unsigned char, unsigned char>, 3> m_replaced;
unsigned char m_replaced_count;

const machine_instruction* instruction;
reladdr_transform_mask m_reladdr_mask;

// first goes place, then value
std::vector<std::pair<size_t, size_t>> replaced;
inline_string<9> m_name;

// Generates a bitmask for an arbitrary mnemonit indicating which operands
// are of the RI type (and therefore are modified by transform_reloc_imm_operands)
static constexpr unsigned char generate_reladdr_bitmask(const machine_instruction* instruction,
std::initializer_list<const std::pair<unsigned char, unsigned char>> replaced)
{
unsigned char result = 0;

decltype(result) top_bit = 1 << (std::numeric_limits<decltype(result)>::digits - 1);

auto replaced_b = replaced.begin();
auto const replaced_e = replaced.end();

size_t position = 0;
for (const auto& op : instruction->operands())
{
if (replaced_b != replaced_e && position == replaced_b->first)
{
++replaced_b;
++position;
continue;
}

if (op.identifier.type == checking::machine_operand_type::RELOC_IMM)
result |= top_bit;
top_bit >>= 1;

reladdr_transform_mask reladdr_mask;
++position;
}
return result;
}

size_t operand_count() const
public:
constexpr mnemonic_code(std::string_view name,
const machine_instruction* instr,
std::initializer_list<const std::pair<unsigned char, unsigned char>> replaced)
: m_instruction(instr)
, m_replaced {}
, m_replaced_count((unsigned char)replaced.size())
, m_reladdr_mask(generate_reladdr_bitmask(instr, replaced))
, m_name(name)
{
return instruction->operands().size() + instruction->optional_operand_count() - replaced.size();
assert(replaced.size() <= m_replaced.size());
size_t i = 0;
for (const auto& r : replaced)
m_replaced[i++] = r;
};

constexpr const machine_instruction* instruction() const { return m_instruction; }
constexpr std::span<const std::pair<unsigned char, unsigned char>> replaced_operands() const
{
return { m_replaced.data(), m_replaced_count };
}
constexpr size_t operand_count() const
{
return m_instruction->operands().size() + m_instruction->optional_operand_count() - m_replaced_count;
}
constexpr reladdr_transform_mask reladdr_mask() const { return m_reladdr_mask; }
constexpr std::string_view name() const { return m_name.to_string_view(); }
};

// machine instruction common representation
struct assembler_instruction
class assembler_instruction
{
int min_operands;
int max_operands; // -1 in case there is no max value
bool has_ord_symbols;
std::string description; // used only for hover and completion

assembler_instruction(int min_operands, int max_operands, bool has_ord_symbols, std::string description)
: min_operands(min_operands)
, max_operands(max_operands)
, has_ord_symbols(has_ord_symbols)
, description(std::move(description)) {};
inline_string<11> m_name;
bool m_has_ord_symbols;
int m_min_operands;
int m_max_operands; // -1 in case there is no max value
std::string_view m_description; // used only for hover and completion

public:
constexpr assembler_instruction(
std::string_view name, int min_operands, int max_operands, bool has_ord_symbols, std::string_view description)
: m_name(name)
, m_has_ord_symbols(has_ord_symbols)
, m_min_operands(min_operands)
, m_max_operands(max_operands)
, m_description(std::move(description)) {};

constexpr auto name() const { return m_name.to_string_view(); }
constexpr auto has_ord_symbols() const { return m_has_ord_symbols; }
constexpr auto min_operands() const { return m_min_operands; }
constexpr auto max_operands() const { return m_max_operands; }
constexpr auto description() const { return m_description; }
};

// static class holding string names of instructions with theirs additional info
Expand All @@ -397,19 +465,19 @@ class instruction

static const ca_instruction& get_ca_instructions(std::string_view name);
static const ca_instruction* find_ca_instructions(std::string_view name);
static const std::vector<ca_instruction>& all_ca_instructions();
static std::span<const ca_instruction> all_ca_instructions();

static const assembler_instruction& get_assembler_instructions(std::string_view name);
static const assembler_instruction* find_assembler_instructions(std::string_view name);
static const std::map<std::string_view, assembler_instruction>& all_assembler_instructions();
static std::span<const assembler_instruction> all_assembler_instructions();

static const machine_instruction& get_machine_instructions(std::string_view name);
static const machine_instruction* find_machine_instructions(std::string_view name);
static std::span<const machine_instruction> all_machine_instructions();

static const mnemonic_code& get_mnemonic_codes(std::string_view name);
static const mnemonic_code* find_mnemonic_codes(std::string_view name);
static const std::map<std::string_view, mnemonic_code>& all_mnemonic_codes();
static std::span<const mnemonic_code> all_mnemonic_codes();

static std::string_view mach_format_to_string(mach_format);
};
Expand Down
6 changes: 3 additions & 3 deletions parser_library/src/context/operation_code.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@
#include "macro.h"

namespace hlasm_plugin::parser_library::context {
struct ca_instruction;
struct assembler_instruction;
class ca_instruction;
class assembler_instruction;
class machine_instruction;
struct mnemonic_code;
class mnemonic_code;

// structure that represents operation code of an instruction
struct opcode_t
Expand Down
31 changes: 15 additions & 16 deletions parser_library/src/lsp/completion_item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,25 +99,24 @@ const std::set<completion_item_s, completion_item_s::label_comparer> completion_
completion_item_kind::mach_instr);
}

for (const auto& [instr_name, asm_instr] : instruction::all_assembler_instructions())
for (const auto& asm_instr : instruction::all_assembler_instructions())
{
std::stringstream doc_ss(" ");
std::stringstream detail_ss("");

// int min_op = asm_instr.second.min_operands;
// int max_op = asm_instr.second.max_operands;
std::string description = asm_instr.description;

detail_ss << instr_name << " " << description;
detail_ss << asm_instr.name() << " " << asm_instr.description();
doc_ss << "Assembler instruction";
result.emplace(std::string(instr_name),
result.emplace(std::string(asm_instr.name()),
detail_ss.str(),
std::string(instr_name) + " " /*+ description*/,
std::string(asm_instr.name()) + " " /*+ description*/,
doc_ss.str(),
completion_item_kind::asm_instr);
}

for (const auto& [mnemonic_name, mnemonic_instr] : instruction::all_mnemonic_codes())
for (const auto& mnemonic_instr : instruction::all_mnemonic_codes())
{
std::stringstream doc_ss(" ");
std::stringstream detail_ss("");
Expand All @@ -127,13 +126,13 @@ const std::set<completion_item_s, completion_item_s::label_comparer> completion_
// get mnemonic operands
size_t iter_over_mnem = 0;

const auto& mach_operands = mnemonic_instr.instruction->operands();
auto no_optional = mnemonic_instr.instruction->optional_operand_count();
const auto& mach_operands = mnemonic_instr.instruction()->operands();
auto no_optional = mnemonic_instr.instruction()->optional_operand_count();
bool first = true;
std::vector<std::string> mnemonic_with_operand_ommited = { "VNOT", "NOTR", "NOTGR" };


auto replaces = mnemonic_instr.replaced;
auto replaces = mnemonic_instr.replaced_operands();

for (size_t i = 0; i < mach_operands.size(); i++)
{
Expand All @@ -157,7 +156,7 @@ const std::set<completion_item_s, completion_item_s::label_comparer> completion_
subs_ops_mnems << ",";
if (std::find(mnemonic_with_operand_ommited.begin(),
mnemonic_with_operand_ommited.end(),
mnemonic_name)
mnemonic_instr.name())
!= mnemonic_with_operand_ommited.end())
{
subs_ops_mnems << mach_operands[i - 1].to_string();
Expand Down Expand Up @@ -212,22 +211,22 @@ const std::set<completion_item_s, completion_item_s::label_comparer> completion_
first = false;
}
detail_ss << "Operands: " + subs_ops_nomnems.str();
doc_ss << "Mnemonic code for " << mnemonic_instr.instruction->name() << " instruction" << std::endl
doc_ss << "Mnemonic code for " << mnemonic_instr.instruction()->name() << " instruction" << std::endl
<< "Substituted operands: " << subs_ops_mnems.str() << std::endl
<< "Instruction format: "
<< instruction::mach_format_to_string(mnemonic_instr.instruction->format());
result.emplace(std::string(mnemonic_name),
<< instruction::mach_format_to_string(mnemonic_instr.instruction()->format());
result.emplace(std::string(mnemonic_instr.name()),
detail_ss.str(),
std::string(mnemonic_name) + " " + subs_ops_nomnems.str(),
std::string(mnemonic_instr.name()) + " " + subs_ops_nomnems.str(),
doc_ss.str(),
completion_item_kind::mach_instr);
}

for (const auto& ca_instr : instruction::all_ca_instructions())
{
result.emplace(std::string(ca_instr.name),
result.emplace(std::string(ca_instr.name()),
"",
std::string(ca_instr.name),
std::string(ca_instr.name()),
"Conditional Assembly",
completion_item_kind::ca_instr);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,7 @@ void asm_processor::process(std::shared_ptr<const processing::resolved_statement
for (auto& op : rebuilt_stmt.operands_ref().value)
{
auto tmp = context::instruction::find_assembler_instructions(*rebuilt_stmt.opcode_ref().value);
bool can_have_ord_syms = tmp ? tmp->has_ord_symbols : true;
bool can_have_ord_syms = tmp ? tmp->has_ord_symbols() : true;

if (op->type != semantics::operand_type::EMPTY && can_have_ord_syms
&& op->access_asm()->has_dependencies(dep_solver))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,34 +213,36 @@ low_language_processor::transform_result low_language_processor::transform_mnemo
// the associated mnemonic structure with the given name
auto mnemonic = context::instruction::get_mnemonic_codes(instr_name);
// the machine instruction structure associated with the given instruction name
auto curr_instr = mnemonic.instruction;
auto curr_instr = mnemonic.instruction();

auto replaced = mnemonic.replaced_operands();

// check whether substituted mnemonic values are ok

// check size of mnemonic operands
int diff = (int)curr_instr->operands().size() - (int)operands.size() - (int)mnemonic.replaced.size();
int diff = (int)curr_instr->operands().size() - (int)operands.size() - (int)replaced.size();
if (std::abs(diff) > curr_instr->optional_operand_count())
{
auto curr_diag = diagnostic_op::error_optional_number_of_operands(instr_name,
curr_instr->optional_operand_count(),
(int)curr_instr->operands().size() - (int)mnemonic.replaced.size(),
(int)curr_instr->operands().size() - (int)replaced.size(),
stmt.stmt_range_ref());

add_diagnostic(curr_diag);
return std::nullopt;
}

std::vector<checking::check_op_ptr> substituted_mnems;
for (auto mnem : mnemonic.replaced)
for (auto mnem : replaced)
substituted_mnems.push_back(std::make_unique<checking::one_operand>((int)mnem.second));

std::vector<checking::check_op_ptr> operand_vector;
// create vector of empty operands
for (size_t i = 0; i < curr_instr->operands().size() + curr_instr->optional_operand_count(); i++)
operand_vector.push_back(nullptr);
// add substituted
for (size_t i = 0; i < mnemonic.replaced.size(); i++)
operand_vector[mnemonic.replaced[i].first] = std::move(substituted_mnems[i]);
for (size_t i = 0; i < replaced.size(); i++)
operand_vector[replaced[i].first] = std::move(substituted_mnems[i]);
// add other
size_t real_op_idx = 0;
for (size_t j = 0; j < operand_vector.size() && real_op_idx < operands.size(); j++)
Expand Down Expand Up @@ -302,7 +304,7 @@ checking::check_op_ptr low_language_processor::get_check_op(const semantics::ope
const auto& ev_op = dynamic_cast<const semantics::evaluable_operand&>(*op);

auto tmp = context::instruction::find_assembler_instructions(*stmt.opcode_ref().value);
bool can_have_ord_syms = tmp ? tmp->has_ord_symbols : true;
bool can_have_ord_syms = tmp ? tmp->has_ord_symbols() : true;

if (can_have_ord_syms && ev_op.has_dependencies(dep_solver))
{
Expand All @@ -314,7 +316,7 @@ checking::check_op_ptr low_language_processor::get_check_op(const semantics::ope

if (auto mach_op = dynamic_cast<const semantics::machine_operand*>(&ev_op))
{
const auto* instr = mnemonic ? mnemonic->instruction
const auto* instr = mnemonic ? mnemonic->instruction()
: &context::instruction::get_machine_instructions(*stmt.opcode_ref().value);
if (op_position < instr->operands().size())
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ void mach_processor::process(std::shared_ptr<const processing::resolved_statemen

const auto& mach_instr = [](const std::string& name) {
if (auto mnemonic = context::instruction::find_mnemonic_codes(name))
return *mnemonic->instruction;
return *mnemonic->instruction();
else
return context::instruction::get_machine_instructions(name);
}(*stmt->opcode_ref().value);
Expand Down
4 changes: 2 additions & 2 deletions parser_library/src/processing/op_code.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ inline unsigned char get_reladdr_bitmask(context::id_index id)
return p_instr->reladdr_mask().mask();

if (auto p_mnemo = context::instruction::find_mnemonic_codes(*id))
return p_mnemo->reladdr_mask.mask();
return p_mnemo->reladdr_mask().mask();

return 0;
}
Expand All @@ -41,7 +41,7 @@ unsigned char processing_status_cache_key::generate_loctr_len(context::id_index
return static_cast<unsigned char>(p_instr->size_in_bits() / 8);

if (auto p_mnemo = context::instruction::find_mnemonic_codes(*id))
return static_cast<unsigned char>(p_mnemo->instruction->size_in_bits() / 8);
return static_cast<unsigned char>(p_mnemo->instruction()->size_in_bits() / 8);
}
return 1;
}
Expand Down
Loading

0 comments on commit 88b1328

Please sign in to comment.