summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2017-10-14 05:18:51 +0200
committerBenjamin Otte <otte@redhat.com>2017-10-30 02:58:03 +0100
commitc546e644193347023718dca64c364262b70192e6 (patch)
tree916ec12d42c1a3fea96410db93ca7dd31c037c74
parent04dc25ed62e703547615ff65a6306a7d74ed8f60 (diff)
downloadgtk+-c546e644193347023718dca64c364262b70192e6.tar.gz
gskslstatement: Add a return value to spirv writing
When writing SPIRV, statements return TRUE if they terminate the current block (such as in a return statement). This is necessary because no code may be written into a block after a termination opcode, so make all other code check this return value and stop writing anything into the current block.
-rw-r--r--gsk/gskslfunction.c5
-rw-r--r--gsk/gskslstatement.c60
-rw-r--r--gsk/gskslstatementprivate.h2
3 files changed, 46 insertions, 21 deletions
diff --git a/gsk/gskslfunction.c b/gsk/gskslfunction.c
index 6f7964a513..7696b09dd5 100644
--- a/gsk/gskslfunction.c
+++ b/gsk/gskslfunction.c
@@ -452,10 +452,7 @@ gsk_sl_function_declared_write_spv (const GskSlFunction *function,
if (initializer)
initializer (writer, initializer_data);
- gsk_sl_statement_write_spv (declared->statement, writer);
-
- if (gsk_sl_type_is_void (return_type) &&
- gsk_sl_statement_get_jump (declared->statement) < GSK_SL_JUMP_RETURN)
+ if (!gsk_sl_statement_write_spv (declared->statement, writer))
gsk_spv_writer_return (writer);
gsk_spv_writer_function_end (writer);
diff --git a/gsk/gskslstatement.c b/gsk/gskslstatement.c
index 5c731eb9c5..f230dfeb85 100644
--- a/gsk/gskslstatement.c
+++ b/gsk/gskslstatement.c
@@ -47,7 +47,7 @@ struct _GskSlStatementClass {
void (* print) (const GskSlStatement *statement,
GskSlPrinter *printer);
GskSlJump (* get_jump) (const GskSlStatement *statement);
- void (* write_spv) (const GskSlStatement *statement,
+ gboolean (* write_spv) (const GskSlStatement *statement,
GskSpvWriter *writer);
};
@@ -95,10 +95,11 @@ gsk_sl_statement_empty_get_jump (const GskSlStatement *statement)
return GSK_SL_JUMP_NONE;
}
-static void
+static gboolean
gsk_sl_statement_empty_write_spv (const GskSlStatement *statement,
GskSpvWriter *writer)
{
+ return FALSE;
}
static const GskSlStatementClass GSK_SL_STATEMENT_EMPTY = {
@@ -164,7 +165,7 @@ gsk_sl_statement_compound_get_jump (const GskSlStatement *statement)
return gsk_sl_statement_get_jump (last->data);
}
-static void
+static gboolean
gsk_sl_statement_compound_write_spv (const GskSlStatement *statement,
GskSpvWriter *writer)
{
@@ -173,8 +174,15 @@ gsk_sl_statement_compound_write_spv (const GskSlStatement *statement,
for (l = compound->statements; l; l = l->next)
{
- gsk_sl_statement_write_spv (l->data, writer);
+ if (gsk_sl_statement_write_spv (l->data, writer))
+ {
+ /* If this happens, the rest of the code is unreachable and
+ * we don't need to emit it. */
+ return TRUE;
+ }
}
+
+ return FALSE;
}
static const GskSlStatementClass GSK_SL_STATEMENT_COMPOUND = {
@@ -228,7 +236,7 @@ gsk_sl_statement_declaration_get_jump (const GskSlStatement *statement)
return GSK_SL_JUMP_NONE;
}
-static void
+static gboolean
gsk_sl_statement_declaration_write_spv (const GskSlStatement *statement,
GskSpvWriter *writer)
{
@@ -243,6 +251,8 @@ gsk_sl_statement_declaration_write_spv (const GskSlStatement *statement,
writer,
gsk_sl_expression_write_spv (declaration->initial, writer));
}
+
+ return FALSE;
}
static const GskSlStatementClass GSK_SL_STATEMENT_DECLARATION = {
@@ -294,7 +304,7 @@ gsk_sl_statement_return_get_jump (const GskSlStatement *statement)
return GSK_SL_JUMP_RETURN;
}
-static void
+static gboolean
gsk_sl_statement_return_write_spv (const GskSlStatement *statement,
GskSpvWriter *writer)
{
@@ -309,6 +319,8 @@ gsk_sl_statement_return_write_spv (const GskSlStatement *statement,
{
gsk_spv_writer_return (writer);
}
+
+ return TRUE;
}
static const GskSlStatementClass GSK_SL_STATEMENT_RETURN = {
@@ -386,7 +398,7 @@ gsk_sl_statement_if_get_jump (const GskSlStatement *statement)
gsk_sl_statement_get_jump (if_stmt->else_part));
}
-static void
+static gboolean
gsk_sl_statement_if_write_spv (const GskSlStatement *statement,
GskSpvWriter *writer)
{
@@ -403,17 +415,17 @@ gsk_sl_statement_if_write_spv (const GskSlStatement *statement,
after_block = gsk_spv_writer_pop_code_block (writer);
gsk_spv_writer_push_code_block (writer, if_block);
- gsk_sl_statement_write_spv (if_stmt->if_part, writer);
- gsk_spv_writer_branch (writer,
- gsk_spv_code_block_get_label (after_block));
+ if (!gsk_sl_statement_write_spv (if_stmt->if_part, writer))
+ gsk_spv_writer_branch (writer,
+ gsk_spv_code_block_get_label (after_block));
gsk_spv_writer_pop_code_block (writer);
if (if_stmt->else_part)
{
else_id = gsk_spv_writer_push_new_code_block (writer);
- gsk_sl_statement_write_spv (if_stmt->else_part, writer);
- gsk_spv_writer_branch (writer,
- gsk_spv_code_block_get_label (after_block));
+ if (!gsk_sl_statement_write_spv (if_stmt->else_part, writer))
+ gsk_spv_writer_branch (writer,
+ gsk_spv_code_block_get_label (after_block));
else_block = gsk_spv_writer_pop_code_block (writer);
}
else
@@ -438,6 +450,8 @@ gsk_sl_statement_if_write_spv (const GskSlStatement *statement,
gsk_spv_writer_push_code_block (writer, after_block);
gsk_spv_writer_commit_code_block (writer);
+
+ return FALSE;
}
static const GskSlStatementClass GSK_SL_STATEMENT_IF = {
@@ -483,13 +497,15 @@ gsk_sl_statement_expression_get_jump (const GskSlStatement *statement)
return GSK_SL_JUMP_NONE;
}
-static void
+static gboolean
gsk_sl_statement_expression_write_spv (const GskSlStatement *statement,
GskSpvWriter *writer)
{
GskSlStatementExpression *expression_statement = (GskSlStatementExpression *) statement;
gsk_sl_expression_write_spv (expression_statement->expression, writer);
+
+ return FALSE;
}
static const GskSlStatementClass GSK_SL_STATEMENT_EXPRESSION = {
@@ -895,10 +911,22 @@ gsk_sl_statement_get_jump (const GskSlStatement *statement)
return statement->class->get_jump (statement);
}
-void
+/**
+ * gsk_sl_statement_write_spv:
+ * @statement: The statement to write
+ * @writer: The writer to write to
+ *
+ * Writes the statement into the current code block. The @writer must
+ * have created a current code block before this function can be called.
+ *
+ * Returns: %TRUE if this statement terminated the block it was in.
+ * This happens usually when gsk_sl_statement_get_jump() for
+ * @statement indicates that it causes a jump.
+ **/
+gboolean
gsk_sl_statement_write_spv (const GskSlStatement *statement,
GskSpvWriter *writer)
{
- statement->class->write_spv (statement, writer);
+ return statement->class->write_spv (statement, writer);
}
diff --git a/gsk/gskslstatementprivate.h b/gsk/gskslstatementprivate.h
index 99d48dfcc7..c550a50366 100644
--- a/gsk/gskslstatementprivate.h
+++ b/gsk/gskslstatementprivate.h
@@ -47,7 +47,7 @@ void gsk_sl_statement_print (const GskSlStat
GskSlJump gsk_sl_statement_get_jump (const GskSlStatement *statement);
-void gsk_sl_statement_write_spv (const GskSlStatement *statement,
+gboolean gsk_sl_statement_write_spv (const GskSlStatement *statement,
GskSpvWriter *writer);
G_END_DECLS