void PrintOptim(char * text) { UInt8 color; color = PrintColor(GREEN); Print(":"); Print(text); PrintColor(color); }
void PrintDelete() { UInt8 color; if (G_VERBOSE) { color = PrintColor(OPTIMIZE_COLOR); Print(" => void"); PrintEOL(); PrintColor(color); } }
void PrintChange(Instr * i) { UInt8 color; if (G_VERBOSE) { color = PrintColor(OPTIMIZE_COLOR); Print(" => "); EmitInstrInline(i); PrintColor(color); } }
void PrintInsert(Instr * i) { UInt8 color; if (G_VERBOSE) { color = PrintColor(OPTIMIZE_COLOR); Print(" + | "); EmitInstrInline(i); PrintColor(color); PrintEOL(); } }
void PrintHeader(UInt8 level, char * text, ...) /* Purpose: Print header to output. */ { char buffer[256]; UInt16 len, half_len; UInt8 color; va_list argp; char * hchr; if (text == NULL) text = ""; va_start(argp, text); vsprintf(buffer, text, argp); va_end(argp); len = StrLen(buffer); if (len > 70) { len = 2; } else { len = 70 - len; } hchr = "="; if (level > 1) hchr = "-"; if (level > 2) hchr = "."; if (G_PRINT_LOG != NULL) { fprintf(G_PRINT_LOG, "<h%d>", level); } color = PrintColor(RED+GREEN); half_len = len / 2; PrintRepeat(hchr, half_len); Print(" "); Print(buffer); Print(" "); PrintRepeat(hchr, len - half_len); PrintColor(color); if (G_PRINT_LOG != NULL) { fprintf(G_PRINT_LOG, "</h%d>", level); } Print("\n"); }
void PrintInit() { #ifdef __Windows__ G_OLD_CP = GetConsoleOutputCP(); SetConsoleOutputCP(CP_UTF8); #endif PrintDestination(stdout); PrintColor(RED+GREEN+BLUE); G_IN_COLOR = false; G_PRINT_LOG = NULL; }
void Card::PrintCard() { // Print out the card: Text Print Sample V = value, C = color, S = suit /* -------- (8) spaces |-VS---| (5) spaces, (2) |, (1) Char |------| |----C-| -------- (8) spaces */ std::cout << "--------" << std::endl; std::cout << "| "; PrintRank(); PrintSuit(); std::cout << " |" << std::endl; std::cout << "| "; std::cout << " |" << std::endl; std::cout << "| "; PrintColor(); std::cout << " |" << std::endl; std::cout << "--------" << std::endl; }
void ProcTranslate(Var * proc) /* Purpose: Translate generic instructions to instructions directly translatable to processor instructions. */ { Instr * i, * first_i, * next_i; InstrBlock * blk; UInt8 step = 0; Bool in_assert; UInt8 color; Loc loc; loc.proc = proc; VERBOSE_NOW = false; if (Verbose(proc)) { VERBOSE_NOW = true; PrintHeader(2, VarName(proc)); } // As first step, we translate all variables stored on register addresses to actual registers for(blk = proc->instr; blk != NULL; blk = blk->next) { for(i = blk->first; i != NULL; i = i->next) { if (i->op == INSTR_LINE) continue; i->result = VarReg(i->result); i->arg1 = VarReg(i->arg1); i->arg2 = VarReg(i->arg2); } } // We perform as many translation steps as necessary // Some translation rules may use other translation rules, so more than one step may be necessary. // Translation ends either when there has not been any modification in last step or after // defined number of steps (to prevent infinite loop in case of invalid set of translation rules). in_assert = false; for(blk = proc->instr; blk != NULL; blk = blk->next) { if (Verbose(proc)) { PrintBlockHeader(blk); } loc.blk = blk; loc.n = 1; // The translation is done by using procedures for code generating. // We detach the instruction list from block and set the block as destination for instruction generator. // In this moment, the code generating stack must be empty anyways. first_i = blk->first; blk->first = blk->last = NULL; GenSetDestination(blk, NULL); i = first_i; while(i != NULL) { loc.i = i; if (ASSERTS_OFF) { if (i->op == INSTR_ASSERT_BEGIN) { in_assert = true; goto next; } else if (i->op == INSTR_ASSERT_END) { in_assert = false; goto next; } else { if (in_assert) goto next; } } if (VERBOSE_NOW) { color = PrintColor(RED+BLUE); PrintInstrLine(loc.n); InstrPrint(i); PrintColor(color); } if (!InstrTranslate3(i->op, i->result, i->arg1, i->arg2, GENERATE)) { InternalErrorLoc("Unsupported instruction", &loc); InstrPrint(i); } next: next_i = i->next; // InstrFree(i); i = next_i; loc.n++; } // Free the instructions i = first_i; while (i!=NULL) { next_i = i->next; InstrFree(i); i = next_i; } } // block }
void EmitInstr2(Instr * instr, char * str) { Var * var; UInt8 format = 0; char * s, c; UInt32 n; BigInt bn; BigInt * pn; s = str; if (instr->op == INSTR_LINE) { PrintColor(BLUE+LIGHT); } while(c = *s++) { if (c == '%') { c = *s++; if (c == '\'') { format = 1; c = *s++; } if (c >='A' && c<='Z') { var = MACRO_ARG[c-'A']; // Variable properties if (*s == '.') { s++; if (StrEqualPrefix(s, "count", 5)) { VarCount(var, &bn); EmitBigInt(&bn); s+= 5; continue; } else if (StrEqualPrefix(s, "size", 4)) { n = VarByteSize(var); EmitInt(n); s+= 4; continue; } else if (StrEqualPrefix(s, "elemsize", 8) || StrEqualPrefix(s, "item.size", 9)) { s += 8; if (var->type->variant == TYPE_ARRAY) { n = TypeSize(var->type->element); } else { n = 0; } EmitInt(n); continue; } if (StrEqualPrefix(s, "step", 4)) { s += 4; n = 1; if (var->type->variant == TYPE_ARRAY) { n = var->type->step; } EmitInt(n); continue; } else if (StrEqualPrefix(s, "index.min", 9)) { s += 9; if (var->type->variant == TYPE_ARRAY) { pn = &var->type->index->range.min; } else { pn = Int0(); } EmitBigInt(pn); continue; } s--; } EmitVar(var, format); continue; } switch(c) { case '0': EmitVar(instr->result, format); continue; case '1': if (instr->op != INSTR_LINE) { EmitVar(instr->arg1, format); } else { EmitInt(instr->line_no); } continue; case '2': if (instr->op != INSTR_LINE) { EmitVar(instr->arg2, format); } else { EmitStr(instr->line); } continue; case '@': break; case 't': c = '\t'; break; } } EmitChar(c); } if (instr->op == INSTR_LINE) { PrintColor(RED+GREEN+BLUE); } }
int main(int argc, char* argv[]) { //Reset color std::cout << Format_Color("Default", FG) << Format_Color("Default", BG); config_um.conf_map = { {"FG", "Default"}, {"BG", "Default"}, {"Number_FG", "Default"}, {"Number_BG", "Default"}, {"Label_FG", "Default"}, {"Label_BG", "Default"}, {"Value_FG", "Default"}, {"Value_BG", "Default"}, {"Hilight_FG", "Default"}, {"Hilight_BG", "Default"}, {"Style", "Long"}, {"Padding", ""} }; if(argc == 1) { return PrintHelp(); } for(int a = 1; a < argc; a++) { if(wolfstring::EndsWith(argv[a], ".wolfmenu")) { menu_count = true; menu_um.LoadFile(argv[a]); } if(wolfstring::EndsWith(argv[a], ".conf")) { config_um.LoadFile(argv[a]); } } if(menu_count) { std::cerr << "Menu count to low. Aborting.\n\n"; return PrintHelp(); } temp_map = menu_um.conf_map; size_t menu_index = 0; std::string style = config_um.GetVal("Style"); while(1) { std::unordered_map<std::string, std::string> temp_map2 = {}; if(current != "") { for(auto zz : temp_map) { if(wolfstring::StartsWith(zz.first, current)) { temp_map2[zz.first] = zz.second; } } if(temp_map2.empty()) { wolfstring::pstring_n("Nothing in menu.\n"); ResetCurrent(); temp_map2 = menu_um.conf_map; } } else { temp_map2 = menu_um.conf_map; } for(auto z : temp_map2) { std::cout << PrintColor(0) << config_um.GetVal("Padding") << PrintColor(1) << menu_index << PrintColor(2) << ": " << PrintColor(3) << z.first << PrintColor(0); menu_index++; if(style == "Tall") { printf("\n"); } if(style == "Long") { printf(" "); } } std::string buffer = ""; std::cout << "\nCurrent: " << current << " > " << PrintColor(4); std::getline(std::cin, buffer); std::cout << PrintColor(0); if(buffer != "") { bool number = true; for(const char &c : buffer) { if(!isdigit(c)) { number = false; goto out; } } out: if(number) { size_t selection = std::stoi(buffer); if(selection < menu_index) { size_t current_index = 0; for(const auto &zzz : temp_map2) { if(selection == current_index) { system(zzz.second.c_str()); return 0; } current_index++; } } } else { if(buffer == "*") { ResetCurrent(); } if(wolfstring::v_match(buffer, {"quit", "exit", "\\c"})) { return 0; } else { current += buffer; } } } menu_index = 0; temp_map = temp_map2; } return 0; }
Bool OptimizeLoop(Var * proc, InstrBlock * header, InstrBlock * end) /* 1. Find loop (starting with inner loops) - Every jump to label preceding the jump (backjump) forms a label - In nested labels, we encounter the backjump first <code1> l1@ <code2> l2@ <code3> if.. l2@ <code4> if.. l3@ <code5> 2. Select variable to put to register - Most used variable should be used - Some variables are already moved to index register (this is considered use too) 3. Compute cost of moving the variable to register */ { Instr * i, initial, ti, * last_mod; Var * top_var, * reg, * top_reg, * orig_result; UInt16 r, regi, changed; UInt32 var_size; Int32 q, top_q, n; Bool init, top_init; InstrBlock * blk, * last_mod_blk; InstrBlock * blk_exit; Bool var_modified; Bool verbose; Rule * rule; UInt8 color; blk_exit = end->next; G_VERBOSE = verbose = Verbose(proc); VarResetUse(); InstrVarUse(header, blk_exit); InstrVarLoopDependent(header, end); // When processing, we assign var to register for(regi = 0; regi < CPU->REG_CNT; regi++) CPU->REG[regi]->var = NULL; while(top_var = FindMostUsedVar()) { // if (Verbose(proc)) { // Print("Most user var: "); PrintVar(top_var); PrintEOL(); // } top_var->read = top_var->write = 0; var_size = VarByteSize(top_var); //====== Select the best register for the given variable // let %A,%A => index -3 // use of register instead of variable -1 // spill +3 top_q = 0; top_reg = NULL; top_init = false; for(regi = 0; regi < CPU->REG_CNT; regi++) { reg = CPU->REG[regi]; if (FlagOn(reg->submode, SUBMODE_IN|SUBMODE_OUT)) continue; // exclude input/output registers if (reg->type->range.max == 1) continue; // exclude flag registers if (var_size != VarByteSize(reg)) continue; // exclude registers with different byte size if (reg->var != NULL) continue; if (InstrRule2(INSTR_LET, reg, top_var, NULL)) { // if (StrEqual(reg->name, "x") && StrEqual(top_var->name, "i")) { // Print(" "); // } q = UsageQuotient(header, end, top_var, reg, &init); if (q < top_q) { top_q = q; top_reg = reg; top_init = init; } } } if (top_reg == NULL) continue; reg = top_reg; if (Verbose(proc)) { color = PrintColor(OPTIMIZE_COLOR); PrintFmt("*** Loop %d..%d\n", header->seq_no, end->seq_no); Print("Var: "); PrintVarVal(top_var); PrintEOL(); Print("Register: "); PrintVarName(top_reg); PrintEOL(); PrintFmt("Quotient: %d\n", top_q); PrintColor(color); } //TODO: If there is Let reg = var and var is not top_var, we need to spill store //=== Replace the use of registers // PrintProc(proc); ResetValues(); initial.op = INSTR_LET; initial.result = top_reg; initial.arg1 = top_var; initial.arg2 = NULL; var_modified = false; // Generate instruction initializing the register used to replace the variable // before the start of the loop. // We only do this, if the variable is not initialized inside the loop. // if (FlagOn(top_var->flags, VarUninitialized) && !top_init) { // top_init = true; // } if (top_init) { LoopInsertPrologue(proc, header, INSTR_LET, top_reg, top_var, NULL); VarSetSrcInstr(top_reg, &initial); } r = 0; last_mod = NULL; for(blk = header; blk != blk_exit; blk = blk->next) { if (verbose) PrintBlockHeader(blk); for(i = blk->first, n=0; i != NULL; i = i->next) { retry: n++; if (i->op == INSTR_LINE) { if (verbose) { PrintInstrLine(n); EmitInstrInline(i); PrintEOL(); } continue; } // Delete unnecessary assignment if (i->op == INSTR_LET) { if (!InVar(i->arg1) && !OutVar(i->result) && VarContains(i->result, i->arg1)) { del: if (verbose) { PrintInstrLine(n); EmitInstrInline(i); } del2: if (verbose) { PrintDelete(); } i = InstrDelete(blk, i); if (i == NULL) break; goto retry; //continue; } } // Load the register with variable if necessary if (InstrReadsVar(i, top_var)) { if (!VarContains(top_reg, top_var)) { if (!(i->op == INSTR_LET && i->result == top_reg && i->arg1 == top_var)) { InstrInsertRule(blk, i, INSTR_LET, top_reg, top_var, NULL); } } } if (i->op == INSTR_LET && (i->result == top_var && i->arg1 == top_reg)) { r++; goto del; } if (InstrSpill(i, top_var)) { InstrInsertRule(blk, i, INSTR_LET, top_var, top_reg, NULL); } if (verbose) { PrintInstrLine(n); EmitInstrInline(i); } orig_result = i->result; memcpy(&ti, i, sizeof(Instr)); changed = VarTestReplace(&ti.result, top_var, reg); r += changed; changed += VarTestReplace(&ti.arg1, top_var, reg); changed += VarTestReplace(&ti.arg2, top_var, reg); // If the instruction used variable, that contains same value as replaced register, use the register instead if (ti.arg1 != reg && VarContains(ti.arg1, reg)) { changed += VarTestReplace(&ti.result, ti.arg1, reg); changed += VarTestReplace(&ti.arg2, ti.arg1, reg); changed += VarTestReplace(&ti.arg1, ti.arg1, reg); } if (changed > 0) { if (i->op == INSTR_LET && ti.result == ti.arg1) { goto del2; } rule = InstrRule(&ti); if (rule != NULL && (i->rule->cycles >= rule->cycles)) { InstrReplaceVar(i, top_var, top_reg); if (i->arg1 != reg && VarContains(i->arg1, reg)) { VarTestReplace(&i->result, i->arg1, reg); VarTestReplace(&i->arg2, i->arg1, reg); VarTestReplace(&i->arg1, i->arg1, reg); } i->rule = rule; CheckInstr(i); PrintChange(i); } } if (verbose) PrintEOL(); ResetValue(i->result); if (orig_result == top_var) { // if (!InstrIsSelfReferencing(i)) { VarSetSrcInstr(i->result, &initial); // } else { // VarSetSrcInstr(i->result, NULL); // } last_mod = i; last_mod_blk = blk; } else { VarSetSrcInstr(i->result, i); } } } // Value of register is not known at the end of loop, but it is not initialized at the beginning of the loop // We must load it before first use. if (!top_init && last_mod) { InstrInsertRule(last_mod_blk, last_mod->next, INSTR_LET, top_var, top_reg, NULL); } // If we replaced some destination by the register, store the register to destination if (r > 0) { // There may be exit label as part of the loop // We need to spill after it if (!VarIsConst(top_var)) { if (blk_exit == NULL || blk_exit->callers != NULL || blk_exit->from != end) { blk_exit = InstrBlockAlloc(); blk_exit->to = end->to; blk_exit->next = end->to; end->next = blk_exit; end->to = blk_exit; } InstrInsertRule(blk_exit, blk_exit->first, INSTR_LET, top_var, top_reg, NULL); } // InstrInsert(blk_exit, blk_exit->first, INSTR_LET, top_var, top_reg, NULL); } if (FlagOn(top_var->flags, VarLoopDependent)) { reg->flags |= VarLoopDependent; } return true; } return false; }