stage4/generate_c/generate_c.cc
changeset 283 214d3fdee596
parent 279 c0453b7f99df
child 318 746a357b8747
--- a/stage4/generate_c/generate_c.cc	Tue Apr 05 17:12:12 2011 +0100
+++ b/stage4/generate_c/generate_c.cc	Tue Apr 05 18:31:55 2011 +0100
@@ -136,6 +136,10 @@
 #define TEMP_VAR VAR_LEADER "TMP_"
 #define SOURCE_VAR VAR_LEADER "SRC_"
 
+/* please see the comment before the RET_operator_c visitor for details... */
+#define END_LABEL VAR_LEADER "end"
+
+
 /***********************************************************************/
 /***********************************************************************/
 /***********************************************************************/
@@ -426,6 +430,43 @@
     };
     virtual ~generate_c_pous_c(void) {}
 
+  private:
+    void print_end_of_block_label(void) {
+      /* Print and __end label for return statements!
+       * If label is not used by at least one goto, compiler will generate a warning.
+       * To work around this we introduce the useless goto.
+       */
+      s4o.print("\n");
+      s4o.print(s4o.indent_spaces);
+      s4o.print("/* to humour the compiler, we insert a goto */\n");
+      s4o.print(s4o.indent_spaces);
+      s4o.print("goto ");
+      s4o.print(END_LABEL);
+      s4o.print(";\n");
+      s4o.indent_left();
+
+      /* write the label marking the end of the code block */
+      /* please see the comment before the RET_operator_c visitor for details... */
+      /* also needed for return_statement_c */
+      s4o.print("\n");
+      s4o.print(s4o.indent_spaces);
+      s4o.print(END_LABEL);
+      s4o.print(":\n");
+      s4o.indent_right();
+
+      /* since every label must be followed by at least one statement, and
+       * only the functions will introduce the return statement after this label,
+       * function blocks written in IL would result in invalid C++ code.
+       * To work around this we introduce the equivalent of a 'nop' operation
+       * to humour the compiler...
+       */
+      s4o.print(s4o.indent_spaces);
+      s4o.print("/* to humour the compiler, we insert a nop */\n");
+      s4o.print(s4o.indent_spaces);
+      s4o.print("if (0);\n\n");
+    }
+  
+
 
   public:
 /********************/
@@ -593,6 +634,8 @@
   generate_c_SFC_IL_ST_c generate_c_code(&s4o, symbol->derived_function_name, symbol);
   symbol->function_body->accept(generate_c_code);
   
+  print_end_of_block_label();
+  
   vardecl = new generate_c_vardecl_c(&s4o,
                 generate_c_vardecl_c::foutputassign_vf,
                 generate_c_vardecl_c::output_vt   |
@@ -776,6 +819,7 @@
   /* (C.5) Function code */
   generate_c_SFC_IL_ST_c generate_c_code(&s4o, symbol->fblock_name, symbol, FB_FUNCTION_PARAM"->");
   symbol->fblock_body->accept(generate_c_code);
+  print_end_of_block_label();
   s4o.indent_left();
   s4o.print(s4o.indent_spaces + "} // ");
   symbol->fblock_name->accept(*this);
@@ -936,6 +980,7 @@
   /* (C.5) Function code */
   generate_c_SFC_IL_ST_c generate_c_code(&s4o, symbol->program_type_name, symbol, FB_FUNCTION_PARAM"->");
   symbol->function_block_body->accept(generate_c_code);
+  print_end_of_block_label();
   s4o.indent_left();
   s4o.print(s4o.indent_spaces + "} // ");
   symbol->program_type_name->accept(*this);