[gtk+/wip/otte/shader: 116/226] gskslstatement: Add gsk_sl_Stement_get_jump()



commit a3dec06d3f3ff903659e301070b75069c28fda10
Author: Benjamin Otte <otte redhat com>
Date:   Sun Oct 1 05:07:48 2017 +0200

    gskslstatement: Add gsk_sl_Stement_get_jump()
    
    This queries where a statement jumps to after it is done. The enum is
    sorted by importance, larger values jump further.
    
    We use this to do 3 things:
    1. Error out if the function body statement does not return a value from
       a non-void function.
    2. Make sure to emit a Return as last instruction in a function body
    3. Print a warning about dead code when statements follow a jump.

 gsk/gskslcompiler.h         |    1 +
 gsk/gskslfunction.c         |   14 +++++++++
 gsk/gskslstatement.c        |   68 +++++++++++++++++++++++++++++++++++++++++++
 gsk/gskslstatementprivate.h |   10 ++++++
 4 files changed, 93 insertions(+), 0 deletions(-)
---
diff --git a/gsk/gskslcompiler.h b/gsk/gskslcompiler.h
index ea56d27..6f0d741 100644
--- a/gsk/gskslcompiler.h
+++ b/gsk/gskslcompiler.h
@@ -42,6 +42,7 @@ typedef enum {
 
 typedef enum {
   GSK_SL_COMPILER_WARNING_CONSTANT,
+  GSK_SL_COMPILER_WARNING_DEAD_CODE,
   GSK_SL_COMPILER_WARNING_SHADOW
 } GskSlCompilerWarning;
 
diff --git a/gsk/gskslfunction.c b/gsk/gskslfunction.c
index 3f8c6c0..cdb150c 100644
--- a/gsk/gskslfunction.c
+++ b/gsk/gskslfunction.c
@@ -429,6 +429,14 @@ gsk_sl_function_declared_write_spv (const GskSlFunction *function,
 
   gsk_sl_statement_write_spv (declared->statement, writer);
 
+  if (gsk_sl_type_is_void (declared->return_type) &&
+      gsk_sl_statement_get_jump (declared->statement) < GSK_SL_JUMP_RETURN)
+    {
+      gsk_spv_writer_add (writer,
+                          GSK_SPV_WRITER_SECTION_CODE,
+                          1, GSK_SPV_OP_RETURN,
+                          NULL);
+    }
   gsk_spv_writer_add (writer,
                       GSK_SPV_WRITER_SECTION_CODE,
                       1, GSK_SPV_OP_FUNCTION_END,
@@ -594,6 +602,12 @@ gsk_sl_function_new_parse (GskSlScope        *scope,
 
   function->statement = gsk_sl_statement_parse_compound (function->scope, preproc, FALSE);
 
+  if (!gsk_sl_type_is_void (function->return_type) &&
+      gsk_sl_statement_get_jump (function->statement) < GSK_SL_JUMP_RETURN)
+    {
+      gsk_sl_preprocessor_error (preproc, SYNTAX, "Function does not return a value.");
+    }
+
   return (GskSlFunction *) function;
 }
 
diff --git a/gsk/gskslstatement.c b/gsk/gskslstatement.c
index 299bd56..bc8f1e6 100644
--- a/gsk/gskslstatement.c
+++ b/gsk/gskslstatement.c
@@ -46,6 +46,7 @@ struct _GskSlStatementClass {
 
   void                  (* print)                               (const GskSlStatement   *statement,
                                                                  GskSlPrinter           *printer);
+  GskSlJump             (* get_jump)                            (const GskSlStatement   *statement);
   void                  (* write_spv)                           (const GskSlStatement   *statement,
                                                                  GskSpvWriter           *writer);
 };
@@ -88,6 +89,12 @@ gsk_sl_statement_empty_print (const GskSlStatement *statement,
   gsk_sl_printer_append (printer, ";");
 }
 
+static GskSlJump
+gsk_sl_statement_empty_get_jump (const GskSlStatement *statement)
+{
+  return GSK_SL_JUMP_NONE;
+}
+
 static void
 gsk_sl_statement_empty_write_spv (const GskSlStatement *statement,
                                   GskSpvWriter         *writer)
@@ -97,6 +104,7 @@ gsk_sl_statement_empty_write_spv (const GskSlStatement *statement,
 static const GskSlStatementClass GSK_SL_STATEMENT_EMPTY = {
   gsk_sl_statement_empty_free,
   gsk_sl_statement_empty_print,
+  gsk_sl_statement_empty_get_jump,
   gsk_sl_statement_empty_write_spv
 };
 
@@ -142,6 +150,20 @@ gsk_sl_statement_compound_print (const GskSlStatement *statement,
   gsk_sl_printer_append (printer, "}");
 }
 
+static GskSlJump
+gsk_sl_statement_compound_get_jump (const GskSlStatement *statement)
+{
+  GskSlStatementCompound *compound = (GskSlStatementCompound *) statement;
+  GSList *last;
+
+  if (compound->statements == NULL)
+    return GSK_SL_JUMP_NONE;
+
+  last = g_slist_last (compound->statements);
+
+  return gsk_sl_statement_get_jump (last->data);
+}
+
 static void
 gsk_sl_statement_compound_write_spv (const GskSlStatement *statement,
                                      GskSpvWriter         *writer)
@@ -158,6 +180,7 @@ gsk_sl_statement_compound_write_spv (const GskSlStatement *statement,
 static const GskSlStatementClass GSK_SL_STATEMENT_COMPOUND = {
   gsk_sl_statement_compound_free,
   gsk_sl_statement_compound_print,
+  gsk_sl_statement_compound_get_jump,
   gsk_sl_statement_compound_write_spv
 };
 
@@ -199,6 +222,12 @@ gsk_sl_statement_declaration_print (const GskSlStatement *statement,
   gsk_sl_printer_append (printer, ";");
 }
 
+static GskSlJump
+gsk_sl_statement_declaration_get_jump (const GskSlStatement *statement)
+{
+  return GSK_SL_JUMP_NONE;
+}
+
 static void
 gsk_sl_statement_declaration_write_spv (const GskSlStatement *statement,
                                         GskSpvWriter         *writer)
@@ -221,6 +250,7 @@ gsk_sl_statement_declaration_write_spv (const GskSlStatement *statement,
 static const GskSlStatementClass GSK_SL_STATEMENT_DECLARATION = {
   gsk_sl_statement_declaration_free,
   gsk_sl_statement_declaration_print,
+  gsk_sl_statement_declaration_get_jump,
   gsk_sl_statement_declaration_write_spv
 };
 
@@ -260,6 +290,12 @@ gsk_sl_statement_return_print (const GskSlStatement *statement,
   gsk_sl_printer_append (printer, ";");
 }
 
+static GskSlJump
+gsk_sl_statement_return_get_jump (const GskSlStatement *statement)
+{
+  return GSK_SL_JUMP_RETURN;
+}
+
 static void
 gsk_sl_statement_return_write_spv (const GskSlStatement *statement,
                                    GskSpvWriter         *writer)
@@ -270,6 +306,7 @@ gsk_sl_statement_return_write_spv (const GskSlStatement *statement,
 static const GskSlStatementClass GSK_SL_STATEMENT_RETURN = {
   gsk_sl_statement_return_free,
   gsk_sl_statement_return_print,
+  gsk_sl_statement_return_get_jump,
   gsk_sl_statement_return_write_spv
 };
 
@@ -329,6 +366,18 @@ gsk_sl_statement_if_print (const GskSlStatement *statement,
     }
 }
  
+static GskSlJump
+gsk_sl_statement_if_get_jump (const GskSlStatement *statement)
+{
+  GskSlStatementIf *if_stmt = (GskSlStatementIf *) statement;
+
+  if (if_stmt->else_part == NULL)
+    return GSK_SL_JUMP_NONE;
+
+  return MIN (gsk_sl_statement_get_jump (if_stmt->if_part),
+              gsk_sl_statement_get_jump (if_stmt->else_part));
+}
+
 static void
 gsk_sl_statement_if_write_spv (const GskSlStatement *statement,
                                GskSpvWriter         *writer)
@@ -388,6 +437,7 @@ gsk_sl_statement_if_write_spv (const GskSlStatement *statement,
 static const GskSlStatementClass GSK_SL_STATEMENT_IF = {
   gsk_sl_statement_if_free,
   gsk_sl_statement_if_print,
+  gsk_sl_statement_if_get_jump,
   gsk_sl_statement_if_write_spv
 };
 
@@ -421,6 +471,12 @@ gsk_sl_statement_expression_print (const GskSlStatement *statement,
   gsk_sl_printer_append (printer, ";");
 }
  
+static GskSlJump
+gsk_sl_statement_expression_get_jump (const GskSlStatement *statement)
+{
+  return GSK_SL_JUMP_NONE;
+}
+
 static void
 gsk_sl_statement_expression_write_spv (const GskSlStatement *statement,
                                        GskSpvWriter         *writer)
@@ -433,6 +489,7 @@ gsk_sl_statement_expression_write_spv (const GskSlStatement *statement,
 static const GskSlStatementClass GSK_SL_STATEMENT_EXPRESSION = {
   gsk_sl_statement_expression_free,
   gsk_sl_statement_expression_print,
+  gsk_sl_statement_expression_get_jump,
   gsk_sl_statement_expression_write_spv
 };
 
@@ -562,6 +619,7 @@ gsk_sl_statement_parse_compound (GskSlScope        *scope,
 {
   GskSlStatementCompound *compound;
   const GskSlToken *token;
+  GskSlJump jump = GSK_SL_JUMP_NONE;
 
   compound = gsk_sl_statement_new (GskSlStatementCompound, &GSK_SL_STATEMENT_COMPOUND);
   if (new_scope)
@@ -584,8 +642,12 @@ gsk_sl_statement_parse_compound (GskSlScope        *scope,
     {
       GskSlStatement *statement;
 
+      if (jump != GSK_SL_JUMP_NONE)
+        gsk_sl_preprocessor_warn (preproc, DEAD_CODE, "Statement cannot be reached.");
+
       statement = gsk_sl_statement_parse (scope, preproc);
       compound->statements = g_slist_prepend (compound->statements, statement);
+      jump = gsk_sl_statement_get_jump (statement);
     }
   compound->statements = g_slist_reverse (compound->statements);
 
@@ -824,6 +886,12 @@ gsk_sl_statement_print (const GskSlStatement *statement,
   statement->class->print (statement, printer);
 }
 
+GskSlJump
+gsk_sl_statement_get_jump (const GskSlStatement *statement)
+{
+  return statement->class->get_jump (statement);
+}
+
 void
 gsk_sl_statement_write_spv (const GskSlStatement *statement,
                             GskSpvWriter         *writer)
diff --git a/gsk/gskslstatementprivate.h b/gsk/gskslstatementprivate.h
index 1e4098f..99d48df 100644
--- a/gsk/gskslstatementprivate.h
+++ b/gsk/gskslstatementprivate.h
@@ -25,6 +25,14 @@
 
 G_BEGIN_DECLS
 
+typedef enum {
+  GSK_SL_JUMP_NONE,
+  GSK_SL_JUMP_BREAK,
+  GSK_SL_JUMP_CONTINUE,
+  GSK_SL_JUMP_RETURN,
+  GSK_SL_JUMP_DISCARD
+} GskSlJump;
+
 GskSlStatement *        gsk_sl_statement_parse                  (GskSlScope             *scope,
                                                                  GskSlPreprocessor      *preproc);
 GskSlStatement *        gsk_sl_statement_parse_compound         (GskSlScope             *scope,
@@ -37,6 +45,8 @@ void                    gsk_sl_statement_unref                  (GskSlStatement
 void                    gsk_sl_statement_print                  (const GskSlStatement   *statement,
                                                                  GskSlPrinter           *printer);
 
+GskSlJump               gsk_sl_statement_get_jump               (const GskSlStatement   *statement);
+
 void                    gsk_sl_statement_write_spv              (const GskSlStatement   *statement,
                                                                  GskSpvWriter           *writer);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]