Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Support START and MHELP instructions #171

Merged
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
- Document outline support
- CNOP instruction implementation (limited)
- START, MHELP instructions

#### Fixed
- Preserve mixed-case labels on macro calls
Expand Down
11 changes: 6 additions & 5 deletions parser_library/src/context/hlasm_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,8 @@ void hlasm_context::add_system_vars_to_scope()
auto val_ndx = std::make_shared<set_symbol<C_t>>(SYSNDX, true, false);

std::string value = std::to_string(SYSNDX_);
int tmp_size = (int)value.size();
for (int i = 0; i < 4 - tmp_size; ++i)
value.insert(value.begin(), '0');
if (auto value_len = value.size(); value_len < 4)
value.insert(0, 4 - value_len, '0');

val_ndx->set_value(std::move(value));
curr_scope()->variables.insert({ SYSNDX, val_ndx });
Expand Down Expand Up @@ -256,7 +255,6 @@ hlasm_context::hlasm_context(std::string file_name, asm_option asm_options, std:
, opencode_file_name_(file_name)
, asm_options_(std::move(asm_options))
, instruction_map_(init_instruction_map())
, SYSNDX_(0)
, ord_ctx(*ids_, *this)
{
scope_stack_.emplace_back();
Expand Down Expand Up @@ -727,16 +725,19 @@ bool hlasm_context::is_in_macro() const { return scope_stack_.back().is_in_macro

macro_invo_ptr hlasm_context::enter_macro(id_index name, macro_data_ptr label_param_data, std::vector<macro_arg> params)
{
assert(SYSNDX_ <= SYSNDX_limit);

macro_def_ptr macro_def = get_macro_definition(name);
assert(macro_def);

auto invo((macro_def->call(std::move(label_param_data), std::move(params), ids().add("SYSLIST"))));
auto invo = macro_def->call(std::move(label_param_data), std::move(params), ids().add("SYSLIST"));
scope_stack_.emplace_back(invo, macro_def);
add_system_vars_to_scope();

visited_files_.insert(macro_def->definition_location.file);

++SYSNDX_;

return invo;
}

Expand Down
19 changes: 17 additions & 2 deletions parser_library/src/context/hlasm_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
#ifndef CONTEXT_HLASM_CONTEXT_H
#define CONTEXT_HLASM_CONTEXT_H

#include <compiler_options.h>
#include <deque>
#include <memory>
#include <set>
#include <vector>

#include "code_scope.h"
#include "compiler_options.h"
#include "operation_code.h"
#include "ordinary_assembly/ordinary_assembly_context.h"
#include "processing_context.h"
Expand Down Expand Up @@ -69,13 +69,17 @@ class hlasm_context

// Compiler options
asm_option asm_options_;
static constexpr alignment sectalgn = doubleword;

// map of all instruction in HLASM
const instruction_storage instruction_map_;
instruction_storage init_instruction_map();

// value of system variable SYSNDX
size_t SYSNDX_;
unsigned long SYSNDX_ = 1;
static constexpr unsigned long SYSNDX_limit_max = 9999999UL;
unsigned long SYSNDX_limit = SYSNDX_limit_max;

void add_system_vars_to_scope();
void add_global_system_vars();

Expand Down Expand Up @@ -252,6 +256,17 @@ class hlasm_context

return val;
}

unsigned long next_sysndx() const { return SYSNDX_; }
void sysndx_limit(unsigned long limit)
{
assert(limit <= SYSNDX_limit_max);
SYSNDX_limit = limit;
}
unsigned long sysndx_limit() const { return SYSNDX_limit; }
static constexpr unsigned long sysndx_limit_max() { return SYSNDX_limit_max; }

alignment section_alignment() const { return sectalgn; }
};

} // namespace hlasm_plugin::parser_library::context
Expand Down
2 changes: 1 addition & 1 deletion parser_library/src/context/id_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@ id_storage::well_known_strings::well_known_strings(std::unordered_set<std::strin
, MACRO(&*ptr.emplace("MACRO").first)
, MEND(&*ptr.emplace("MEND").first)
, MEXIT(&*ptr.emplace("MEXIT").first)
, MHELP(&*ptr.emplace("MHELP").first)
, ASPACE(&*ptr.emplace("ASPACE").first)
, AIF(&*ptr.emplace("AIF").first)
, AGO(&*ptr.emplace("AGO").first)
, ACTR(&*ptr.emplace("ACTR").first)
, AREAD(&*ptr.emplace("AREAD").first)
, empty(&*ptr.emplace("").first)
{}
2 changes: 1 addition & 1 deletion parser_library/src/context/id_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@ class id_storage
const std::string* MACRO;
const std::string* MEND;
const std::string* MEXIT;
const std::string* MHELP;
const std::string* ASPACE;
const std::string* AIF;
const std::string* AGO;
const std::string* ACTR;
const std::string* AREAD;
const std::string* empty;
well_known_strings(std::unordered_set<std::string>& ptr);

} const well_known;
Expand Down
1 change: 1 addition & 0 deletions parser_library/src/context/instruction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ const std::vector<ca_instruction> instruction::ca_instructions = {
{ "MACRO", true },
{ "MEND", true },
{ "MEXIT", true },
{ "MHELP", false },
{ "AEJECT", true },
{ "AREAD", false },
{ "ASPACE", false },
Expand Down
11 changes: 11 additions & 0 deletions parser_library/src/diagnostic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1828,6 +1828,17 @@ diagnostic_op diagnostic_op::error_E071(const range& range)
return diagnostic_op(diagnostic_severity::error, "E071", "Macro prototype expected.", range);
}

