/** * Create code for the work function of a built-in filter. * * @param filter The filter that the work function is being built for * @param selfID A unique id assigned in FlatIRToC * @param p A printer to output the generated code */ static void predefinedFilterWork(SIRPredefinedFilter filter, int selfID, CodegenPrintWriter p) { Tape inputTape = RegisterStreams.getFilterInStream(filter); Tape outputTape = RegisterStreams.getFilterOutStream(filter); // Caller has printed function name and an iteration parameter ____n // Generate loop to execute body of this function ____n times, // In loop generate specialized code for function. p.print("void " + ClusterUtils.getWorkName(filter, selfID) + "(int ____n) {"); p.indent(); p.newLine(); p.indent(); // p.println("// predefinedFilterWork " + filter.getName()); // SIRFileReader if (filter instanceof SIRFileReader) { if (!(KjcOptions.mencoder || KjcOptions.blender)) { genFileReaderWork((SIRFileReader) filter, outputTape, selfID, p); } // SIRFileWriter } else if (filter instanceof SIRFileWriter) { if (!(KjcOptions.mencoder || KjcOptions.blender)) { genFileWriterWork((SIRFileWriter) filter, inputTape, selfID, p); } // SIRIdentity } else if (filter instanceof SIRIdentity) { assert false : "should not process SIRIdentity here"; p.println("for (; 0 < ____n; ____n--) {"); p.indent(); p.println(" " + outputTape.getPushName() + "(" + inputTape.getPopName() + "());"); p.outdent(); p.print("}"); // end of for loop. } else if (filter instanceof SIRDummySink || filter instanceof SIRDummySource) { // DummySource and SummySink do not appear in any of our // application code. Are they part of the language? // TODO: get right exception for unimplemented. throw new Error("Unsupported predefined filter " + filter.getName()); } else { // TODO: get right unchecked exception for unextended code... throw new Error("Unknown predefined filter " + filter.getName()); } p.newLine(); p.outdent(); // end of method body p.outdent(); // end of method definition p.print("}"); p.newLine(); p.newLine(); }
/* * There is special case code for FileReader<bit> since individual * bits can not be read in by any system routine that I know. * * With most bit streams that I (A.D.) have seen, the order is * little-endian in words, low-to-high bit in bytes. * This code -- matching Matt's implementation for the library * is a bit odd: endian-ness depends on fread / fwrite -- my * laziness, should always be little-endian -- but bits are read * and written from high to low. So byte 0b10011111 * is read as 1, 0, 0, 1, 1, 1, 1, 1 and is written back as * 0b10011111. This looks a little odd if a bit stream does not * end on a byte boundary: writing stream 1,0,1,1 results in 0b10110000 * * If we change the number of bits bufferred from 1 byte to a larger * integer type, we will have to worry about endian-ness on disk. * This code was designed for .BMP files, which are little-endian. * on disk. We will also have to worry about file lengths: Unix allows * file lengths in bytes, this will involve some extra code for not writing * an excessive number of bytes on the last write, causing the file lengths * to be dependent on the size of 'bits_type'. **/ private static void genFileReaderWorkBit( SIRFileReader filter, Tape outputTape, int selfID, CodegenPrintWriter p) { // haven't bothered to do buffered file input on top of the // bit input (it is possible but seems a little complicated) System.err.println( "PERFORMANCE WARNING: FileReader<bit> reads only 1 byte" + " at a time; faster to use FileReader<int>, which is buffered."); // String theType = "" + filter.getOutputType(); // wrap in loop p.println("for (; 0 < ____n; ____n--) {"); p.indent(); // the bit type is special since you can not just read or // write a bit. It requires bufferring in some larger // integer type. String bits_to_go = bitsToGoName(filter); String the_bits = theBitsName(filter); p.println("static " + bits_type + " " + the_bits + " = 0;"); p.println("static int " + bits_to_go + " = 0;"); p.newline(); p.println("if (" + bits_to_go + " == 0) {"); p.indent(); p.println( "if (fread(" + "&" + the_bits + ", " + "sizeof(" + the_bits + ")," + " " + "1, " + fpName(filter) + ")) {"); p.indent(); p.println(bits_to_go + " = 8 * sizeof(" + the_bits + ");"); // identical to code fragment below /////////////////////// p.println( outputTape.getPushName() + "((" + the_bits + " & (1 << (sizeof(" + the_bits + ") * 8 - 1))) ? 1 : 0);"); p.println(the_bits + " <<= 1;"); p.println(bits_to_go + "--;"); // end identical to code fragment below //////////////////// p.outdent(); p.println("}"); p.outdent(); p.println("} else {"); p.indent(); // identical to code fragment above ///////////////////////// p.println( outputTape.getPushName() + "((" + the_bits + " & (1 << (sizeof(" + the_bits + ") * 8 - 1))) ? 1 : 0);"); p.println(the_bits + " <<= 1;"); p.println(bits_to_go + "--;"); // end identical to code fragment above ///////////////////// p.outdent(); p.println("}"); // close loop p.outdent(); p.print("}"); // end of for loop. }
/* * File reader code currently works by using fread. * * The File* is declared outside any function / method. * * This code follows the model in the library of stalling (not pushing) * at end of file (detected by fread returning 0). * */ private static void genFileReaderWork( SIRFileReader filter, Tape outputTape, int selfID, CodegenPrintWriter p) { if (KjcOptions.asciifileio) { System.err.println("Error: -asciifileio not supported in cluster backend."); System.err.println("Exiting..."); System.exit(1); } String theType = "" + filter.getOutputType(); // dispatch to special routine for bit type if (theType.equals("bit")) { genFileReaderWorkBit(filter, outputTape, selfID, p); return; } // get source and destination ids of outgoing tape Tape out = RegisterStreams.getFilterOutStream(filter); int s = out.getSource(); int d = out.getDest(); // template code to generate, using symbolic free vars above. StringBuilder sb = new StringBuilder(); sb.append("\n int __index;\n"); sb.append(" for (__index=0; __index < ____n; __index++) {\n"); if (KjcOptions.compressed) { sb.append(" unsigned char __temp = 0;\n"); sb.append(" FileReader_read(__file_descr__"); sb.append(selfID); sb.append(", &__temp, 1);\n"); sb.append(" PUSH(__temp);\n"); sb.append(" unsigned int __frame_size = __temp;\n"); sb.append(" FileReader_read(__file_descr__"); sb.append(selfID); sb.append(", &__temp, 1);\n"); sb.append(" PUSH(__temp);\n"); sb.append(" __frame_size <<= 8;\n"); sb.append(" __frame_size += __temp;\n"); sb.append(" FileReader_read(__file_descr__"); sb.append(selfID); sb.append(", &__temp, 1);\n"); sb.append(" PUSH(__temp);\n"); sb.append(" __frame_size <<= 8;\n"); sb.append(" __frame_size += __temp;\n"); sb.append(" FileReader_read(__file_descr__"); sb.append(selfID); sb.append(", &__temp, 1);\n"); sb.append(" PUSH(__temp);\n"); sb.append(" __frame_size <<= 8;\n"); sb.append(" __frame_size += __temp;\n"); // the frame size includes the four bytes used to state the frame size sb.append(" FileReader_read(__file_descr__"); sb.append(selfID); sb.append(", (void *)(BUFFER + HEAD), __frame_size - 4);\n"); sb.append(" HEAD += __frame_size - 4;\n"); } else { sb.append(" PUSH(FileReader_read<"); sb.append(theType); sb.append(">(__file_descr__"); sb.append(selfID); sb.append("));\n"); } sb.append(" }\n"); String template = sb.toString(); /* " #ifdef FUSED" + "\n" + " #ifdef NOMOD" + "\n" + " // read directly into buffer" + "\n" + " if (fread(&(BUFFER[HEAD]), sizeof(BUFFER[HEAD]), ____n, FILEREADER)) {" + "\n" + " HEAD+=____n;" + "\n" + " }" + "\n" + " #else" + "\n" + " // wraparound buffer, might have to read in two pieces (but never" + "\n" + " // more, since we would overwrote what we already wrote on this call)" + "\n" + " if (HEAD+____n <= __BUF_SIZE_MASK) {" + "\n" + " // no overflow" + "\n" + " if (fread(&(BUFFER[HEAD]), sizeof(BUFFER[HEAD]), ____n, FILEREADER)) {" + "\n" + " HEAD+=____n;" + "\n" + " }" + "\n" + " } else {" + "\n" + " // overflow, need two pieces" + "\n" + " int piece1 = __BUF_SIZE_MASK - HEAD;" + "\n" + " int piece2 = ____n - piece1;" + "\n" + " if (fread(&(BUFFER[HEAD]), sizeof(BUFFER[HEAD]), piece1, FILEREADER)) {" + "\n" + " if (fread(&(BUFFER[0]), sizeof(BUFFER[HEAD]), piece2, FILEREADER)) {" + "\n" + " HEAD+=____n;" + "\n" + " HEAD&=__BUF_SIZE_MASK;" + "\n" + " }" + "\n" + " }" + "\n" + " }" + "\n" + " #endif" + "\n" + " #else" + "\n" + " // read as a block" + "\n" + " TYPE __buffer[____n];" + "\n" + " int __index;" + "\n" + " if (fread(__buffer, sizeof(__buffer[0]), ____n, FILEREADER)) {" + "\n" + " for (__index=0; __index < ____n; __index++) {" + "\n" + " // should move push out of loop, but not clear if mult-push implemented yet" + "\n" + " PUSH(__buffer[__index]);" + "\n" + " }" + "\n" + " }" + "\n" + " #endif"; */ // set values of free variables String TYPE = theType; String FILEREADER = fpName(filter); String FUSED = "__FUSED_" + s + "_" + d; String NOMOD = "__NOMOD_" + s + "_" + d; String BUFFER = "BUFFER_" + s + "_" + d; String HEAD = "HEAD_" + s + "_" + d; String BUF_SIZE_MASK = "__BUF_SIZE_MASK_" + s + "_" + d; String PUSH = outputTape.getPushName(); // replace templates with correct values template = Utils.replaceAll(template, "TYPE", TYPE); template = Utils.replaceAll(template, "FILEREADER", FILEREADER); template = Utils.replaceAll(template, "FUSED", FUSED); template = Utils.replaceAll(template, "NOMOD", NOMOD); template = Utils.replaceAll(template, "BUFFER", BUFFER); template = Utils.replaceAll(template, "HEAD", HEAD); template = Utils.replaceAll(template, "BUF_SIZE_MASK", BUF_SIZE_MASK); template = Utils.replaceAll(template, "PUSH", PUSH); // output code p.println(template); }