Skip to content

Commit

Permalink
feat: Support CATTR, XATTR and R-type constants
Browse files Browse the repository at this point in the history
  • Loading branch information
slavek-kucera authored Jul 16, 2024
1 parent 6fe1ab5 commit 85f51dc
Show file tree
Hide file tree
Showing 22 changed files with 698 additions and 42 deletions.
3 changes: 3 additions & 0 deletions clients/vscode-hlasmplugin/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## ****Unreleased****

#### Added
- Support CATTR, XATTR and R-type constants

## [1.14.0](https://github.com/eclipse-che4z/che-che4z-lsp-for-hlasm/compare/1.13.0...1.14.0) (2024-07-16)

#### Added
Expand Down
2 changes: 1 addition & 1 deletion parser_library/src/checking/asm_instr_check.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -981,7 +981,7 @@ bool expression_instruction::check(std::span<const asm_operand* const> to_check,
}

cattr::cattr(const std::vector<label_types>& allowed_types, std::string_view name_of_instruction)
: assembler_instruction(allowed_types, name_of_instruction, 1, -1) {};
: assembler_instruction(allowed_types, name_of_instruction, 0, -1) {};

bool cattr::check(std::span<const asm_operand* const> to_check,
const range& stmt_range,
Expand Down
61 changes: 61 additions & 0 deletions parser_library/src/context/hlasm_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <memory>
#include <numeric>

#include "diagnostic_tools.h"
#include "ebcdic_encoding.h"
#include "expressions/conditional_assembly/terms/ca_constant.h"
#include "expressions/conditional_assembly/terms/ca_symbol_attribute.h"
Expand Down Expand Up @@ -1074,6 +1075,66 @@ hlasm_context::name_result hlasm_context::try_get_symbol_name(id_index symbol) c
return std::make_pair(true, symbol);
}

bool hlasm_context::register_psect(id_index symbol, id_index psect)
{
auto [_, inserted] = psect_registrations.try_emplace(symbol, psect, processing_stack());
return inserted;
}

namespace {
const section* extract_symbol_base(const symbol* s)
{
if (s->kind() != symbol_value_kind::RELOC)
return nullptr;
const auto& bases = s->value().get_reloc().bases();
if (bases.size() != 1)
return nullptr;
const auto& [base, mult] = bases.front();
if (mult != 1)
return nullptr;
return base.owner;
}

bool psect_compatible_symbol(const symbol* s)
{
auto attr = s->attributes().origin();
return attr != symbol_origin::EQU && attr != symbol_origin::UNKNOWN;
}

bool psect_compatible_section(const section* s)
{
return s->kind == section_kind::EXECUTABLE || s->kind == section_kind::READONLY;
}
} // namespace

void hlasm_context::validate_psect_registrations(diagnostic_consumer& diags)
{
for (const auto& [sym, details] : psect_registrations)
{
const auto& [psect, stack] = details;
const auto* section = ord_ctx.get_section(psect);
if (const symbol * s; !section && (s = ord_ctx.get_symbol(psect)) != nullptr
&& (!psect_compatible_symbol(s) || (section = extract_symbol_base(s)) == nullptr))
{
diags.add_diagnostic(
add_stack_details(diagnostic_op::error_A173_invalid_psect(range(stack.frame().pos)), stack));
continue;
}
if (!section)
{
diags.add_diagnostic(
add_stack_details(diagnostic_op::error_E032(psect.to_string_view(), range(stack.frame().pos)), stack));
continue;
}
if (!psect_compatible_section(section))
{
diags.add_diagnostic(
add_stack_details(diagnostic_op::error_A173_invalid_psect(range(stack.frame().pos)), stack));
continue;
}
}
}

const code_scope& get_current_scope(const context::hlasm_context& ctx) { return ctx.current_scope(); }
variable_symbol* get_var_sym(const expressions::evaluation_context& eval_ctx, id_index name)
{
Expand Down
10 changes: 8 additions & 2 deletions parser_library/src/context/hlasm_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,10 @@

#include <cassert>
#include <deque>
#include <map>
#include <memory>
#include <set>
#include <span>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

Expand Down Expand Up @@ -146,6 +145,8 @@ class hlasm_context

label_storage opencode_sequence_symbols;

std::unordered_map<id_index, std::pair<id_index, processing_stack_t>> psect_registrations;

// return variable symbol from an arbitrary scope
variable_symbol* get_var_sym(id_index name, const code_scope& scope, const system_variable_map& sysvars) const;

Expand Down Expand Up @@ -342,6 +343,11 @@ class hlasm_context
system_variable_map get_system_variables(const code_scope&);

friend variable_symbol* get_var_sym(const expressions::evaluation_context& eval_ctx, id_index name);

bool goff() const noexcept { return asm_options_.sysopt_xobject; }

bool register_psect(id_index symbol, id_index psect);
void validate_psect_registrations(diagnostic_consumer& diags);
};