diagnostic_op diagnostic_op::error_E072(const range& range)
{
return diagnostic_op(diagnostic_severity::error, "E072", "SYSNDX limit reached, macro call supressed.", range);
}

diagnostic_op diagnostic_op::error_E073(const range& range)
{
return diagnostic_op(
diagnostic_severity::error, "E073", "Illegal START instruction - CSECT already exists.", range);
}

diagnostic_op diagnostic_op::warning_W010(const std::string& message, const range& range)
{
return diagnostic_op(diagnostic_severity::warning, "W010", message + " not expected", range);
Expand Down
4 changes: 4 additions & 0 deletions parser_library/src/diagnostic.h
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,10 @@ struct diagnostic_op

static diagnostic_op error_E071(const range& range);

static diagnostic_op error_E072(const range& range);

static diagnostic_op error_E073(const range& range);

static diagnostic_op warning_W010(const std::string& message, const range& range);

static diagnostic_op warning_W011(const range& range);
Expand Down
13 changes: 7 additions & 6 deletions parser_library/src/parsing/parser_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,26 +143,27 @@ void parser_impl::resolve_expression(std::vector<expressions::ca_expr_ptr>& expr
void parser_impl::resolve_expression(expressions::ca_expr_ptr& expr) const
{
auto [_, opcode] = *proc_status;
if (opcode.value == hlasm_ctx->ids().well_known.SETA || opcode.value == hlasm_ctx->ids().well_known.ACTR
|| opcode.value == hlasm_ctx->ids().well_known.ASPACE || opcode.value == hlasm_ctx->ids().well_known.AGO)
const auto& wk = hlasm_ctx->ids().well_known;
if (opcode.value == wk.SETA || opcode.value == wk.ACTR || opcode.value == wk.ASPACE || opcode.value == wk.AGO
|| opcode.value == wk.MHELP)
resolve_expression(expr, context::SET_t_enum::A_TYPE);
else if (opcode.value == hlasm_ctx->ids().well_known.SETB)
else if (opcode.value == wk.SETB)
{
if (!expr->is_compatible(ca_expression_compatibility::setb))
expr->add_diagnostic(diagnostic_op::error_CE016_logical_expression_parenthesis(expr->expr_range));

resolve_expression(expr, context::SET_t_enum::B_TYPE);
}
else if (opcode.value == hlasm_ctx->ids().well_known.AIF)
else if (opcode.value == wk.AIF)
{
if (!expr->is_compatible(ca_expression_compatibility::aif))
expr->add_diagnostic(diagnostic_op::error_CE016_logical_expression_parenthesis(expr->expr_range));

resolve_expression(expr, context::SET_t_enum::B_TYPE);
}
else if (opcode.value == hlasm_ctx->ids().well_known.SETC)
else if (opcode.value == wk.SETC)
resolve_expression(expr, context::SET_t_enum::C_TYPE);
else if (opcode.value == hlasm_ctx->ids().well_known.AREAD)
else if (opcode.value == wk.AREAD)
{
// aread operand is just enumeration
}
Expand Down
49 changes: 49 additions & 0 deletions parser_library/src/processing/instruction_sets/asm_processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,7 @@ asm_processor::process_table_t asm_processor::create_table(context::hlasm_contex
table.emplace(h_ctx.ids().add("CCW0"), [this](rebuilt_statement stmt) { process_CCW(std::move(stmt)); });
table.emplace(h_ctx.ids().add("CCW1"), [this](rebuilt_statement stmt) { process_CCW(std::move(stmt)); });
table.emplace(h_ctx.ids().add("CNOP"), [this](rebuilt_statement stmt) { process_CNOP(std::move(stmt)); });
table.emplace(h_ctx.ids().add("START"), [this](rebuilt_statement stmt) { process_START(std::move(stmt)); });

return table;
}
Expand Down Expand Up @@ -765,4 +766,52 @@ void asm_processor::process_CNOP(rebuilt_statement stmt)
hlasm_ctx.ord_ctx.reserve_storage_area(0, context::alignment { (size_t)*byte_value, (size_t)*boundary_value });
}


void asm_processor::process_START(rebuilt_statement stmt)
{
if (!check(stmt, hlasm_ctx, checker_, *this))
return;

auto sect_name = find_label_symbol(stmt);

if (std::any_of(hlasm_ctx.ord_ctx.sections().begin(), hlasm_ctx.ord_ctx.sections().end(), [](const auto& s) {
return s->kind == context::section_kind::EXECUTABLE || s->kind == context::section_kind::READONLY;
}))
{
add_diagnostic(diagnostic_op::error_E073(stmt.stmt_range_ref()));
return;
}

if (hlasm_ctx.ord_ctx.symbol_defined(sect_name))
{
add_diagnostic(diagnostic_op::error_E031("symbol", stmt.label_ref().field_range));
return;
}

auto sym_loc = hlasm_ctx.processing_stack().back().proc_location;
sym_loc.pos.column = 0;
hlasm_ctx.ord_ctx.set_section(sect_name, context::section_kind::EXECUTABLE, std::move(sym_loc));

const auto& ops = stmt.operands_ref().value;
if (ops.size() != 1)
return;

auto initial_offset = try_get_abs_value(ops.front().get());
if (!initial_offset.has_value())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Emit a diagnostic here that says "operand has to be absolute expression with all symbols previously defined"? It is a special requirement that will probably never be checked in the checker.

return;

size_t start_section_alignment = hlasm_ctx.section_alignment().boundary;
size_t start_section_alignment_mask = start_section_alignment - 1;

auto offset = initial_offset.value();
if (offset & start_section_alignment_mask)
{
// TODO: generate informational message?
offset += start_section_alignment_mask;
offset &= ~start_section_alignment_mask;
}

hlasm_ctx.ord_ctx.set_available_location_counter_value(start_section_alignment, offset);
}

} // namespace hlasm_plugin::parser_library::processing
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class asm_processor : public low_language_processor
void process_AINSERT(rebuilt_statement stmt);
void process_CCW(rebuilt_statement stmt);
void process_CNOP(rebuilt_statement stmt);
void process_START(rebuilt_statement stmt);

template<checking::data_instr_type instr_type>
void process_data_instruction(rebuilt_statement stmt);
Expand Down
42 changes: 42 additions & 0 deletions parser_library/src/processing/instruction_sets/ca_processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ ca_processor::process_table_t ca_processor::create_table(context::hlasm_context&
table.emplace(h_ctx.ids().add("AREAD"), std::bind(&ca_processor::process_AREAD, this, std::placeholders::_1));
table.emplace(h_ctx.ids().add("ASPACE"), std::bind(&ca_processor::process_ASPACE, this, std::placeholders::_1));
table.emplace(h_ctx.ids().add("AEJECT"), std::bind(&ca_processor::process_AEJECT, this, std::placeholders::_1));
table.emplace(h_ctx.ids().add("MHELP"), [this](const semantics::complete_statement& stmt) { process_MHELP(stmt); });

return table;
}
Expand Down Expand Up @@ -638,3 +639,44 @@ template void ca_processor::process_GBL_LCL<context::C_t, false>(const semantics
template void ca_processor::process_GBL_LCL<context::A_t, true>(const semantics::complete_statement& stmt);
template void ca_processor::process_GBL_LCL<context::B_t, true>(const semantics::complete_statement& stmt);
template void ca_processor::process_GBL_LCL<context::C_t, true>(const semantics::complete_statement& stmt);

void ca_processor::process_MHELP(const semantics::complete_statement& stmt)
{
register_seq_sym(stmt);

const auto& ops = stmt.operands_ref().value;
if (ops.size() > 1)
{
add_diagnostic(diagnostic_op::error_E020("operand", stmt.instruction_ref().field_range));
return;
}
if (ops.size() < 1)
{
add_diagnostic(diagnostic_op::error_E021("operand", stmt.instruction_ref().field_range));
return;
}

const auto* ca_op = ops[0]->access_ca();
assert(ca_op);
if (!ca_op)
return;

uint32_t value = 0;
if (ca_op->kind == semantics::ca_kind::EXPR)
{
value = ca_op->access_expr()->expression->evaluate<context::A_t>(eval_ctx);
}
else if (ca_op->kind == semantics::ca_kind::VAR)
{
auto val = ca_op->access_var()->variable_symbol->evaluate(eval_ctx);
if (val.type == context::SET_t_enum::A_TYPE)
value = val.access_a();
}
else
{
add_diagnostic(diagnostic_op::error_E010("operand", ca_op->operand_range));
}
value &= ~0xffUL; // ignore the option part
if (value & 0xff00UL) // rest is considered only when byte 3 is non-zero
hlasm_ctx.sysndx_limit(std::min((unsigned long)value, context::hlasm_context::sysndx_limit_max()));
}
2 changes: 2 additions & 0 deletions parser_library/src/processing/instruction_sets/ca_processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ class ca_processor : public instruction_processor
void process_AREAD(const semantics::complete_statement& stmt);

void process_empty(const semantics::complete_statement&);

void process_MHELP(const semantics::complete_statement& stmt);
};

} // namespace hlasm_plugin::parser_library::processing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,15 @@ macro_processor::macro_processor(

