/// <summary>Adds 1 to the usage count for the needed register size.</summary> /// <param name="size">Size of reg in bytes.</param> /// <param name="stmt">The statement where a new register is being requested.</param> public void AddToCalc(int size, Stmt stmt) { // grow maxCurSz if needed largestSz = Math.Max(size, largestSz); curSizeCts[size]++; //lets see if there is a free spot with the exact size needed if (worstCaseMode) { if (maxSizeCts[size] < curSizeCts[size]) { maxSizeCts[size] = curSizeCts[size]; firstStmtWithMostRegs = stmt; } } // does curSizeCt fit in current maxSizeCts? if not then grow it else { int[] leftovers = new int[largestSz + 1]; for (int i = largestSz; i > 0; i--) { bool doesNotFit = true; leftovers[i] += maxSizeCts[i] - curSizeCts[i]; // lets see if we can borrow from a larger register space for (int j = i; j <= largestSz; j++) if (leftovers[j] > 0) { leftovers[j]--; leftovers[j - i]++; doesNotFit = false; break; } if (doesNotFit) { maxSizeCts[size]++; firstStmtWithMostRegs = stmt; break; } } } }
//public bool TryGetVar(string name, out Variable variable) //{ // bool success = varsByName.TryGetValue(name, out variable); // return success; //} /// <summary>Adds a GcnVar to the Vars collection while making sure it is valid.</summary> public void AddVariable(List<Variable> pendingNewVarsToAddToNextStmt, Stmt stmt, Log log, char type, int size, char dataType, string options) { MatchCollection r2 = Regex.Matches(options, @"(?<4>[a-z_][a-z_0-9]*)" + @"((?<8>\ +(?<5>[sv])(?:(?<6>\d+)|(?:\[(?<6>\d+):(?<7>\d+)\])))|" + // assign exact reg @"(?:\ +(?<9>[a-z_][a-z0-9_]*)(?:\[(?<10>\d+)\])?))?" + // Match to another Vars Reg# @"\s*(,|$)\s*"); if (r2.Count <= 0) // there should be at least one match { log.Error("The new variable options could not be understood: " + options); return; } foreach (Match m in r2) { GroupCollection g = m.Groups; string name = g[4].Value; string varsRegToCopy = ""; int varsRegToCopyIndex = 0; int requestedReg = -1; if (g[8].Success) { requestedReg = Int32.Parse(g[6].Value); // error checking if (type != g[5].Value[0]) log.Warning("The variable type ({0}) does not match the register type {1}", type, g[5].Value); if (g[7].Success) if ((int.Parse(g[7].Value) - requestedReg + 1) != (size / 4)) log.Warning("The variable size({0}) does not match the size of {1}[#:#]", size, type); } else if (g[9].Success) { varsRegToCopy = g[9].Value; if (g[10].Success) varsRegToCopyIndex = int.Parse(g[10].Value); // make sure the name is not already added to the dictionary Variable copySrc; if (!varsByName.TryGetValue(varsRegToCopy, out copySrc)) { log.Error("The past variable '{0}' cannot be found.", varsRegToCopy); continue; } // if this is copying a reg from another variable and that variable is fixed then copy the reg now. if (copySrc.isRegisterNumSpecifed) requestedReg = copySrc.regNo + varsRegToCopyIndex; if (type != (copySrc.isScaler ? 's' : 'v')) log.Warning("'{0}' is type '{1}' however '{2}' is type '{3}'.", name, type, varsRegToCopy, copySrc.isScaler ? 's' : 'v'); if (requestedReg + ((size + 3) / 4) > copySrc.regNo + copySrc.RegsRequired) log.Warning("The new variable '{0}' extends past the source variables last register.", name); } // make sure the reserved word is not in ISA_DATA.AsmReserveDWords, it will be added regardless if (Array.BinarySearch<string>(ISA_DATA.AsmReserveDWords, name) >= 0) { log.Error("'{0}' cannot be used as a register name because it is a reserved word.", name); continue; } // make sure the variable name is not a common alias if (ISA_DATA.sRegAliases.ContainsKey(name)) { log.Error("'{0}' cannot be used as a variable because it is a common register alias.", name); continue; } // make sure the name is not already added to the dictionary if (varsByName.ContainsKey(name)) { log.Error("Variable '{0}' has already been declared.", name); continue; } // lets now add it to the var dictionary Variable var = new Variable() { name = name, isScaler = (type == 's'), size = size, type = dataType, regNo = requestedReg, // -1 for not yet assigned variablesRegToCopy = varsRegToCopy, variablesRegToCopyIndex = varsRegToCopyIndex, isRegisterNumSpecifed = (requestedReg >= 0) }; varsByName.Add(name, var); pendingNewVarsToAddToNextStmt.Add(var); // lets calculate usage RegUsageCalc regUsageCalc = var.isScaler ? sRegUsageCalc : vRegUsageCalc; if (regUsageCalc != null) regUsageCalc.AddToCalc(var.size, stmt); } }
public void MarkVariableUsedInStmt(Stmt stmt, string name, int index, int startPos, int length) { Variable nr; if (!varsByName.TryGetValue(name, out nr)) log.Error("Variable, '{0}', is not defined.", name); else { if (nr.stmtTerminated == null) nr.stmtsUsedIn.Add(stmt); else log.Error("Variable, " + name + ", is being used but has already been marked terminated."); stmt.vars.Add(new VariableUsageLoc() { variable = nr, indexOffset = index, startPos = startPos, varLength = length }); } }
static void Main(string[] args) { // args = "TestInput.txt output.bin /OutputUsage".Split(' '); // <---- uncomment to use testinput.txt // args = "TestInput.txt output.bin /showstmts".Split(' '); // <---- uncomment to use testinput.txt Log log = new Log(0); Stopwatch startedAt = new Stopwatch(); startedAt.Start(); if (args.Count() < 2) { // process asm -> finished bin // process asm,RegPool -> finished bin // process asm -> partial + binSize,vRegCt,sRegCt // process partial+RegPool -> finished bin Console.WriteLine( //01234567890123456789012345678901234567890123456789012345678901234567890123456789 "Usage: Asm4GCN.exe <input> <output> /OutputUsage /ShowStmts\n\n" + " <input> This is an Asm text file.\n\n" + //" /OutputBin This is the finished GCN asm bin file.\n" + " /OutputUsage Outputs the vector\\scalar register counts and the\n" + " binary size. When in this mode a usage file is\n" + " created and not a bin.\n\n" + " /ShowStmts Shows the statements in a friendly to read format.\n\n" + " A example usage plan using the 'outputusage' option:\n" + " 1) Extract Asm block from c/c++/c# code into myAsm.txt.\n" + " 2) Get the register and size requirements for the block..\n" + " example: Asm4GCN.exe myAsm.txt /OutputUsage AsmBlockReq.txt\n" + " 3) Using the requirements, create dummy code with the same\n" + " scalar\\vector register needs and bin size then note what\n" + " actual registers are used.\n" + " 4) Now that the registers are known, the binary file can be \n" + " finished.\n" + " example: Asm4GCN.exe tempStage.int /OutputBin myBin.bin\n" + " 5) Now that we have the asm block in binary form we need to\n" + " locate the dummy code and replace it with the newly\n" + " generated binaries.\n"); return; } //string OutputBin = "", OutputUsage = ""; string outputFilename = args[1]; bool doShowStmts = false; bool inUsageMode = false; //bool doOutputBin = false; for (int i = 2; i < args.Count(); i++) { if (args[i].ToLower() == "/outputusage") { inUsageMode = true; } else if (args[i].ToLower() == "/showstmts") { doShowStmts = true; } else { Console.WriteLine("Unknown command line option: " + args[i]); return; } } /////////////////// Read the input file /////////////////// string[] lines = new string[0]; try { lines = System.IO.File.ReadAllLines(args[0]); } catch (Exception e) { log.Error("Unable to open input file. Details: {0}", e.Message); return; } GcnBlock Asm4GCN = new GcnBlock(); List <Stmt> gcnStmts; int binSize = 0; if (inUsageMode) { List <RegUsage> sRegUsage, vRegUsage; string logOutput; Asm4GCN.CompileForSpecs(lines, out gcnStmts, out sRegUsage, out vRegUsage, out binSize, out logOutput); log.Append(logOutput); // Write bin or halfway point to output file int stats_4ByteInstCt = 0; int stats_8ByteInstCt = 0; foreach (Stmt op in gcnStmts) { if (op.opCode.literal.HasValue) { stats_8ByteInstCt++; } else { stats_4ByteInstCt++; } } if (true) // lets just always show this for now { log.WriteLine("4-Byte_Inst_Count:{0} 8-Byte_Inst_Count:{1} Total:{2} bytes", stats_4ByteInstCt, stats_8ByteInstCt, stats_4ByteInstCt * 4 + stats_8ByteInstCt * 8); //log.WriteLine("Displaying all {0} Scaler sizes:", sRegUsage.Count); for (int i = 0; i < sRegUsage.Count; i++) { log.WriteLine("{1} Scaler reg(s) of size {0} needed", sRegUsage[i].regSize, sRegUsage[i].timesUsed); } //log.WriteLine("Line # on last S Reg increase: {0}", sRegUsageCalc.lineOnLastPoolIncrease); //log.WriteLine("Displaying all {0} Vector sizes:", vRegUsage.Count); for (int i = 0; i < vRegUsage.Count; i++) { log.WriteLine("{1} Vector reg(s) of size {0} needed", vRegUsage[i].regSize, vRegUsage[i].timesUsed); } //log.WriteLine("Line # on last S Reg increase: {0}", sRegUsageCalc.lineOnLastPoolIncrease); } // Lets save the regUsage to a file try { //MemoryStream stream = new MemoryStream(); //BinaryWriter writer2 = new BinaryWriter(stream); using (BinaryWriter writer = new BinaryWriter(File.Open(outputFilename, FileMode.Create))) { writer.Write(stats_4ByteInstCt); writer.Write(stats_8ByteInstCt); writer.Write(sRegUsage.Count); for (int i = 0; i < sRegUsage.Count; i++) { writer.Write(sRegUsage[i].regSize); writer.Write(sRegUsage[i].timesUsed); } writer.Write(vRegUsage.Count); for (int i = 0; i < vRegUsage.Count; i++) { writer.Write(vRegUsage[i].regSize); writer.Write(vRegUsage[i].timesUsed); } } } catch (Exception e) { log.Error("Unable to write binary output file. {0}", e.Message); } } else // binary creating mode (not Usage-Mode) { string logOutput; bool success; byte[] bin = Asm4GCN.CompileForBin(lines, out gcnStmts, out binSize, out logOutput, out success); // log.Append(logOutput); if (success) { try { // Write bin to output file File.WriteAllBytes(outputFilename, bin); //// Display the output (for debugging only) //using (BinaryWriter writer = new BinaryWriter(File.Open(OutputBin, FileMode.Create))) //{ // foreach (GcnStmt op in gcnStmts) // { // writer.Write(op.opCode.code); // if (op.opCode.literal.HasValue) // writer.Write((uint)op.opCode.literal); // } //} } catch (Exception e) { log.Error("Unable to write binary output file. {0}", e.Message); } } else { log.Error("{0} not generated because of errors.", outputFilename); } } log.WriteLine("Time taken: {0} ms", startedAt.ElapsedMilliseconds); /////////// Display the opcode. /////////// //log.WriteLine("Starting Display the opcode: {0} ms", startedAt.ElapsedMilliseconds); if (doShowStmts) { log.WriteLine("ID |Line|Sz|Loc| OpCode |Params post Processing| Source Line"); for (int i = 0; i < gcnStmts.Count; i++) { Stmt stmt = gcnStmts[i]; string sBefore = lines[stmt.lineNum - 1]; string sAfter = stmt.options; sBefore = sBefore.Substring(0, Math.Min(30, sBefore.Length)); sAfter = sAfter.Substring(0, Math.Min(21, sAfter.Length)); sBefore = Regex.Replace(sBefore, @"\t|\n|\r", " "); log.WriteLine("{0,3}|{1,4}|{2,2}|{3,3}|{4:X}| {5,-21}| {6,-30}", stmt.GcnStmtId, stmt.lineNum, stmt.opSize, stmt.locInBin, stmt.opCode.code, sAfter, sBefore);// stmt.inst.id + " Options:" + stmt.options); } } //Console.WriteLine("Output file size in words (4 bytes): {0} ", new FileInfo(args[1]).Length); Console.WriteLine("Press any key to exit."); Console.ReadKey(); }
private byte[] Compile(string[] srcLines, out int binSize, Log log) { // log.WriteLine("Starting Lines: {0} ms", startedAt.ElapsedMilliseconds); // StringBuilder sb = new StringBuilder(); //Future: Maybe use string builder here // Apply #defines, strip out comments, cleanup, record last time each var is used. bool inCommentMode = false; List <Variable> pendingNewVarsToAddToNextStmt = new List <Variable>();; // pending New Variables To Add To Next Stmt List <Label> pendingLabelsToAddToNextStmt = new List <Label>();; // pending New Labels that need a Stmt attached for (int line = 1; line < srcLines.Length + 1; line++) // from lines 1 to Last { string curLine = srcLines[line - 1]; while (curLine.EndsWith(@"\")) { curLine = curLine.Remove(curLine.Length - 1) + srcLines[line++]; } // cleanup comments and whitespace curLine = CleanupComments(curLine, ref inCommentMode, line, log); // cleanup defines curLine = ProcessDefines(curLine, log); // Lets split up the multiple statements that might be on this one line. String[] stmts = curLine.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); // Process each statement on this line. for (int stmtNumberOnLine = 0; stmtNumberOnLine < stmts.Length; stmtNumberOnLine++) { ProcessSingleStmt(curLine, stmts[stmtNumberOnLine], line, stmtNumberOnLine, ref pendingNewVarsToAddToNextStmt, pendingLabelsToAddToNextStmt, log, stmts); } } // Process remaining labels that pointed to exit (since there are no stmt-headers after the last statement, exit labels need .) foreach (Label label in pendingLabelsToAddToNextStmt) { label.isAtEnd = true; labels.AddLabel(label, log); } // Process Automatic variable freeing. vars.ProcessAutomaticFreeing(gcnStmts); // Process register assignments. vars.AssignRegNumbers(gcnStmts); // Convert each statement into in to binary (delay statements with variables) List <Stmt> needLabelFilled = new List <Stmt>(); foreach (Stmt gcnStmt in gcnStmts) { ProcessStmt(gcnStmt, needLabelFilled, log); } // At this point we have to finish two things: // (1) Find the "stmt.opSize" of each stmt and build min/max distance tables // (2) Fill in the "stmt.opCode" for any stmt that have a label. /////////// Fill in the OpSize on each statement /////////// FillOpSizeValue(log, needLabelFilled); /////////// Optional final Error checking /////////// int loc = 0; for (int i = 0; i < gcnStmts.Count; i++) { Stmt stmt = gcnStmts[i]; if (stmt.opSize != stmt.opCode.Size) { log.Error("ERROR: (internal) Stmt {0} on line {1} has an opSize of {2} however HasValue is {3}", stmt.inst.name, stmt.lineNum, stmt.opSize, stmt.opCode.literal.HasValue); } if (stmt.opSize == 0) { log.WriteLine("Stmt {0} had an opSizeOfZero"); } if (stmt.locInBin != loc) { log.WriteLine("stmt.locInBin ({0}) might not be correct.", stmt.locInBin); } if (stmt.GcnStmtId != i) { log.WriteLine("stmt.GcnStmtId ({0}) might not be correct.", stmt.GcnStmtId); } loc += stmt.opSize; } /////////// Lets print all the logs & warnings /////////// if (log.hasErrors) { log.WriteLine("One or more Error(s) in GCN Assembly"); } /////////// Get bin size /////////// binSize = 0; foreach (Stmt stmt in gcnStmts) { binSize += stmt.opSize * 4; } /////////// Create bin /////////// // Write bin to output file byte[] bin = new byte[binSize]; MemoryStream ms = new MemoryStream(bin); using (BinaryWriter writer = new BinaryWriter(ms)) { foreach (Stmt op in gcnStmts) { //writer.Write() writer.Write(op.opCode.code); if (op.opCode.literal.HasValue) { writer.Write((uint)op.opCode.literal); } } } return(bin); // code to aid debugging //if (doOutputInter) //{ try { using (BinaryWriter writer = new BinaryWriter(File.Open(OutputInter, FileMode.Create))){ // foreach (GcnStmt s in gcnStmts) { // writer.Write(s.inst.id); // writer.Write(s.GcnStmtId); // writer.Write(s.options); // writer.Write(s.srcLine); } // writer.Close(); } } // catch (Exception e) { log.Error("Unable to write intermediate output file. {0}", e.Message); } } }
private void ProcessSingleStmt(string curLine, string stmtText, int lineNum, int stmtNumberOnLine, ref List <Variable> pendingNewVarsToAddToNextStmt, List <Label> pendingLabelsToAddToNextStmt, Log log, string[] stmts) { // Split out label from statement and record any labels on the line Match l = Regex.Match(stmtText, @"([a-z_][a-z0-9_]*):(\s|$)"); if (l.Success) { pendingLabelsToAddToNextStmt.Add(new Label() { labelName = l.Groups[1].Value, lineNum = lineNum }); if (l.Length == stmtText.Length) { return; } stmtText = stmtText.Remove(0, l.Length); } // Replace Friendly statements with Asm statements stmtText = FriendlyConverter.FriendlyFormatToAsmFormater(stmtText, vars, ISA_Gen, log); // Extract first word, and options char[] delimiterChars = { ',', ' ' }; string[] commands = stmtText.Split(delimiterChars, 2, StringSplitOptions.RemoveEmptyEntries); string firstWord = commands[0]; //string options = commands.Count() > 1 ? commands[1].Trim() : ""; Stmt stmt = new Stmt() { options = commands.Count() > 1 ? commands[1].Trim() : "", lineNum = lineNum, lineDepth = stmtNumberOnLine, fullStmt = stmtText, GcnStmtId = gcnStmts.Count, }; ///////// Process Register Reservations, Renaming and Freeing ///////// // New Format: [sv][1248][fiub][#] VarName Free Format: free VarName // ren cat dog if (firstWord == "free") { string[] matches = stmt.options.Split(delimiterChars, StringSplitOptions.RemoveEmptyEntries); foreach (string name in matches) { vars.FreeVariable(name, gcnStmts); } return; } ///////// Process #S_POOL / #V_POOL --> sRegPool/vRegPool ///////// //string cmd = Regex.Match(curLine, @"(?<=^\ *\#)(define|ref|[vs]_pool)").Value; if (firstWord == "#v_pool" || firstWord == "#s_pool") { // skip line if #S_POOL / #V_POOL if (!vars.UsingRegPools) { return; } // Show warning if there are already existing vars. if (vars.Count > 0) { log.Warning("#S_POOL / #V_POOL normally occur in the header area. Having this command in the " + "body can be used to clear all variable names and pool reservations."); } Match def = Regex.Match(curLine, @"^\ *#(v|s)_pool\ *(?:(?:[vs](\d+)|(\S+?))\s*,?\s*)+"); if (!def.Groups[0].Success | !def.Groups[2].Success) { log.Error("error processing #POOL statement in '{0}'", curLine); return; } if (def.Groups[3].Success) { log.Error("unknown value '{0}' in POOL command (skipping)", def.Groups[3]); } int[] available_Regs = new int[def.Groups[2].Captures.Count]; for (int i = 0; i < available_Regs.Length; i++) { available_Regs[i] = Int32.Parse(def.Groups[2].Captures[i].Value); } vars.ReloadRegPool(def.Groups[1].Value[0], available_Regs); return; // we are done with this statement. } ///////// Process Variable Declarations ///////// // Example: s_mov_b32 v8u ttt, aaa, bbb // Example: s_mov_b32 v8u ttt S4, aaa, bbb // Example: v4u myVar0 s[2:3]; // Example: s4u myVar1 myVar0 // Single line Declarations Match m = Regex.Match(firstWord, @"(?<1>s|v)(?<2>1|2|4|8|16)(?<3>[fiub])"); if (m.Success) { char type = m.Groups[1].Value[0]; int size = Int32.Parse(m.Groups[2].Value); char dataType = m.Groups[3].Value[0]; vars.AddVariable(pendingNewVarsToAddToNextStmt, stmt, log, type, size, dataType, stmt.options); return; } // Inline Declarations var inlines = Regex.Matches(stmt.options, @"(?<![a-z_0-9])(?<2>s|v)(?<3>1|2|4|8|16)(?<4>[fiub])[\t\s]+" + @"(?<5>(?<6>[a-z_][a-z_0-9]*)" + @"( [a-z_][a-z_0-9]*(\[\d+(?::\d+)\])?)?)"); foreach (Match m3 in inlines) { char type = m3.Groups[2].Value[0]; int size = Int32.Parse(m3.Groups[3].Value); char dataType = m3.Groups[4].Value[0]; vars.AddVariable(pendingNewVarsToAddToNextStmt, stmt, log, type, size, dataType, m3.Groups[5].Value); stmt.options = stmt.options.Remove(m3.Index, m3.Length).Insert(m3.Index, m3.Groups[6].Value); } ///////// lookup instruction details ///////// if (!ISA_DATA.isa_inst_dic.TryGetValue(firstWord, out stmt.inst)) { log.Error("'{0}' is not a recognized instruction", firstWord); return; } ///////// Record var names and location making sure to exclude reserved words ///////// var foundVars = Regex.Matches(stmt.options, @"(?<=,|\ |^)(?![vs]\d+)(([a-z_][a-z0-9_]*)(?:\[(\d+)\])?)(?=,|\ |$)"); foreach (Match r in foundVars) { //Future: save char location so we don't have to search for the variable again when we do the replacement. string varName = r.Value; // ignore reserved words if (Array.BinarySearch <string>(ISA_DATA.AsmReserveDWords, varName) >= 0) { continue; } // ignore common register aliases if (ISA_DATA.sRegAliases.ContainsKey(varName)) { continue; } int len = varName.Length; bool hasIndex = varName.EndsWith("]"); int index = 0; int startPos = r.Index; if (hasIndex) { varName = r.Groups[2].Value; index = int.Parse(r.Groups[3].Value); } // Lets lookup the GcnVar to make sure it exists and also retrieve it. vars.MarkVariableUsedInStmt(stmt, varName, index, startPos, len); } ; ///////// Lets add the stmt to the list ///////// // Before adding, lets link any pending statements. foreach (Label label in pendingLabelsToAddToNextStmt) { label.firstStmt = stmt; labels.AddLabel(label, log); } pendingLabelsToAddToNextStmt.Clear(); // Also, lets link-up any new variables if (pendingNewVarsToAddToNextStmt.Count > 0) { foreach (Variable v in pendingNewVarsToAddToNextStmt) { v.stmtDeclared = stmt; } stmt.newVars = pendingNewVarsToAddToNextStmt; pendingNewVarsToAddToNextStmt = new List <Variable>(); } gcnStmts.Add(stmt); }
//public bool TryGetVar(string name, out Variable variable) //{ // bool success = varsByName.TryGetValue(name, out variable); // return success; //} /// <summary>Adds a GcnVar to the Vars collection while making sure it is valid.</summary> public void AddVariable(List <Variable> pendingNewVarsToAddToNextStmt, Stmt stmt, Log log, char type, int size, char dataType, string options) { MatchCollection r2 = Regex.Matches(options, @"(?<4>[a-z_][a-z_0-9]*)" + @"((?<8>\ +(?<5>[sv])(?:(?<6>\d+)|(?:\[(?<6>\d+):(?<7>\d+)\])))|" + // assign exact reg @"(?:\ +(?<9>[a-z_][a-z0-9_]*)(?:\[(?<10>\d+)\])?))?" + // Match to another Vars Reg# @"\s*(,|$)\s*"); if (r2.Count <= 0) // there should be at least one match { log.Error("The new variable options could not be understood: " + options); return; } foreach (Match m in r2) { GroupCollection g = m.Groups; string name = g[4].Value; string varsRegToCopy = ""; int varsRegToCopyIndex = 0; int requestedReg = -1; if (g[8].Success) { requestedReg = Int32.Parse(g[6].Value); // error checking if (type != g[5].Value[0]) { log.Warning("The variable type ({0}) does not match the register type {1}", type, g[5].Value); } if (g[7].Success) { if ((int.Parse(g[7].Value) - requestedReg + 1) != (size / 4)) { log.Warning("The variable size({0}) does not match the size of {1}[#:#]", size, type); } } } else if (g[9].Success) { varsRegToCopy = g[9].Value; if (g[10].Success) { varsRegToCopyIndex = int.Parse(g[10].Value); } // make sure the name is not already added to the dictionary Variable copySrc; if (!varsByName.TryGetValue(varsRegToCopy, out copySrc)) { log.Error("The past variable '{0}' cannot be found.", varsRegToCopy); continue; } // if this is copying a reg from another variable and that variable is fixed then copy the reg now. if (copySrc.isRegisterNumSpecifed) { requestedReg = copySrc.regNo + varsRegToCopyIndex; } if (type != (copySrc.isScaler ? 's' : 'v')) { log.Warning("'{0}' is type '{1}' however '{2}' is type '{3}'.", name, type, varsRegToCopy, copySrc.isScaler ? 's' : 'v'); } if (requestedReg + ((size + 3) / 4) > copySrc.regNo + copySrc.RegsRequired) { log.Warning("The new variable '{0}' extends past the source variables last register.", name); } } // make sure the reserved word is not in ISA_DATA.AsmReserveDWords, it will be added regardless if (Array.BinarySearch <string>(ISA_DATA.AsmReserveDWords, name) >= 0) { log.Error("'{0}' cannot be used as a register name because it is a reserved word.", name); continue; } // make sure the variable name is not a common alias if (ISA_DATA.sRegAliases.ContainsKey(name)) { log.Error("'{0}' cannot be used as a variable because it is a common register alias.", name); continue; } // make sure the name is not already added to the dictionary if (varsByName.ContainsKey(name)) { log.Error("Variable '{0}' has already been declared.", name); continue; } // lets now add it to the var dictionary Variable var = new Variable() { name = name, isScaler = (type == 's'), size = size, type = dataType, regNo = requestedReg, // -1 for not yet assigned variablesRegToCopy = varsRegToCopy, variablesRegToCopyIndex = varsRegToCopyIndex, isRegisterNumSpecifed = (requestedReg >= 0) }; varsByName.Add(name, var); pendingNewVarsToAddToNextStmt.Add(var); // lets calculate usage RegUsageCalc regUsageCalc = var.isScaler ? sRegUsageCalc : vRegUsageCalc; if (regUsageCalc != null) { regUsageCalc.AddToCalc(var.size, stmt); } } }
/// <summary> /// Adds a label to the label dictionary. /// </summary> /// <param name="name">The name of the label. (i.e "myLabel" in myLabel:)</param> /// <param name="firstStmt">The next statement following this label.</param> /// <param name="log">Location to write errors and warnings.</param> public void AddLabel(string name, int lineNum, Stmt firstStmt, Log log) { Label newLabel = new Label { labelName = name, lineNum = lineNum, firstStmt = firstStmt }; AddLabel(newLabel, log); }
//private void ProcessLine(string curLine, List<GcnStmt> needLabelFilled, int line, Log log) private void ProcessStmt(Stmt stmt, List<Stmt> needLabelFilled, Log log) { log.lineNum = stmt.lineNum; ///////// If instruction has a destination label then lets save it for later. ///////// if (Regex.IsMatch(stmt.options, @"(?:^|\s|,)@[a-z_][0-9a-z_]+")) { if (stmt.inst.minSize == stmt.inst.maxSize) stmt.opSize = stmt.inst.minSize; needLabelFilled.Add(stmt); } else { stmt.opCode = Encoder.convertInstToBin(stmt.options, stmt.inst, log); stmt.opSize = stmt.opCode.Size; } }
private void ProcessSingleStmt(string curLine, string stmtText, int lineNum, int stmtNumberOnLine, ref List<Variable> pendingNewVarsToAddToNextStmt, List<Label> pendingLabelsToAddToNextStmt, Log log, string[] stmts) { // Split out label from statement and record any labels on the line Match l = Regex.Match(stmtText, @"([a-z_][a-z0-9_]*):(\s|$)"); if (l.Success) { pendingLabelsToAddToNextStmt.Add(new Label() { labelName = l.Groups[1].Value, lineNum = lineNum }); if (l.Length == stmtText.Length) return; stmtText = stmtText.Remove(0, l.Length); } // Replace Friendly statements with Asm statements stmtText = FriendlyConverter.FriendlyFormatToAsmFormater(stmtText, vars, ISA_Gen, log); // Extract first word, and options char[] delimiterChars = { ',', ' ' }; string[] commands = stmtText.Split(delimiterChars, 2, StringSplitOptions.RemoveEmptyEntries); string firstWord = commands[0]; //string options = commands.Count() > 1 ? commands[1].Trim() : ""; Stmt stmt = new Stmt() { options = commands.Count() > 1 ? commands[1].Trim() : "", lineNum = lineNum, lineDepth = stmtNumberOnLine, fullStmt = stmtText, GcnStmtId = gcnStmts.Count, }; ///////// Process Register Reservations, Renaming and Freeing ///////// // New Format: [sv][1248][fiub][#] VarName Free Format: free VarName // ren cat dog if (firstWord == "free") { string[] matches = stmt.options.Split(delimiterChars, StringSplitOptions.RemoveEmptyEntries); foreach (string name in matches) vars.FreeVariable(name, gcnStmts); return; } ///////// Process #S_POOL / #V_POOL --> sRegPool/vRegPool ///////// //string cmd = Regex.Match(curLine, @"(?<=^\ *\#)(define|ref|[vs]_pool)").Value; if (firstWord == "#v_pool" || firstWord == "#s_pool") { // skip line if #S_POOL / #V_POOL if (!vars.UsingRegPools) return; // Show warning if there are already existing vars. if (vars.Count > 0) log.Warning("#S_POOL / #V_POOL normally occur in the header area. Having this command in the " + "body can be used to clear all variable names and pool reservations."); Match def = Regex.Match(curLine, @"^\ *#(v|s)_pool\ *(?:(?:[vs](\d+)|(\S+?))\s*,?\s*)+"); if (!def.Groups[0].Success | !def.Groups[2].Success) { log.Error("error processing #POOL statement in '{0}'", curLine); return; } if (def.Groups[3].Success) log.Error("unknown value '{0}' in POOL command (skipping)", def.Groups[3]); int[] available_Regs = new int[def.Groups[2].Captures.Count]; for (int i = 0; i < available_Regs.Length; i++) available_Regs[i] = Int32.Parse(def.Groups[2].Captures[i].Value); vars.ReloadRegPool(def.Groups[1].Value[0], available_Regs); return; // we are done with this statement. } ///////// Process Variable Declarations ///////// // Example: s_mov_b32 v8u ttt, aaa, bbb // Example: s_mov_b32 v8u ttt S4, aaa, bbb // Example: v4u myVar0 s[2:3]; // Example: s4u myVar1 myVar0 // Single line Declarations Match m = Regex.Match(firstWord, @"(?<1>s|v)(?<2>1|2|4|8|16)(?<3>[fiub])"); if (m.Success) { char type = m.Groups[1].Value[0]; int size = Int32.Parse(m.Groups[2].Value); char dataType = m.Groups[3].Value[0]; vars.AddVariable(pendingNewVarsToAddToNextStmt, stmt, log, type, size, dataType, stmt.options); return; } // Inline Declarations var inlines = Regex.Matches(stmt.options, @"(?<![a-z_0-9])(?<2>s|v)(?<3>1|2|4|8|16)(?<4>[fiub])[\t\s]+" + @"(?<5>(?<6>[a-z_][a-z_0-9]*)" + @"( [a-z_][a-z_0-9]*(\[\d+(?::\d+)\])?)?)"); foreach (Match m3 in inlines) { char type = m3.Groups[2].Value[0]; int size = Int32.Parse(m3.Groups[3].Value); char dataType = m3.Groups[4].Value[0]; vars.AddVariable(pendingNewVarsToAddToNextStmt, stmt, log, type, size, dataType, m3.Groups[5].Value); stmt.options = stmt.options.Remove(m3.Index, m3.Length).Insert(m3.Index, m3.Groups[6].Value); } ///////// lookup instruction details ///////// if (!ISA_DATA.isa_inst_dic.TryGetValue(firstWord, out stmt.inst)) { log.Error("'{0}' is not a recognized instruction", firstWord); return; } ///////// Record var names and location making sure to exclude reserved words ///////// var foundVars = Regex.Matches(stmt.options, @"(?<=,|\ |^)(?![vs]\d+)(([a-z_][a-z0-9_]*)(?:\[(\d+)\])?)(?=,|\ |$)"); foreach (Match r in foundVars) { //Future: save char location so we don't have to search for the variable again when we do the replacement. string varName = r.Value; // ignore reserved words if (Array.BinarySearch<string>(ISA_DATA.AsmReserveDWords, varName) >= 0) continue; // ignore common register aliases if (ISA_DATA.sRegAliases.ContainsKey(varName)) continue; int len = varName.Length; bool hasIndex = varName.EndsWith("]"); int index = 0; int startPos = r.Index; if (hasIndex) { varName = r.Groups[2].Value; index = int.Parse(r.Groups[3].Value); } // Lets lookup the GcnVar to make sure it exists and also retrieve it. vars.MarkVariableUsedInStmt(stmt, varName, index, startPos, len); }; ///////// Lets add the stmt to the list ///////// // Before adding, lets link any pending statements. foreach (Label label in pendingLabelsToAddToNextStmt) { label.firstStmt = stmt; labels.AddLabel(label, log); } pendingLabelsToAddToNextStmt.Clear(); // Also, lets link-up any new variables if (pendingNewVarsToAddToNextStmt.Count > 0) { foreach (Variable v in pendingNewVarsToAddToNextStmt) v.stmtDeclared = stmt; stmt.newVars = pendingNewVarsToAddToNextStmt; pendingNewVarsToAddToNextStmt = new List<Variable>(); } gcnStmts.Add(stmt); }