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