void macro_processor::process(std::shared_ptr<const processing::resolved_statement> stmt)
{
auto args = get_args(*stmt);
const auto next_sysndx = hlasm_ctx.next_sysndx();
const auto sysndx_limit = hlasm_ctx.sysndx_limit();
if (next_sysndx > sysndx_limit)
{
add_diagnostic(diagnostic_op::error_E072(stmt->stmt_range_ref()));
return;
}

auto args = get_args(*stmt);
hlasm_ctx.enter_macro(stmt->opcode_ref().value, std::move(args.name_param), std::move(args.symbolic_params));
}

Expand Down
2 changes: 1 addition & 1 deletion parser_library/test/debugging/debugger_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ TEST(debugger, test)
}),
},
{ "&SYSECT", "" },
{ "&SYSNDX", "0000" },
{ "&SYSNDX", "0001" },
{ "&SYSSTYP", "" },
{ "&SYSLOC", "" },
{ "&SYSNEST", 1 },
Expand Down
4 changes: 2 additions & 2 deletions parser_library/test/diagnostics_check_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ TEST(diagnostics,
{
std::string input(
R"(
S START 32
ACONTROL NOAFPR,COMPAT(CASE,NOCASE),FLAG(USING0,AL),OPTABLE(ZS5,LIST)
ACONTROL NOTYPECHECK,TYPECHECK(MAGNITUDE,NOREG),OPTABLE(DOS)
ADATA -300,2*100,2,3,'test'
Expand All @@ -256,7 +257,7 @@ TEST(diagnostics,
CEJECT 10/2
CNOP 6,8
COM
CSECT
S CSECT
END ,(MYCOMPIlER,0101,00273)
EXITCTL LISTING,256,*+128,,-2
EXITCTL SOURCE,,,
Expand All @@ -280,7 +281,6 @@ lr OPSYN
RMODE 24
label1 RSECT
SPACE 4
START 34
TITLE 'string' remark
USING (3,3),12
USING 1,3,15,0,0/0
Expand Down
1 change: 1 addition & 0 deletions parser_library/test/processing/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ target_sources(library_test PRIVATE
occurence_collector_test.cpp
opsyn_test.cpp
org_test.cpp
start_test.cpp
)

Loading