00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 # include "incls/_precompiled.incl"
00025
00026 # ifdef DELTA_COMPILER
00027 # include "incls/_mapConformance.cpp.incl"
00028
00029 void Variable::print() {
00030 if (in_register()) {
00031 std->print("R%d", offset());
00032 } else if (on_stack()) {
00033 std->print("S[%d]", offset());
00034 } else if (is_unused()) {
00035 std->print("UN");
00036 } else if (is_top_of_stack()){
00037 std->print("tos");
00038 } else {
00039 fatal("invalid variable");
00040 }
00041 }
00042
00043
00044 Variable MapConformance::pop_temporary() {
00045 Variable result = Variable::top_of_stack();
00046 if (!_free_register.is_unused()) {
00047 result = _free_register;
00048 _free_register = Variable::unused();
00049 }
00050 return result;
00051 }
00052
00053 void MapConformance::push_temporary(Variable var) {
00054 if (var.in_register()) {
00055 _free_register = var;
00056 }
00057 }
00058
00059 void MapConformance::push(Variable src, int n) {
00060 for (int index = 0; index < n; index++) {
00061 push(src);
00062 }
00063 }
00064 class MappingEntry : public ValueObj {
00065 private:
00066 Variable _reg;
00067 Variable _stack;
00068 public:
00069 MappingEntry(Variable reg, Variable stack) {
00070 _reg = reg;
00071 _stack = stack;
00072 }
00073 Variable reg() { return _reg; }
00074 Variable stack() { return _stack; }
00075
00076 bool has_reg() { return !reg().is_unused(); }
00077 bool has_stack() { return !stack().is_unused(); }
00078
00079 void set_reg(Variable r) { _reg = r; }
00080 void set_stack(Variable s) { _stack = s; }
00081
00082 void print();
00083 };
00084
00085 void MappingEntry::print() {
00086 if (!reg().is_unused()) reg().print();
00087 if (!stack().is_unused()) stack().print();
00088 }
00089
00090 bool operator == (MappingEntry x, MappingEntry y) {
00091 return x.reg() == y.reg() && x.stack() == y.stack();
00092 }
00093
00094 class MappingTask : public ResourceObj {
00095 private:
00096 MappingTask* _next;
00097 MappingTask* _parent;
00098 bool _is_processed;
00099 char* _what_happend;
00100 bool _uses_top_of_stack;
00101 Variable _variable_to_free;
00102 public:
00103 MappingTask(Variable src_register, Variable src_stack, Variable dst_register, Variable dst_stack)
00104 : src(src_register, src_stack), dst(dst_register, dst_stack) {
00105 _next = NULL;
00106 _is_processed = false;
00107 _what_happend = "Nothing";
00108 _parent = NULL;
00109 _uses_top_of_stack = false;
00110 _variable_to_free = Variable::unused();
00111 }
00112
00113 bool is_processed() const { return _is_processed; }
00114 void set_processed(char* reason) {
00115 _is_processed = true;
00116 _what_happend = reason;
00117 }
00118
00119 void append(MappingTask* son) {
00120 assert(!is_processed(), "should be un touched");
00121 assert(!son->is_processed(), "should be un touched");
00122 son->set_next(next());
00123 set_next(son);
00124 son->set_processed("Linked");
00125 }
00126
00127 MappingTask* next() const { return _next; }
00128 void set_next(MappingTask* n) { _next = n; }
00129
00130 MappingTask* parent() const { return _parent; }
00131 void set_parent(MappingTask* p) { _parent = p; }
00132
00133 Variable variable_to_free() const { return _variable_to_free; }
00134 void set_variable_to_free(Variable var) { _variable_to_free = var; }
00135
00136 bool uses_top_of_stack() const { return _uses_top_of_stack; }
00137 void set_uses_top_of_stack(bool b) { _uses_top_of_stack = b; }
00138
00139 MappingEntry src;
00140 MappingEntry dst;
00141
00142 void process_task(MapConformance* mc, MappingTask* p);
00143 void generate_code(MapConformance* mc);
00144
00145 bool target_includes(Variable var);
00146 bool is_dependent(MapConformance* mc, MappingTask* task);
00147 bool in_parent_chain(MappingTask* task);
00148
00149 int number_of_targets();
00150
00151 void print(int index);
00152 };
00153
00154 int MappingTask::number_of_targets() {
00155 int result = 0;
00156 for (MappingTask* current = this; current; current = current->next()) {
00157 if (current->dst.has_reg()) result++;
00158 if (current->dst.has_stack()) result++;
00159 }
00160 return result;
00161 }
00162
00163
00164 bool MappingTask::in_parent_chain(MappingTask* task) {
00165 for (MappingTask* current = this; current; current = current->parent()) {
00166 if (current == task) return true;
00167 }
00168 return false;
00169 }
00170
00171 bool MappingTask::target_includes(Variable var) {
00172 for (MappingTask* current = this; current; current = current->next()) {
00173 if (current->dst.reg() == var || current->dst.stack() == var)
00174 return true;
00175 }
00176 return false;
00177 }
00178
00179
00180 bool MappingTask::is_dependent(MapConformance* mc, MappingTask* task) {
00181
00182
00183 if (this == task) return false;
00184
00185 bool is_reg_dependent = false;
00186 bool is_stack_dependent = false;
00187
00188 if (task->src.has_reg()) {
00189 is_reg_dependent = target_includes(task->src.reg());
00190 }
00191
00192 if (task->src.has_stack()) {
00193 is_stack_dependent = target_includes(task->src.stack());
00194 }
00195
00196 if (is_reg_dependent || is_stack_dependent) {
00197 if (in_parent_chain(task)) {
00198
00199 if (task->src.has_reg()) {
00200 if (task->src.has_stack()) {
00201 task->src.set_stack(Variable::unused());
00202 }
00203 Variable temp = mc->pop_temporary();
00204 if (temp.is_top_of_stack()) {
00205 mc->push(task->src.reg(), number_of_targets());
00206 task->src.set_reg(temp);
00207 task->set_uses_top_of_stack(true);
00208 } else {
00209 mc->move(task->src.reg(), temp);
00210 task->src.set_reg(temp);
00211 task->set_variable_to_free(temp);
00212 }
00213 } else {
00214 Variable temp = mc->pop_temporary();
00215 if (temp.is_top_of_stack()) {
00216 mc->push(task->src.stack(), number_of_targets());
00217 task->src.set_reg(temp);
00218 task->set_uses_top_of_stack(true);
00219 } else {
00220 mc->move(task->src.stack(), temp);
00221 task->src.set_reg(temp);
00222 task->src.set_stack(Variable::unused());
00223 task->set_variable_to_free(temp);
00224 }
00225 }
00226 return false;
00227 }
00228 }
00229
00230 return is_reg_dependent || is_stack_dependent;
00231 }
00232
00233 void MappingTask::process_task(MapConformance* mc, MappingTask* p) {
00234 if (is_processed()) return;
00235
00236
00237 set_parent(p);
00238 for (int index = 0; index < mc->mappings->length(); index++) {
00239 MappingTask* task = mc->mappings->at(index);
00240 if (!task->is_processed() && is_dependent(mc, task)) {
00241 task->process_task(mc, this);
00242 }
00243 }
00244 set_parent(NULL);
00245
00246
00247 generate_code(mc);
00248 mc->push_temporary(variable_to_free());
00249 set_processed("Code has been generated");
00250 }
00251
00252 void MappingTask::generate_code(MapConformance* mc) {
00253 bool uses_temp = false;
00254
00255 if (uses_top_of_stack()) {
00256
00257 for (MappingTask* current = this; current; current = current->next()) {
00258 if(current->dst.has_reg()) {
00259 mc->pop(current->dst.reg());
00260 }
00261 if (dst.has_stack() && !(src.stack() == dst.stack())) {
00262 mc->pop(current->dst.stack());
00263 }
00264 }
00265 } else if (src.has_reg()) {
00266
00267 for (MappingTask* current = this; current; current = current->next()) {
00268 if(current->dst.has_reg()) {
00269 mc->move(src.reg(), current->dst.reg());
00270 }
00271 if (current->dst.has_stack() && !(src.stack() == current->dst.stack())) {
00272 mc->move(src.reg(), current->dst.stack());
00273 }
00274 }
00275 } else {
00276
00277 Variable temp;
00278 for (MappingTask* current = this; current; current = current->next()) {
00279 if(current->dst.has_reg()) temp = current->dst.reg();
00280 }
00281 if (temp.is_unused()) {
00282 uses_temp = true;
00283 temp = mc->pop_temporary();
00284 }
00285 if (temp.in_register()) {
00286
00287 mc->move(src.stack(), temp);
00288 for (MappingTask* current = this; current; current = current->next()) {
00289 if(current->dst.has_reg() && !(current->dst.reg() == temp)) {
00290 mc->move(temp, current->dst.reg());
00291 }
00292 if (current->dst.has_stack() && !(src.stack() == current->dst.stack())) {
00293 mc->move(temp, current->dst.stack());
00294 }
00295 }
00296 if (uses_temp) {
00297 mc->push_temporary(temp);
00298 }
00299 } else {
00300 for (MappingTask* current = this; current; current = current->next()) {
00301 if(current->dst.has_reg()) {
00302 mc->push(src.stack());
00303 mc->pop(current->dst.reg());
00304 }
00305 if (current->dst.has_stack() && !(src.stack() == current->dst.stack())) {
00306 mc->push(src.stack());
00307 mc->pop(current->dst.stack());
00308 }
00309 }
00310 }
00311 }
00312 }
00313
00314 void MappingTask::print(int index) {
00315 std->print(" %2d: ", index);
00316 src.print();
00317 std->print(" -> ");
00318 dst.print();
00319 if (_what_happend != NULL) {
00320 std->set_indentation(35);
00321 std->indent();
00322 std->print("%s", _what_happend);
00323 }
00324 std->cr();
00325 }
00326
00327 MapConformance::MapConformance() {
00328 mappings = new GrowableArray<MappingTask*>(20);
00329 used_variables = NULL;
00330 _free_register.set_unused();
00331 }
00332
00333 void MapConformance::append_mapping(Variable src_register, Variable src_stack, Variable dst_register, Variable dst_stack) {
00334 mappings->append(new MappingTask(src_register, src_stack, dst_register, dst_stack));
00335 }
00336
00337 void MapConformance::generate(Variable free_register1, Variable free_register2) {
00338 this->_free_register = free_register1;
00339
00340 this->used_variables = NEW_RESOURCE_ARRAY(Variable, mappings->length() * 2);
00341 this->number_of_used_variables = 0;
00342
00343 simplify();
00344 process_tasks();
00345
00346 this->_free_register.set_unused();
00347 this->used_variables = NULL;
00348 }
00349
00350 void MapConformance::move(Variable src, Variable dst) {
00351 std->print(" move ");
00352 src.print();
00353 std->print(", ");
00354 dst.print();
00355 std->cr();
00356 }
00357
00358 void MapConformance::push(Variable src) {
00359 std->print(" push ");
00360 src.print();
00361 std->cr();
00362 }
00363
00364 void MapConformance::pop(Variable dst) {
00365 std->print(" pop ");
00366 dst.print();
00367 std->cr();
00368 }
00369
00370 void MapConformance::print() {
00371 std->print_cr("MapConformance");
00372 for (int index = 0; index < mappings->length(); index++) {
00373 mappings->at(index)->print(index);
00374 }
00375 }
00376
00377 bool MapConformance::reduce_noop_task(MappingTask* task) {
00378
00379 bool result = true;
00380
00381 if (task->dst.has_reg() && task->src.reg() != task->dst.reg()) {
00382 result = false;
00383 }
00384
00385 if (task->dst.has_stack() && task->src.stack() != task->dst.stack()) {
00386 result = false;
00387 }
00388
00389 if (result) task->set_processed("Noop");
00390 return result;
00391 }
00392
00393 void MapConformance::simplify() {
00394
00395 for (int x = 0; x < mappings->length(); x++) {
00396 MappingTask* x_task = mappings->at(x);
00397 if (!x_task->is_processed() && !reduce_noop_task(x_task)) {
00398 for (int y = x + 1; y < mappings->length(); y++) {
00399 MappingTask* y_task = mappings->at(y);
00400 if (x_task->src == y_task->src) x_task->append(y_task);
00401 }
00402 }
00403 }
00404 }
00405
00406 void MapConformance::process_tasks() {
00407 for (int index = 0; index < mappings->length(); index++) {
00408 mappings->at(index)->process_task(this, NULL);
00409 }
00410 }
00411
00412 #endif // DELTA_COMPILER