1 /* -*- mesa-c++  -*-
2  *
3  * Copyright (c) 2022 Collabora LTD
4  *
5  * Author: Gert Wollny <gert.wollny@collabora.com>
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * on the rights to use, copy, modify, merge, publish, distribute, sub
11  * license, and/or sell copies of the Software, and to permit persons to whom
12  * the Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the next
15  * paragraph) shall be included in all copies or substantial portions of the
16  * Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24  * USE OR OTHER DEALINGS IN THE SOFTWARE.
25  */
26 
27 #include "sfn_instr_controlflow.h"
28 
29 #include <sstream>
30 
31 namespace r600 {
32 
ControlFlowInstr(CFType type)33 ControlFlowInstr::ControlFlowInstr(CFType type):
34    m_type(type)
35 {
36 }
37 
do_ready() const38 bool ControlFlowInstr::do_ready() const
39 {
40    /* Have to rework this, but the CF should always */
41    return true;
42 }
43 
44 
is_equal_to(const ControlFlowInstr& rhs) const45 bool ControlFlowInstr::is_equal_to(const ControlFlowInstr& rhs) const
46 {
47    return m_type == rhs.m_type;
48 }
49 
accept(ConstInstrVisitor& visitor) const50 void ControlFlowInstr::accept(ConstInstrVisitor& visitor) const
51 {
52    visitor.visit(*this);
53 }
54 
accept(InstrVisitor& visitor)55 void ControlFlowInstr::accept(InstrVisitor& visitor)
56 {
57    visitor.visit(this);
58 }
59 
do_print(std::ostream& os) const60 void ControlFlowInstr::do_print(std::ostream& os) const
61 {
62    switch (m_type) {
63    case cf_else: os << "ELSE"; break;
64    case cf_endif: os << "ENDIF";break;
65    case cf_loop_begin: os << "LOOP_BEGIN"; break;
66    case cf_loop_end: os << "LOOP_END"; break;
67    case cf_loop_break: os << "BREAK"; break;
68    case cf_loop_continue: os << "CONTINUE"; break;
69    case cf_wait_ack: os << "WAIT_ACK"; break;
70    default:
71       unreachable("Unknown CF type");
72    }
73 }
74 
from_string(std::string type_str)75 Instr::Pointer ControlFlowInstr::from_string(std::string type_str)
76 {
77    if (type_str == "ELSE")
78       return new ControlFlowInstr(cf_else);
79    else if (type_str == "ENDIF")
80       return new ControlFlowInstr(cf_endif);
81    else if (type_str == "LOOP_BEGIN")
82       return new ControlFlowInstr(cf_loop_begin);
83    else if (type_str == "LOOP_END")
84       return new ControlFlowInstr(cf_loop_end);
85    else if (type_str == "BREAK")
86       return new ControlFlowInstr(cf_loop_break);
87    else if (type_str == "CONTINUE")
88       return new ControlFlowInstr(cf_loop_continue);
89    else if (type_str == "WAIT_ACK")
90       return new ControlFlowInstr(cf_wait_ack);
91    else
92       return nullptr;
93 }
94 
nesting_corr() const95 int ControlFlowInstr::nesting_corr() const
96 {
97    switch (m_type) {
98    case cf_else:
99    case cf_endif:
100    case cf_loop_end: return -1;
101    default:
102       return 0;
103    }
104 }
105 
nesting_offset() const106 int ControlFlowInstr::nesting_offset() const
107 {
108    switch (m_type) {
109    case cf_endif:
110    case cf_loop_end: return -1;
111    case cf_loop_begin: return 1;
112    default:
113       return 0;
114    }
115 }
116 
IfInstr(AluInstr *pred)117 IfInstr::IfInstr(AluInstr *pred):
118    m_predicate(pred)
119 {
120    assert(pred);
121 }
122 
IfInstr(const IfInstr& orig)123 IfInstr::IfInstr(const IfInstr& orig)
124 {
125    m_predicate = new AluInstr(*orig.m_predicate);
126 }
127 
is_equal_to(const IfInstr& rhs) const128 bool IfInstr::is_equal_to(const IfInstr& rhs) const
129 {
130    return m_predicate->equal_to(*rhs.m_predicate);
131 }
132 
accept(ConstInstrVisitor& visitor) const133 void IfInstr::accept(ConstInstrVisitor& visitor) const
134 {
135    visitor.visit(*this);
136 }
137 
accept(InstrVisitor& visitor)138 void IfInstr::accept(InstrVisitor& visitor)
139 {
140    visitor.visit(this);
141 }
142 
replace_source(PRegister old_src, PVirtualValue new_src)143 bool IfInstr::replace_source(PRegister old_src, PVirtualValue new_src)
144 {
145    return m_predicate->replace_source(old_src, new_src);
146 }
147 
do_ready() const148 bool IfInstr::do_ready() const
149 {
150    return m_predicate->ready();
151 }
152 
forward_set_scheduled()153 void IfInstr::forward_set_scheduled()
154 {
155    m_predicate->set_scheduled();
156 }
157 
forward_set_blockid(int id, int index)158 void IfInstr::forward_set_blockid(int id, int index)
159 {
160    m_predicate->set_blockid(id, index);
161 }
162 
do_print(std::ostream& os) const163 void IfInstr::do_print(std::ostream& os) const
164 {
165    os << "IF (( " << *m_predicate << " ))";
166 }
167 
set_predicate(AluInstr *new_predicate)168 void IfInstr::set_predicate(AluInstr *new_predicate)
169 {
170    m_predicate = new_predicate;
171    m_predicate->set_blockid(block_id(), index());
172 }
173 
from_string(std::istream &is, ValueFactory& value_factory)174 Instr::Pointer IfInstr::from_string(std::istream &is, ValueFactory& value_factory)
175 {
176    std::string pred_start;
177    is >> pred_start;
178    if (pred_start != "((")
179       return nullptr;
180    char buf[2048];
181 
182    is.get(buf, 2048, ')');
183    std::string pred_end;
184    is >> pred_end;
185 
186    if (pred_end != "))") {
187       return nullptr;
188    }
189 
190    std::istringstream bufstr(buf);
191 
192    std::string instr_type;
193    bufstr >> instr_type;
194 
195    if (instr_type != "ALU")
196       return nullptr;
197 
198    auto pred = AluInstr::from_string(bufstr, value_factory, nullptr);
199    return new IfInstr(static_cast<AluInstr*>(pred));
200 }
201 
202 }
203