public void emit_get_class_object(Codegen c, CodeGeneratorState s) throws PlcException, IOException { if (is_void() && !is_container()) // c.emit_summon_null(); throw new PlcException("PhantomType", "asked to emit void class object"); // Why not, btw? else if (is_int()) c.emitSummonByName(".internal.int"); else if (is_long()) c.emitSummonByName(".internal.long"); else if (is_float()) c.emitSummonByName(".internal.float"); else if (is_double()) c.emitSummonByName(".internal.double"); else if (is_string()) c.emitSummonByName(".internal.string"); else if (is_container()) { if (_container_class != null) c.emitSummonByName(_container_class.getName()); else if (_container_class_expression != null) _container_class_expression.generate_code(c, s); else c.emitSummonByName(".internal.container.array"); } else if (_class != null) c.emitSummonByName(_class.getName()); else if (_class_expression != null) _class_expression.generate_code(c, s); else throw new PlcException("emit_get_class_object", "can't get class object"); }
public void generate_code(CodeGeneratorState s) throws PlcException, IOException { if (code == null) { c.emitRet(); // empty function code return; } // ------------------------------------------ // traverse tree to allocate automatic vars? // ------------------------------------------ int n_auto_vars = svars.getUsedSlots(); int n_int_auto_vars = isvars.getUsedSlots(); // ------------------------------------------ // ------------------------------------------ // generate prologue code here // ------------------------------------------ // check number of args int n_args = args_def.size(); String good_args_label = c.getLabel(); c.emitIConst_32bit(n_args); c.emitISubLU(); c.emitJz(good_args_label); // wrong count - throw string // BUG! Need less consuming way of reporting this. Maybe by // calling class object Method? Or by summoning something? c.emitString("arg count: " + name + " in " + s.get_class().getName()); c.emitThrow(); c.markLabel(good_args_label); if (requestDebug) c.emitDebug((byte) 0x1, "Enabled debug"); // push nulls to reserve stack space for autovars // BUG! We can execute vars initialization code here, can we? // We can if code does not depend on auto vars itself, or depends only on // previous ones. // TODO: BUG! autovars in arguments are already on stack, we don't have to reserve space for (int i = n_auto_vars; i > 0; i--) c.emitPushNull(); // TODO introduce instruction to reserve o+i space in one step // Reserve integer stack place for int vars for (int i = n_int_auto_vars; i > 0; i--) c.emitIConst_0(); // ------------------------------------------ // ------------------------------------------ // generate main code by descending the tree // ------------------------------------------ code.generate_code(c, s); // ------------------------------------------ // ------------------------------------------ // generate epilogue code here // ------------------------------------------ if (requestDebug) c.emitDebug((byte) 0x2, "Disabled debug"); c.emitRet(); // catch the fall-out // ------------------------------------------ }
public void generateLlvmCode(CodeGeneratorState s, BufferedWriter llvmFile) throws PlcException, IOException { LlvmCodegen llc = new LlvmCodegen(s.get_class(), this, llvmFile); StringBuilder argdef = new StringBuilder(); boolean firstParm = true; for (ArgDefinition a : args_def) { if (!firstParm) argdef.append(", "); firstParm = false; argdef.append("i64 %" + a.getName()); } String llvmMethodName = name; name = name.replaceAll("<init>", "_\\$_Constructor"); llc.putln(String.format("define %s @%s(%s) {", llc.getObjectType(), name, argdef)); // function if (code != null) { // ------------------------------------------ // traverse tree to allocate automatic vars? // ------------------------------------------ // int n_auto_vars = svars.getUsedSlots(); // int n_int_auto_vars = isvars.getUsedSlots(); // ------------------------------------------ // ------------------------------------------ // generate prologue code here // ------------------------------------------ /* // check number of args int n_args = args_def.size(); String good_args_label = c.getLabel(); c.emitIConst_32bit(n_args); c.emitISubLU(); c.emitJz(good_args_label); // wrong count - throw string // BUG! Need less consuming way of reporting this. Maybe by // calling class object Method? Or by summoning something? c.emitString("arg count: "+name + " in " + s.get_class().getName()); c.emitThrow(); c.markLabel(good_args_label); */ if (requestDebug) llc.emitDebug((byte) 0x1); // if(requestDebug) llc.emitDebug((byte)0x1,"Enabled debug"); // push nulls to reserve stack space for autovars // BUG! We can execute vars initialization code here, can we? // We can if code does not depend on auto vars itself, or depends only on // previous ones. // for( int i = n_auto_vars; i > 0; i-- ) c.emitPushNull(); // Reserve integer stack place for int vars for( int i = n_int_auto_vars; i > 0; i-- ) // c.emitIConst_0(); // ------------------------------------------ // ------------------------------------------ // generate main code by descending the tree // ------------------------------------------ code.generateLlvmCode(llc); // ------------------------------------------ // ------------------------------------------ // generate epilogue code here // ------------------------------------------ // if(requestDebug) c.emitDebug((byte)0x2,"Disabled debug"); if (requestDebug) llc.emitDebug((byte) 0x2); } // catch the fall-out llc.putln("ret " + llc.getObjectType() + " <{ i8* null, i8* null }> ;"); // empty function code llc.putln("}"); // end of function // ------------------------------------------ // Part of code is generated to the buffer to // be emitted after the method code. Flush it // now. // ------------------------------------------ llc.flushPostponedCode(); }