bool test_symbol_for_read(const variable_symbol* var,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,40 @@ section* ordinary_assembly_context::set_section(
return s;
}

section* ordinary_assembly_context::create_and_set_class(
id_index name, location symbol_location, const library_info& li, section* base, bool partitioned)
{
assert(std::ranges::find(sections_, name, &section::name) == sections_.end());
assert(symbol_can_be_assigned(symbols_, name));

auto* s = set_section(*create_section(name,
section_kind::EXECUTABLE,
{
.owner = last_active_control_section,
.parent = base,
.partitioned = partitioned,
}));
symbols_.insert_or_assign(name,
symbol(name,
s->current_location_counter().current_address(),
symbol_attributes::make_section_attrs(),
std::move(symbol_location),
hlasm_ctx_.processing_stack()));
m_symbol_dependencies->add_defined(name, nullptr, li);

return s;
}

section* ordinary_assembly_context::set_section(section& s)
{
curr_section_ = &s;
if (s.kind != section_kind::DUMMY)
{
if (s.goff.has_value())
last_active_control_section = s.goff->owner;
else
last_active_control_section = &s;
}

return &s;
}
Expand Down Expand Up @@ -370,13 +401,21 @@ std::pair<address, space_ptr> ordinary_assembly_context::reserve_storage_area_sp

section* ordinary_assembly_context::create_section(id_index name, section_kind kind)
{
using enum section_kind;
section* ret = sections_.emplace_back(std::make_unique<section>(name, kind)).get();
if (first_control_section_ == nullptr
&& (kind == section_kind::COMMON || kind == section_kind::EXECUTABLE || kind == section_kind::READONLY))
if (first_control_section_ == nullptr && (kind == COMMON || kind == EXECUTABLE || kind == READONLY))
first_control_section_ = ret;
return ret;
}

section* ordinary_assembly_context::create_section(id_index name, section_kind kind, goff_details details)
{
using enum section_kind;
section* ret = sections_.emplace_back(std::make_unique<section>(name, kind, std::move(details))).get();
if (first_control_section_ == nullptr && (kind == COMMON || kind == EXECUTABLE || kind == READONLY))
first_control_section_ = ret;
return ret;
}

size_t ordinary_assembly_context::current_literal_pool_generation() const { return m_literals->current_generation(); }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,11 @@

#include <memory>
#include <unordered_map>
#include <unordered_set>
#include <variant>
#include <vector>

#include "alignment.h"
#include "dependable.h"
#include "diagnostic.h"
#include "diagnostic_consumer.h"
#include "section.h"
#include "symbol.h"
Expand Down Expand Up @@ -69,6 +67,7 @@ class ordinary_assembly_context

section* curr_section_;
section* first_control_section_ = nullptr;
section* last_active_control_section = nullptr;

// literals
std::unique_ptr<literal_pool> m_literals;
Expand Down Expand Up @@ -117,6 +116,8 @@ class ordinary_assembly_context

// sets current section
section* set_section(id_index name, section_kind kind, location symbol_location, const library_info& li);
section* create_and_set_class(
id_index name, location symbol_location, const library_info& li, section* base, bool partitioned);
section* set_section(section& s);

// creates an external section
Expand Down Expand Up @@ -195,11 +196,14 @@ class ordinary_assembly_context

opcode_generation current_opcode_generation() const;

section* get_last_active_control_section() const { return last_active_control_section; }

private:
void create_private_section();
std::pair<address, space_ptr> reserve_storage_area_space(
size_t length, alignment align, const dependency_evaluation_context& dep_ctx, const library_info& li);
section* create_section(id_index name, section_kind kind);
section* create_section(id_index name, section_kind kind, goff_details details);

friend class ordinary_assembly_dependency_solver;
};
Expand Down
9 changes: 9 additions & 0 deletions parser_library/src/context/ordinary_assembly/section.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ section::section(id_index name, section_kind kind)
curr_loctr_ = loctrs_.back().get();
}

