Skip to content

Commit

Permalink
feat: Support O and T attributes in machine expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
slavek-kucera authored Sep 5, 2022
1 parent ad2af4b commit 2ab7dde
Show file tree
Hide file tree
Showing 30 changed files with 410 additions and 151 deletions.
1 change: 1 addition & 0 deletions clients/vscode-hlasmplugin/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#### Added
- Add support for z16 instructions
- Enhance documentation for instruction mnemonics
- Support O and T attributes in machine expressions

### Fixed

Expand Down
31 changes: 3 additions & 28 deletions parser_library/src/checking/asm_instr_check.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#include "context/common_types.h"
#include "diagnostic_collector.h"
#include "lexing/tools.h"

namespace {
const std::vector<std::string_view> rmode_options = { "24", "31", "64", "ANY" };
Expand Down Expand Up @@ -650,32 +651,6 @@ bool ictl::check(const std::vector<const asm_operand*>& to_check,
external::external(const std::vector<label_types>& allowed_types, std::string_view name_of_instruction)
: assembler_instruction(allowed_types, name_of_instruction, 1, -1) {};

static bool is_valid_symbol_name(std::string_view s, bool extended_names_allowed = true)
{
static constexpr const auto allowed_symbols = []() {
std::array<bool, 256> result = {};
for (unsigned char c = 'a'; c <= 'z'; ++c)
result[c] = true;
for (unsigned char c = 'A'; c <= 'Z'; ++c)
result[c] = true;
for (unsigned char c = '0'; c <= '9'; ++c)
result[c] = true;
result['@'] = true;
result['#'] = true;
result['$'] = true;
result['_'] = true;
return result;
}();
if (s.empty())
return false;
if (s.size() > 63 || !extended_names_allowed && s.size() > 8)
return false;
if (s.front() >= '0' && s.front() <= '9')
return false;
return std::all_of(
s.begin(), s.end(), [](unsigned char c) { return c < allowed_symbols.size() && allowed_symbols[c]; });
}

bool external::check(const std::vector<const asm_operand*>& to_check,
const range& stmt_range,
const diagnostic_collector& add_diagnostic) const
Expand All @@ -695,7 +670,7 @@ bool external::check(const std::vector<const asm_operand*>& to_check,
for (const auto& parameter : complex_op->operand_parameters)
{
if (is_operand_empty(parameter.get()) || is_operand_complex(parameter.get())
|| !is_valid_symbol_name(get_simple_operand(parameter.get())->operand_identifier))
|| !lexing::is_valid_symbol_name(get_simple_operand(parameter.get())->operand_identifier))
{
add_diagnostic(diagnostic_op::error_A129_EXTRN_format(operand->operand_range));
return false;
Expand All @@ -705,7 +680,7 @@ bool external::check(const std::vector<const asm_operand*>& to_check,
else if (auto simple_op = get_simple_operand(operand); simple_op)
{
// check simple external symbol
if (!is_valid_symbol_name(simple_op->operand_identifier))
if (!lexing::is_valid_symbol_name(simple_op->operand_identifier))
{
add_diagnostic(diagnostic_op::error_A129_EXTRN_format(operand->operand_range));
return false;
Expand Down
13 changes: 10 additions & 3 deletions parser_library/src/context/hlasm_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "expressions/conditional_assembly/terms/ca_symbol_attribute.h"
#include "instruction.h"
#include "lexing/lexer.h"
#include "lexing/tools.h"
#include "using.h"

namespace hlasm_plugin::parser_library::context {
Expand Down Expand Up @@ -807,7 +808,7 @@ SET_t hlasm_context::get_attribute_value_ord(data_attr_kind attribute, const sym
return "U";
case data_attr_kind::O:
if (symbol)
return get_opcode_attr(symbol->name);
return get_opcode_attr(symbol->name());
return "U";
default:
if (symbol)
Expand All @@ -829,14 +830,14 @@ struct opcode_attr_visitor
}
};

C_t hlasm_context::get_opcode_attr(id_index symbol)
C_t hlasm_context::get_opcode_attr(id_index symbol) const
{
if (auto it = macros_.find(symbol); it != macros_.end())
return "M";

if (auto it = m_instruction_map.find(symbol); it != m_instruction_map.end())
{
auto& [opcode, detail] = *it;
const auto& [opcode, detail] = *it;
return std::visit(opcode_attr_visitor(), detail);
}

Expand Down Expand Up @@ -901,6 +902,12 @@ macro_invo_ptr hlasm_context::enter_macro(id_index name, macro_data_ptr label_pa
macro_def_ptr macro_def = get_macro_definition(name);
assert(macro_def);

if (label_param_data)
{
if (auto label = label_param_data->get_value(); lexing::is_valid_symbol_name(label))
ord_ctx.symbol_mentioned_on_macro(ids().add(std::move(label)));
}

auto invo = macro_def->call(std::move(label_param_data), std::move(params), ids().add("SYSLIST"));
auto& new_scope = scope_stack_.emplace_back(invo, macro_def);
add_system_vars_to_scope(new_scope);
Expand Down
2 changes: 1 addition & 1 deletion parser_library/src/context/hlasm_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ class hlasm_context
SET_t get_attribute_value_ord(data_attr_kind attribute, id_index symbol);
SET_t get_attribute_value_ord(data_attr_kind attribute, const symbol* symbol);

C_t get_opcode_attr(id_index symbol);
C_t get_opcode_attr(id_index symbol) const;

// gets macro storage
const macro_storage& macros() const;
Expand Down
2 changes: 0 additions & 2 deletions parser_library/src/context/ordinary_assembly/address.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,6 @@ void space::resolve(space_ptr this_space, std::variant<space_ptr, address> value
resolve(std::move(this_space), std::move(std::get<address>(value)));
}

bool space::resolved() const { return resolved_; }

const std::vector<address::base_entry>& address::bases() const { return bases_; }

std::vector<address::base_entry>& address::bases() { return bases_; }
Expand Down
2 changes: 1 addition & 1 deletion parser_library/src/context/ordinary_assembly/address.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ struct space
// common resolver for 2 methods above
static void resolve(space_ptr this_space, std::variant<space_ptr, address> value);

bool resolved() const;
bool resolved() const { return resolved_; }
int resolved_length;
std::vector<address::space_entry> resolved_ptrs;

Expand Down
7 changes: 7 additions & 0 deletions parser_library/src/context/ordinary_assembly/dependable.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#define CONTEXT_DEPENDABLE_H

#include <optional>
#include <variant>

#include "dependency_collector.h"

Expand All @@ -28,6 +29,10 @@ namespace hlasm_plugin::parser_library::context {
class symbol;
struct symbol_value;
struct using_evaluate_result;
struct symbol_candidate
{
bool mentioned;
};

// interface for obtaining symbol from its name
class dependency_solver
Expand All @@ -39,6 +44,8 @@ class dependency_solver
virtual bool using_active(id_index label, const section* sect) const = 0;
virtual using_evaluate_result using_evaluate(
id_index label, const section* owner, int32_t offset, bool long_offset) const = 0;
virtual std::variant<const symbol*, symbol_candidate> get_symbol_candidate(id_index name) const = 0;
virtual std::string get_opcode_attr(id_index symbol) const = 0;

protected:
~dependency_solver() = default;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,20 @@
#include "context/using.h"

namespace hlasm_plugin::parser_library::context {

bool symbol_can_be_assigned(const auto& symbols, auto name)
{
auto it = symbols.find(name);
return it == symbols.end() || std::holds_alternative<macro_label_tag>(it->second);
}

void ordinary_assembly_context::create_private_section()
{
curr_section_ = create_section(id_storage::empty_id, section_kind::EXECUTABLE);
}

const std::vector<std::unique_ptr<section>>& ordinary_assembly_context::sections() const { return sections_; }

const std::unordered_map<id_index, std::variant<symbol, label_tag>>& ordinary_assembly_context::symbols() const
{
return symbols_;
}

ordinary_assembly_context::ordinary_assembly_context(hlasm_context& hlasm_ctx)
: curr_section_(nullptr)
, m_literals(std::make_unique<literal_pool>(hlasm_ctx))
Expand All @@ -48,16 +50,10 @@ ordinary_assembly_context::~ordinary_assembly_context() = default;
bool ordinary_assembly_context::create_symbol(
id_index name, symbol_value value, symbol_attributes attributes, location symbol_location)
{
auto [_, inserted] = symbols_.try_emplace(name,
std::in_place_type_t<symbol>(),
name,
value,
attributes,
std::move(symbol_location),
hlasm_ctx_.processing_stack());
assert(symbol_can_be_assigned(symbols_, name));

if (!inserted)
throw std::runtime_error("symbol name in use");
symbols_.insert_or_assign(
name, symbol(name, value, attributes, std::move(symbol_location), hlasm_ctx_.processing_stack()));

bool ok = true;

Expand All @@ -69,7 +65,7 @@ bool ordinary_assembly_context::create_symbol(

void ordinary_assembly_context::add_symbol_reference(symbol sym)
{
auto [it, _] = symbol_refs_.try_emplace(sym.name, std::move(sym));
auto [it, _] = symbol_refs_.try_emplace(sym.name(), std::move(sym));
symbol_dependencies.add_defined(it->first);
}

Expand Down Expand Up @@ -111,20 +107,20 @@ section* ordinary_assembly_context::set_section(id_index name, section_kind kind
curr_section_ = &**tmp;
else
{
if (name != id_storage::empty_id && symbols_.find(name) != symbols_.end())
throw std::invalid_argument("symbol already defined");

curr_section_ = create_section(name, kind);

auto tmp_addr = curr_section_->current_location_counter().current_address();
symbols_.try_emplace(name,
std::in_place_type_t<symbol>(),
name,
tmp_addr,
symbol_attributes::make_section_attrs(),
std::move(symbol_location),
hlasm_ctx_.processing_stack());
symbol_dependencies.add_defined(name);
if (name != id_storage::empty_id)
{
assert(symbol_can_be_assigned(symbols_, name));
symbols_.insert_or_assign(name,
symbol(name,
tmp_addr,
symbol_attributes::make_section_attrs(),
std::move(symbol_location),
hlasm_ctx_.processing_stack()));
symbol_dependencies.add_defined(name);
}
}

return curr_section_;
Expand All @@ -145,15 +141,15 @@ void ordinary_assembly_context::create_external_section(
}
}();

auto [it, inserted] = symbols_.try_emplace(name,
std::in_place_type_t<symbol>(),
name,
create_section(name, kind)->current_location_counter().current_address(),
attrs,
std::move(symbol_location),
processing_stack);

assert(inserted);
assert(symbol_can_be_assigned(symbols_, name));

symbols_.insert_or_assign(name,
symbol(name,
create_section(name, kind)->current_location_counter().current_address(),
attrs,
std::move(symbol_location),
std::move(processing_stack)));
}

void ordinary_assembly_context::set_location_counter(id_index name, location symbol_location)
Expand All @@ -178,14 +174,14 @@ void ordinary_assembly_context::set_location_counter(id_index name, location sym
{
auto tmp_addr = curr_section_->current_location_counter().current_address();

auto [_, inserted] = symbols_.try_emplace(name,
std::in_place_type_t<symbol>(),
name,
tmp_addr,
symbol_attributes::make_section_attrs(),
std::move(symbol_location),
hlasm_ctx_.processing_stack());
assert(inserted);
assert(symbol_can_be_assigned(symbols_, name));
symbols_.insert_or_assign(name,
symbol(name,
tmp_addr,
symbol_attributes::make_section_attrs(),
std::move(symbol_location),
hlasm_ctx_.processing_stack()));

symbol_dependencies.add_defined(name);
}
}
Expand Down Expand Up @@ -250,7 +246,11 @@ void ordinary_assembly_context::set_available_location_counter_value()
symbol_dependencies.add_dependency(sp, std::make_unique<aggregate_address_resolver>(std::move(addr), 0, 0), {});
}

bool ordinary_assembly_context::symbol_defined(id_index name) const { return symbols_.find(name) != symbols_.end(); }
bool ordinary_assembly_context::symbol_defined(id_index name) const
{
auto it = symbols_.find(name);
return it != symbols_.end() && !std::holds_alternative<macro_label_tag>(it->second);
}

bool ordinary_assembly_context::section_defined(id_index name, section_kind kind) const
{
Expand Down Expand Up @@ -351,15 +351,14 @@ void ordinary_assembly_context::generate_pool(diagnosable_ctx& diags, index_t<us
bool ordinary_assembly_context::is_using_label(id_index name) const
{
auto it = symbols_.find(name);
return it != symbols_.end() && std::holds_alternative<label_tag>(it->second);
return it != symbols_.end() && std::holds_alternative<using_label_tag>(it->second);
}

void ordinary_assembly_context::register_using_label(id_index name)
{
auto [_, inserted] = symbols_.try_emplace(name, std::in_place_type_t<label_tag>());
assert(symbol_can_be_assigned(symbols_, name));

if (!inserted)
throw std::runtime_error("symbol name in use");
symbols_.insert_or_assign(name, using_label_tag {});
}

index_t<using_collection> ordinary_assembly_context::current_using() const { return hlasm_ctx_.using_current(); }
Expand All @@ -377,4 +376,11 @@ bool ordinary_assembly_context::using_label_active(
return usings.is_label_mapping_section(context_id, label, sect);
}

void ordinary_assembly_context::symbol_mentioned_on_macro(id_index name)
{
symbols_.try_emplace(name, macro_label_tag {});
}

void ordinary_assembly_context::start_reporting_label_candidates() { reporting_candidates = true; }

} // namespace hlasm_plugin::parser_library::context
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#define CONTEXT_ORDINARY_ASSEMBLY_CONTEXT_H

#include <unordered_map>
#include <unordered_set>
#include <variant>

#include "alignment.h"
Expand All @@ -38,7 +39,9 @@ class hlasm_context;
class literal_pool;
class location_counter;

struct label_tag
struct using_label_tag
{};
struct macro_label_tag
{};

// class holding complete information about the 'ordinary assembly' (assembler and machine instructions)
Expand All @@ -48,10 +51,13 @@ class ordinary_assembly_context
// list of visited sections
std::vector<std::unique_ptr<section>> sections_;
// list of visited symbols
std::unordered_map<id_index, std::variant<symbol, label_tag>> symbols_;
std::unordered_map<id_index, std::variant<symbol, using_label_tag, macro_label_tag>> symbols_;
// list of lookaheaded symbols
std::unordered_map<id_index, symbol> symbol_refs_;

// ids that were mentioned as macro labels and could have been symbols
bool reporting_candidates = false;

section* curr_section_;
section* first_control_section_ = nullptr;

Expand All @@ -66,7 +72,7 @@ class ordinary_assembly_context
const std::vector<std::unique_ptr<section>>& sections() const;

// access symbols
const std::unordered_map<id_index, std::variant<symbol, label_tag>>& symbols() const;
const auto& symbols() const { return symbols_; }

// access symbol dependency table
symbol_dependency_tables symbol_dependencies;
Expand Down Expand Up @@ -161,6 +167,9 @@ class ordinary_assembly_context
index_t<using_collection> current_using() const;
bool using_label_active(index_t<using_collection> context_id, id_index label, const section* sect) const;

void symbol_mentioned_on_macro(id_index name);
void start_reporting_label_candidates();

private:
void create_private_section();
std::pair<address, space_ptr> reserve_storage_area_space(
Expand Down
Loading

0 comments on commit 2ab7dde

Please sign in to comment.