Skip to content

Commit

Permalink
feat: Instruction set versioning support
Browse files Browse the repository at this point in the history
  • Loading branch information
jirimosinger authored Apr 22, 2022
1 parent ce0ba21 commit f9532c5
Show file tree
Hide file tree
Showing 40 changed files with 3,696 additions and 2,713 deletions.
1 change: 1 addition & 0 deletions clients/vscode-hlasmplugin/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- Allow viewing content generated by AINSERT instruction and preprocessors
- Expand the list of associated file extensions
- DB2 preprocessor now supports the VERSION option
- Instruction set versioning support

#### Fixed
- Fixed an issue preventing correct N' attribute evaluation of empty subscript arrays
Expand Down
59 changes: 44 additions & 15 deletions clients/vscode-hlasmplugin/proc_grps_schema
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,50 @@
"asm_options": {
"type": "object",
"description": "List of assembler options",
"properties": {
"SYSPARM": {
"type": "string",
"description": "It specifies the character string the assembler assigns to the &SYSPARM system variable symbol.",
"maxlength": 255
},
"PROFILE": {
"type": "string",
"description": "Profile Member to be copied into the source program."
},
"SYSTEM_ID": {
"type": "string",
"description": "Provides the value for the SYSTEM_ID system variable. Defaults to 'z/OS 02.04.00' when omitted."
}
"properties": {
"OPTABLE": {
"type": "string",
"description": "Specifies the instruction set to use.",
"enum": [
"UNI",
"DOS",
"370",
"XA",
"ESA",
"ZOP",
"ZS1",
"YOP",
"ZS2",
"Z9",
"ZS3",
"Z10",
"ZS4",
"Z11",
"ZS5",
"Z12",
"ZS6",
"Z13",
"ZS7",
"Z14",
"ZS8",
"Z15",
"ZS9"
]
},
"SYSPARM": {
"type": "string",
"description": "Specifies the character string the assembler assigns to the &SYSPARM system variable symbol.",
"maxLength": 255
},
"PROFILE": {
"type": "string",
"description": "Profile Member to be copied into the source program."
},
"SYSTEM_ID": {
"type": "string",
"description": "Provides the value for the SYSTEM_ID system variable. Defaults to 'z/OS 02.04.00' when omitted."
}
}
},
"preprocessor": {
"description": "Defines optional preprocessor pass for open code.",
Expand Down Expand Up @@ -92,7 +121,7 @@
"version": {
"type": "string",
"description": "The DB2 package VERSION string",
"maxlength": 64
"maxLength": 64
}
}
}
Expand Down
1 change: 1 addition & 0 deletions parser_library/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ target_sources(parser_library PRIVATE
ebcdic_encoding.cpp
ebcdic_encoding.h
error_messages.h
instruction_set_version.h
lib_config.cpp
location.h
preprocessor_options.h
Expand Down
1 change: 0 additions & 1 deletion parser_library/src/checking/instruction_checker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ const std::map<std::string_view, std::unique_ptr<assembler_instruction>> assembl
a.add<no_operands>("COM",
{ label_types::OPTIONAL, label_types::ORD_SYMBOL, label_types::SEQUENCE_SYMBOL, label_types::VAR_SYMBOL });
a.add<copy>("COPY", { label_types::OPTIONAL, label_types::SEQUENCE_SYMBOL });
a.add<copy>("COPY", { label_types::OPTIONAL, label_types::SEQUENCE_SYMBOL });
a.add<no_operands>("CSECT",
{ label_types::OPTIONAL, label_types::ORD_SYMBOL, label_types::SEQUENCE_SYMBOL, label_types::VAR_SYMBOL });
a.add<no_operands>("CXD",
Expand Down
2 changes: 1 addition & 1 deletion parser_library/src/checking/instruction_checker.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class assembler_checker final : public instruction_checker
const std::vector<const operand*>& operand_vector,
const range& stmt_range,
const diagnostic_collector& add_diagnostic) const override;
// map of all assembler instruction maes to their representations
// map of all assembler instruction names to their representations
static const std::map<std::string_view,
std::unique_ptr<hlasm_plugin::parser_library::checking::assembler_instruction>>
assembler_instruction_map;
Expand Down
5 changes: 5 additions & 0 deletions parser_library/src/compiler_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

#include <string>

#include "instruction_set_version.h"

// This file contains assembler compiler options definitions.

namespace hlasm_plugin::parser_library {
Expand All @@ -25,6 +27,9 @@ struct asm_option
std::string sysparm;
std::string profile;

static constexpr instruction_set_version instr_set_default = instruction_set_version::UNI;
instruction_set_version instr_set = instr_set_default;

static const std::string system_id_default;
std::string system_id = system_id_default;

Expand Down
22 changes: 22 additions & 0 deletions parser_library/src/config/proc_grps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include "proc_grps.h"

#include "instruction_set_version.h"
#include "nlohmann/json.hpp"

namespace hlasm_plugin::parser_library::config {
Expand Down Expand Up @@ -43,6 +44,8 @@ void from_json(const nlohmann::json& j, library& p)
void to_json(nlohmann::json& j, const assembler_options& p)
{
j = nlohmann::json::object();
if (p.optable.size())
j["OPTABLE"] = p.optable;
if (p.profile.size())
j["PROFILE"] = p.profile;
if (p.sysparm.size())
Expand All @@ -55,6 +58,8 @@ void from_json(const nlohmann::json& j, assembler_options& p)
if (!j.is_object())
throw nlohmann::json::other_error::create(501, "asm_options must be an object.");

if (auto it = j.find("OPTABLE"); it != j.end())
it->get_to(p.optable);
if (auto it = j.find("PROFILE"); it != j.end())
it->get_to(p.profile);
if (auto it = j.find("SYSPARM"); it != j.end())
Expand Down Expand Up @@ -215,6 +220,23 @@ void from_json(const nlohmann::json& j, proc_grps& p)
it->get_to(p.macro_extensions);
}

namespace {
bool optable_valid(std::string_view optable) noexcept
{
#ifdef __cpp_lib_ranges
return optable.size() == 0
|| std::ranges::any_of(instr_set_version_equivalents, [optable](auto item) { return optable == item.first; });
#else
return optable.size() == 0
|| std::any_of(std::begin(instr_set_version_equivalents),
std::end(instr_set_version_equivalents),
[optable](auto item) { return optable == item.first; });
#endif
}
} // namespace

bool assembler_options::valid() const noexcept { return sysparm.size() < 256 && optable_valid(optable); }

namespace {
struct preprocessor_validator
{
Expand Down
3 changes: 2 additions & 1 deletion parser_library/src/config/proc_grps.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,10 @@ struct assembler_options
{
std::string sysparm;
std::string profile;
std::string optable;
std::string system_id;

bool valid() const noexcept { return sysparm.size() < 256; }
bool valid() const noexcept;
};
void to_json(nlohmann::json& j, const assembler_options& p);
void from_json(const nlohmann::json& j, assembler_options& p);
Expand Down
66 changes: 54 additions & 12 deletions parser_library/src/context/hlasm_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,53 @@ code_scope* hlasm_context::curr_scope() { return &scope_stack_.back(); }

const code_scope* hlasm_context::curr_scope() const { return &scope_stack_.back(); }

hlasm_context::instruction_storage hlasm_context::init_instruction_map(id_storage& ids)
namespace {
constexpr bool operator<=(z_arch_affiliation z_affil, instruction_set_version instr_set)
{
return static_cast<uint16_t>(z_affil) <= static_cast<uint16_t>(instr_set);
}

bool instruction_available(instruction_set_affiliation instr_set_affiliation, instruction_set_version active_instr_set)
{
switch (active_instr_set)
{
case instruction_set_version::UNI:
return instr_set_affiliation.uni;
case instruction_set_version::DOS:
return instr_set_affiliation.dos;
case instruction_set_version::_370:
return instr_set_affiliation._370;
case instruction_set_version::XA:
return instr_set_affiliation.xa;
case instruction_set_version::ESA:
return instr_set_affiliation.esa;
case instruction_set_version::ZOP:
case instruction_set_version::YOP:
case instruction_set_version::Z9:
case instruction_set_version::Z10:
case instruction_set_version::Z11:
case instruction_set_version::Z12:
case instruction_set_version::Z13:
case instruction_set_version::Z14:
case instruction_set_version::Z15:
return instr_set_affiliation.z_arch == z_arch_affiliation::NO_AFFILIATION
? false
: instr_set_affiliation.z_arch <= active_instr_set;
default:
return false;
}
}
} // namespace

hlasm_context::instruction_storage hlasm_context::init_instruction_map(
id_storage& ids, instruction_set_version active_instr_set)
{
hlasm_context::instruction_storage instr_map;
for (const auto& instr : instruction::all_machine_instructions())
{
if (!instruction_available(instr.instr_set_affiliation(), active_instr_set))
continue;

auto id = ids.add(std::string(instr.name()));
instr_map.emplace(id, &instr);
}
Expand All @@ -51,9 +93,13 @@ hlasm_context::instruction_storage hlasm_context::init_instruction_map(id_storag
}
for (const auto& instr : instruction::all_mnemonic_codes())
{
if (!instruction_available(instr.instr_set_affiliation(), active_instr_set))
continue;

auto id = ids.add(std::string(instr.name()));
instr_map.emplace(id, &instr);
}

return instr_map;
}

Expand Down Expand Up @@ -310,14 +356,14 @@ void hlasm_context::add_global_system_vars(code_scope& scope)

bool hlasm_context::is_opcode(id_index symbol) const
{
return macros_.find(symbol) != macros_.end() || instruction_map_.find(symbol) != instruction_map_.end();
return macros_.contains(symbol) || m_instruction_map.contains(symbol);
}

hlasm_context::hlasm_context(std::string file_name, asm_option asm_options, std::shared_ptr<id_storage> init_ids)
: ids_(std::move(init_ids))
, opencode_file_name_(file_name)
, asm_options_(std::move(asm_options))
, instruction_map_(init_instruction_map(*ids_))
, m_instruction_map(init_instruction_map(*ids_, asm_options_.instr_set))
, m_usings(std::make_unique<using_collection>())
, m_active_usings(1, m_usings->remove_all())
, m_statements_remaining(asm_options_.statement_count_limit)
Expand Down Expand Up @@ -405,7 +451,7 @@ id_storage& hlasm_context::ids() { return *ids_; }

std::shared_ptr<id_storage> hlasm_context::ids_ptr() { return ids_; }

const hlasm_context::instruction_storage& hlasm_context::instruction_map() const { return instruction_map_; }
const hlasm_context::instruction_storage& hlasm_context::instruction_map() const { return m_instruction_map; }

processing_stack_t hlasm_context::processing_stack() const
{
Expand Down Expand Up @@ -593,7 +639,7 @@ void hlasm_context::add_mnemonic(id_index mnemo, id_index op_code)

if (auto mac_it = macros_.find(op_code); mac_it != macros_.end())
value.opcode_detail = mac_it->second;
else if (auto instr_it = instruction_map_.find(op_code); instr_it != instruction_map_.end())
else if (auto instr_it = m_instruction_map.find(op_code); instr_it != m_instruction_map.end())
value.opcode_detail = instr_it->second;
else
throw std::invalid_argument("undefined operation code");
Expand All @@ -619,7 +665,7 @@ opcode_t hlasm_context::get_operation_code(id_index symbol) const

if (auto mac_it = macros_.find(symbol); mac_it != macros_.end())
value = opcode_t { symbol, mac_it->second };
else if (auto instr_it = instruction_map_.find(symbol); instr_it != instruction_map_.end())
else if (auto instr_it = m_instruction_map.find(symbol); instr_it != m_instruction_map.end())
value = opcode_t { symbol, instr_it->second };

return value;
Expand Down Expand Up @@ -737,14 +783,10 @@ struct opcode_attr_visitor

C_t hlasm_context::get_opcode_attr(id_index symbol)
{
auto it = instruction_map_.find(symbol);

auto mac_it = macros_.find(symbol);

if (mac_it != macros_.end())
if (auto it = macros_.find(symbol); it != macros_.end())
return "M";

if (it != instruction_map_.end())
if (auto it = m_instruction_map.find(symbol); it != m_instruction_map.end())
{
auto& [opcode, detail] = *it;
return std::visit(opcode_attr_visitor(), detail);
Expand Down
10 changes: 5 additions & 5 deletions parser_library/src/context/hlasm_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ class hlasm_context
asm_option asm_options_;
static constexpr alignment sectalgn = doubleword;

// map of all instruction in HLASM
const instruction_storage instruction_map_;
static instruction_storage init_instruction_map(id_storage& ids);
// map of active instructions in HLASM
const instruction_storage m_instruction_map;
static instruction_storage init_instruction_map(id_storage& ids, instruction_set_version active_instr_set);

// value of system variable SYSNDX
unsigned long SYSNDX_ = 1;
Expand Down Expand Up @@ -156,7 +156,7 @@ class hlasm_context
id_storage& ids();
std::shared_ptr<id_storage> ids_ptr();

// map of instructions
// map of active instructions
const instruction_storage& instruction_map() const;

// field that accessed ordinary assembly context
Expand Down Expand Up @@ -192,7 +192,7 @@ class hlasm_context
void remove_mnemonic(id_index mnemo);
const opcode_map& opcode_mnemo_storage() const;

// checks wheter the symbol is an operation code (is a valid instruction or a mnemonic)
// checks whether the symbol is an operation code (is a valid instruction or a mnemonic)
opcode_t get_operation_code(id_index symbol) const;

// get data attribute value of variable symbol
Expand Down
Loading

0 comments on commit f9532c5

Please sign in to comment.