section::section(id_index name, section_kind kind, goff_details details)
: name(name)
, kind(kind)
, goff(std::move(details))
{
loctrs_.emplace_back(std::make_unique<location_counter>(name, *this, loctr_kind::STARTING));
curr_loctr_ = loctrs_.back().get();
}

location_counter& section::set_location_counter(id_index loctr_name)
{
auto tmp = std::ranges::find(loctrs_, loctr_name, &location_counter::name);
Expand Down
15 changes: 14 additions & 1 deletion parser_library/src/context/ordinary_assembly/section.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
#ifndef CONTEXT_SECTION_H
#define CONTEXT_SECTION_H

#include <cstdint>
#include <memory>
#include <optional>
#include <vector>

#include "../id_index.h"
Expand All @@ -24,7 +26,7 @@ namespace hlasm_plugin::parser_library::context {

class location_counter;

enum class section_kind
enum class section_kind : std::uint8_t
{
DUMMY,
COMMON,
Expand All @@ -34,6 +36,15 @@ enum class section_kind
WEAK_EXTERNAL,
};

class section;

struct goff_details
{
section* owner;
section* parent;
bool partitioned;
};

// class representing section (CSECT/DSECT ...)
class section
{
Expand All @@ -45,11 +56,13 @@ class section
// unique identifier
const id_index name;
const section_kind kind;
const std::optional<goff_details> goff;

// access list of location counters
const std::vector<std::unique_ptr<location_counter>>& location_counters() const;

section(id_index name, section_kind kind);
section(id_index name, section_kind kind, goff_details details);

// sets current location counter
location_counter& set_location_counter(id_index loctr_name);
Expand Down
40 changes: 40 additions & 0 deletions parser_library/src/diagnostic_op.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,46 @@ diagnostic_op diagnostic_op::error_A165_POP_USING(const range& range)
return diagnostic_op(diagnostic_severity::error, "A165", "Illegal POP USING - stack is empty.", range);
}

diagnostic_op diagnostic_op::error_A166_GOFF_required(const range& range)
{
return diagnostic_op(diagnostic_severity::error, "A166", "GOFF/XOBJECT option is required", range);
}

diagnostic_op diagnostic_op::error_A167_CATTR_label(const range& range)
{
return diagnostic_op(diagnostic_severity::error, "A167", "Valid class name required", range);
}

diagnostic_op diagnostic_op::error_A168_XATTR_label(const range& range)
{
return diagnostic_op(diagnostic_severity::error, "A168", "External symbol name required", range);
}

diagnostic_op diagnostic_op::error_A169_no_section(const range& range)
{
return diagnostic_op(diagnostic_severity::error, "A169", "Executable section must be started", range);
}

diagnostic_op diagnostic_op::error_A170_section_type_mismatch(const range& range)
{
return diagnostic_op(diagnostic_severity::error, "A170", "Section type mismatch", range);
}

diagnostic_op diagnostic_op::warn_A171_operands_ignored(const range& range)
{
return diagnostic_op(diagnostic_severity::warning, "A171", "Operands ignored", range);
}

diagnostic_op diagnostic_op::warn_A172_psect_redefinition(const range& range)
{
return diagnostic_op(diagnostic_severity::warning, "A172", "PSECT cannot be set multiple times", range);
}

diagnostic_op diagnostic_op::error_A173_invalid_psect(const range& range)
{
return diagnostic_op(diagnostic_severity::error, "A173", "Invalid PSECT symbol", range);
}

diagnostic_op diagnostic_op::error_A200_SCOPE_param(std::string_view instr_name, const range& range)
{
return diagnostic_op(diagnostic_severity::error,
Expand Down
16 changes: 16 additions & 0 deletions parser_library/src/diagnostic_op.h
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,22 @@ struct diagnostic_op

static diagnostic_op error_A165_POP_USING(const range& range);

static diagnostic_op error_A166_GOFF_required(const range& range);

static diagnostic_op error_A167_CATTR_label(const range& range);

static diagnostic_op error_A168_XATTR_label(const range& range);

static diagnostic_op error_A169_no_section(const range& range);

static diagnostic_op error_A170_section_type_mismatch(const range& range);

static diagnostic_op warn_A171_operands_ignored(const range& range);

static diagnostic_op warn_A172_psect_redefinition(const range& range);

static diagnostic_op error_A173_invalid_psect(const range& range);

// operand parameters

static diagnostic_op error_A200_SCOPE_param(std::string_view instr_name, const range& range);
Expand Down
Loading

0 comments on commit 85f51dc

Please sign in to comment.