int get_arg_count(const char *name, Function *op) { uint8_t args_present[MAX_ARGS]; int nb_args, i, n; const char *p; for(i = 0;i < MAX_ARGS; i++) args_present[i] = 0; // compute the number of arguments by looking at // the uses of the op parameters for (Function::arg_iterator i = op->arg_begin(), e = op->arg_end(); i != e; ++i) { const char *tmpArgName = i->getName().c_str(); char *argName = (char *) malloc(strlen(tmpArgName + 1)); strcpy(argName, tmpArgName); if (strstart(argName, "__op_param", &p)) { if (i->hasNUsesOrMore(1)) { n = strtoul(p, NULL, 10); if (n > MAX_ARGS) error("too many arguments in %s", name); args_present[n - 1] = 1; } } } for (i = 1; i <= MAX_ARGS; i++) { char *funcName = (char *) malloc(20); sprintf(funcName, "__op_gen_label%d", i); Function *f = ops->getFunction(std::string(funcName)); if (f != NULL) { for (Function::use_iterator j = f->use_begin(), e = f->use_end(); j != e; ++j) { if (Instruction *inst = dyn_cast<Instruction>(*j)) { if (inst->getParent()->getParent() == op) { args_present[i - 1] = 1; } } } } else { std::cout << "symbol not found\n"; } } nb_args = 0; while (nb_args < MAX_ARGS && args_present[nb_args]) nb_args++; for(i = nb_args; i < MAX_ARGS; i++) { if (args_present[i]) error("inconsistent argument numbering in %s", name); } return nb_args; }
// generate code for ops which return a void value void gen_code_void_op(const char *name, FILE *outfile, Function *op) { uint8_t args_present[MAX_ARGS]; int nb_args, i, n; const char *p; for(i = 0;i < MAX_ARGS; i++) args_present[i] = 0; // compute the number of arguments by looking at // the uses of the op parameters for (Function::arg_iterator i = op->arg_begin(), e = op->arg_end(); i != e; ++i) { const char *tmpArgName = i->getName().c_str(); char *argName = (char *) malloc(strlen(tmpArgName + 1)); strcpy(argName, tmpArgName); if (strstart(argName, "__op_param", &p)) { if (i->hasNUsesOrMore(1)) { n = strtoul(p, NULL, 10); if (n > MAX_ARGS) error("too many arguments in %s", name); args_present[n - 1] = 1; } } } nb_args = 0; while (nb_args < MAX_ARGS && args_present[nb_args]) nb_args++; for(i = nb_args; i < MAX_ARGS; i++) { if (args_present[i]) error("inconsistent argument numbering in %s", name); } // add local variables for op parameters if (nb_args > 0) { fprintf(outfile, " long "); for(i = 0; i < nb_args; i++) { if (i != 0) fprintf(outfile, ", "); fprintf(outfile, "param%d", i + 1); } fprintf(outfile, ";\n"); } // load parameters in variables for(i = 0; i < nb_args; i++) { fprintf(outfile, " param%d = *opparam_ptr++;\n", i + 1); } // load op parameters into the arguments of the call // fprintf(outfile, "Value * args[MAX_ARGS];\n"); // for (i = 0; i < nb_args; i++) { // fprintf(outfile, "args[%d] = ConstantInt::get(Type::Int32Ty, param%d);\n", i, i + 1); // } // for (i = nb_args; i < MAX_ARGS; i++) { // fprintf(outfile, "args[%d] = zero;\n", i); // } // add call to micro op //fprintf(outfile, " currCall = new CallInst(M->getFunction(\"%s\"), (Value **)&args, %d, \"\", currInst);\n", name, MAX_ARGS); // load op parameters into the arguments of the call fprintf(outfile, "std::vector<Value *> args;\n"); for (i = 0; i < nb_args; i++) { fprintf(outfile, "args.push_back(ConstantInt::get(Type::Int32Ty, param%d));\n", i + 1); } for (i = nb_args; i < MAX_ARGS; i++) { fprintf(outfile, "args.push_back(zero);\n"); } // add call to micro op fprintf(outfile, " currCall = new CallInst(M->getFunction(\"%s\"), args.begin(), args.end(), \"\", currInst);\n", name); if (strcmp(name, "op_exit_tb") == 0) { fprintf(outfile, " currBB = new BasicBlock(\"\", tb);\n" " currInst = new ReturnInst(fallThrough, currBB);\n" ); } else if (strcmp(name, "op_goto_tb0")) { // fprintf(outfile, // " currBB = new BasicBlock(\"\", tb);\n" // " currInst = new ReturnInst(tb0, currBB);\n" // ); } else if (strcmp(name, "op_goto_tb1")) { // fprintf(outfile, // " currBB = new BasicBlock(\"\", tb);\n" // " currInst = new ReturnInst(tb1, currBB);\n" // ); } fprintf(outfile, " InlineFunction(currCall);"); // inlining can change the basic block the return instruction belongs to fprintf(outfile, " currBB = currInst->getParent();"); }
// generate code for ops which return a void value void gen_code_void_op(const char *name, FILE *outfile, Function *op) { uint8_t args_present[MAX_ARGS]; int nb_args, i, n; const char *p; for(i = 0;i < MAX_ARGS; i++) args_present[i] = 0; // compute the number of arguments by looking at // the uses of the op parameters for (Function::arg_iterator i = op->arg_begin(), e = op->arg_end(); i != e; ++i) { const char *tmpArgName = i->getName().c_str(); char *argName = (char *) malloc(strlen(tmpArgName + 1)); strcpy(argName, tmpArgName); if (strstart(argName, "__op_param", &p)) { if (i->hasNUsesOrMore(1)) { n = strtoul(p, NULL, 10); if (n > MAX_ARGS) error("too many arguments in %s", name); args_present[n - 1] = 1; } } } nb_args = 0; while (nb_args < MAX_ARGS && args_present[nb_args]) nb_args++; for(i = nb_args; i < MAX_ARGS; i++) { if (args_present[i]) error("inconsistent argument numbering in %s", name); } // add local variables for op parameters if (nb_args > 0) { fprintf(outfile, " long "); for(i = 0; i < nb_args; i++) { if (i != 0) fprintf(outfile, ", "); fprintf(outfile, "param%d", i + 1); } fprintf(outfile, ";\n"); } // load parameres in variables for(i = 0; i < nb_args; i++) { fprintf(outfile, " param%d = *opparam_ptr++;\n", i + 1); } // load op parameters into the arguments of the call fprintf(outfile, "Value * args[MAX_ARGS];\n"); for (i = 0; i < nb_args; i++) { fprintf(outfile, "args[%d] = ConstantInt::get(Type::Int32Ty, param%d);\n", i, i + 1); } for (i = nb_args; i < MAX_ARGS; i++) { fprintf(outfile, "args[%d] = zero;\n", i); } // add call to micro op fprintf(outfile, " currCall = new CallInst(M->getFunction(\"%s\"), (Value **)&args, %d, \"\", currBB);\n", name, MAX_ARGS); fprintf(outfile, " InlineFunction(currCall);"); }