/* -*- mesa-c++ -*- * * Copyright (c) 2022 Collabora LTD * * Author: Gert Wollny * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * on the rights to use, copy, modify, merge, publish, distribute, sub * license, and/or sell copies of the Software, and to permit persons to whom * the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "sfn_instr_controlflow.h" #include namespace r600 { ControlFlowInstr::ControlFlowInstr(CFType type): m_type(type) { } bool ControlFlowInstr::do_ready() const { /* Have to rework this, but the CF should always */ return true; } bool ControlFlowInstr::is_equal_to(const ControlFlowInstr& rhs) const { return m_type == rhs.m_type; } void ControlFlowInstr::accept(ConstInstrVisitor& visitor) const { visitor.visit(*this); } void ControlFlowInstr::accept(InstrVisitor& visitor) { visitor.visit(this); } void ControlFlowInstr::do_print(std::ostream& os) const { switch (m_type) { case cf_else: os << "ELSE"; break; case cf_endif: os << "ENDIF";break; case cf_loop_begin: os << "LOOP_BEGIN"; break; case cf_loop_end: os << "LOOP_END"; break; case cf_loop_break: os << "BREAK"; break; case cf_loop_continue: os << "CONTINUE"; break; case cf_wait_ack: os << "WAIT_ACK"; break; default: unreachable("Unknown CF type"); } } Instr::Pointer ControlFlowInstr::from_string(std::string type_str) { if (type_str == "ELSE") return new ControlFlowInstr(cf_else); else if (type_str == "ENDIF") return new ControlFlowInstr(cf_endif); else if (type_str == "LOOP_BEGIN") return new ControlFlowInstr(cf_loop_begin); else if (type_str == "LOOP_END") return new ControlFlowInstr(cf_loop_end); else if (type_str == "BREAK") return new ControlFlowInstr(cf_loop_break); else if (type_str == "CONTINUE") return new ControlFlowInstr(cf_loop_continue); else if (type_str == "WAIT_ACK") return new ControlFlowInstr(cf_wait_ack); else return nullptr; } int ControlFlowInstr::nesting_corr() const { switch (m_type) { case cf_else: case cf_endif: case cf_loop_end: return -1; default: return 0; } } int ControlFlowInstr::nesting_offset() const { switch (m_type) { case cf_endif: case cf_loop_end: return -1; case cf_loop_begin: return 1; default: return 0; } } IfInstr::IfInstr(AluInstr *pred): m_predicate(pred) { assert(pred); } IfInstr::IfInstr(const IfInstr& orig) { m_predicate = new AluInstr(*orig.m_predicate); } bool IfInstr::is_equal_to(const IfInstr& rhs) const { return m_predicate->equal_to(*rhs.m_predicate); } void IfInstr::accept(ConstInstrVisitor& visitor) const { visitor.visit(*this); } void IfInstr::accept(InstrVisitor& visitor) { visitor.visit(this); } bool IfInstr::replace_source(PRegister old_src, PVirtualValue new_src) { return m_predicate->replace_source(old_src, new_src); } bool IfInstr::do_ready() const { return m_predicate->ready(); } void IfInstr::forward_set_scheduled() { m_predicate->set_scheduled(); } void IfInstr::forward_set_blockid(int id, int index) { m_predicate->set_blockid(id, index); } void IfInstr::do_print(std::ostream& os) const { os << "IF (( " << *m_predicate << " ))"; } void IfInstr::set_predicate(AluInstr *new_predicate) { m_predicate = new_predicate; m_predicate->set_blockid(block_id(), index()); } Instr::Pointer IfInstr::from_string(std::istream &is, ValueFactory& value_factory) { std::string pred_start; is >> pred_start; if (pred_start != "((") return nullptr; char buf[2048]; is.get(buf, 2048, ')'); std::string pred_end; is >> pred_end; if (pred_end != "))") { return nullptr; } std::istringstream bufstr(buf); std::string instr_type; bufstr >> instr_type; if (instr_type != "ALU") return nullptr; auto pred = AluInstr::from_string(bufstr, value_factory, nullptr); return new IfInstr(static_cast(pred)); } }