Added support for constants in shader `case` and array size declaration

This commit is contained in:
Yuri Roubinsky 2020-12-16 20:13:56 +03:00
parent 9e49dbda2a
commit fe4c8e387b
3 changed files with 119 additions and 28 deletions

View File

@ -930,7 +930,11 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
}
declaration += _mkid(adnode->declarations[i].name);
declaration += "[";
declaration += itos(adnode->declarations[i].size);
if (adnode->size_expression != nullptr) {
declaration += _dump_node_code(adnode->size_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
} else {
declaration += itos(adnode->declarations[i].size);
}
declaration += "]";
int sz = adnode->declarations[i].initializer.size();
if (sz > 0) {

View File

@ -920,7 +920,7 @@ void ShaderLanguage::clear() {
}
}
bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_reassign, const FunctionInfo &p_function_info, const StringName &p_identifier, DataType *r_data_type, IdentifierType *r_type, bool *r_is_const, int *r_array_size, StringName *r_struct_name) {
bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_reassign, const FunctionInfo &p_function_info, const StringName &p_identifier, DataType *r_data_type, IdentifierType *r_type, bool *r_is_const, int *r_array_size, StringName *r_struct_name, ConstantNode::Value *r_constant_value) {
if (p_function_info.built_ins.has(p_identifier)) {
if (r_data_type) {
*r_data_type = p_function_info.built_ins[p_identifier].type;
@ -968,6 +968,9 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
if (r_struct_name) {
*r_struct_name = p_block->variables[p_identifier].struct_name;
}
if (r_constant_value) {
*r_constant_value = p_block->variables[p_identifier].value;
}
return true;
}
@ -1028,6 +1031,9 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
}
if (shader->constants.has(p_identifier)) {
if (r_is_const) {
*r_is_const = true;
}
if (r_data_type) {
*r_data_type = shader->constants[p_identifier].type;
}
@ -1040,6 +1046,11 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
if (r_struct_name) {
*r_struct_name = shader->constants[p_identifier].type_str;
}
if (r_constant_value) {
if (shader->constants[p_identifier].initializer && shader->constants[p_identifier].initializer->values.size() == 1) {
*r_constant_value = shader->constants[p_identifier].initializer->values[0];
}
}
return true;
}
@ -5010,17 +5021,53 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
decl.name = name;
decl.size = 0U;
pos = _get_tkpos();
tk = _get_token();
if (tk.type == TK_BRACKET_CLOSE) {
unknown_size = true;
} else {
if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) {
_set_tkpos(pos);
Node *n = _parse_and_reduce_expression(p_block, p_function_info);
if (n) {
if (n->type == Node::TYPE_VARIABLE) {
VariableNode *vn = static_cast<VariableNode *>(n);
if (vn) {
ConstantNode::Value v;
DataType data_type;
_find_identifier(p_block, false, p_function_info, vn->name, &data_type, nullptr, &is_const, nullptr, nullptr, &v);
if (is_const) {
if (data_type == TYPE_INT) {
int32_t value = v.sint;
if (value > 0) {
node->size_expression = n;
decl.size = (uint32_t)value;
}
} else if (data_type == TYPE_UINT) {
uint32_t value = v.uint;
if (value > 0U) {
node->size_expression = n;
decl.size = value;
}
}
}
}
} else if (n->type == Node::TYPE_OPERATOR) {
_set_error("Array size expressions are not yet implemented.");
return ERR_PARSE_ERROR;
}
}
} else if (((int)tk.constant) > 0) {
decl.size = (uint32_t)tk.constant;
}
if (decl.size == 0U) {
_set_error("Expected integer constant > 0 or ']'");
return ERR_PARSE_ERROR;
}
decl.size = ((uint32_t)tk.constant);
tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
@ -5218,7 +5265,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
_set_error("Expected array initialization");
return ERR_PARSE_ERROR;
}
if (is_const) {
if (node->is_const) {
_set_error("Expected initialization of constant");
return ERR_PARSE_ERROR;
}
@ -5252,6 +5299,13 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
}
decl.initializer = n;
if (n->type == Node::TYPE_CONSTANT) {
ConstantNode *const_node = static_cast<ConstantNode *>(n);
if (const_node && const_node->values.size() == 1) {
var.value = const_node->values[0];
}
}
if (var.type == TYPE_STRUCT ? (var.struct_name != n->get_datatype_name()) : (var.type != n->get_datatype())) {
_set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (var.type == TYPE_STRUCT ? String(var.struct_name) : get_datatype_name(var.type)) + "'");
return ERR_PARSE_ERROR;
@ -5420,18 +5474,29 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
ControlFlowNode *flow = (ControlFlowNode *)switch_block->statements[i];
if (flow) {
if (flow->flow_op == FLOW_OP_CASE) {
ConstantNode *n2 = static_cast<ConstantNode *>(flow->expressions[0]);
if (!n2) {
return ERR_PARSE_ERROR;
if (flow->expressions[0]->type == Node::TYPE_CONSTANT) {
ConstantNode *cn = static_cast<ConstantNode *>(flow->expressions[0]);
if (!cn || cn->values.empty()) {
return ERR_PARSE_ERROR;
}
if (constants.has(cn->values[0].sint)) {
_set_error("Duplicated case label: '" + itos(cn->values[0].sint) + "'");
return ERR_PARSE_ERROR;
}
constants.insert(cn->values[0].sint);
} else if (flow->expressions[0]->type == Node::TYPE_VARIABLE) {
VariableNode *vn = static_cast<VariableNode *>(flow->expressions[0]);
if (!vn) {
return ERR_PARSE_ERROR;
}
ConstantNode::Value v;
_find_identifier(p_block, false, p_function_info, vn->name, nullptr, nullptr, nullptr, nullptr, nullptr, &v);
if (constants.has(v.sint)) {
_set_error("Duplicated case label: '" + itos(v.sint) + "'");
return ERR_PARSE_ERROR;
}
constants.insert(v.sint);
}
if (n2->values.empty()) {
return ERR_PARSE_ERROR;
}
if (constants.has(n2->values[0].sint)) {
_set_error("Duplicated case label: '" + itos(n2->values[0].sint) + "'");
return ERR_PARSE_ERROR;
}
constants.insert(n2->values[0].sint);
} else if (flow->flow_op == FLOW_OP_DEFAULT) {
continue;
} else {
@ -5467,12 +5532,38 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
tk = _get_token();
}
if (tk.type != TK_INT_CONSTANT) {
_set_error("Expected integer constant");
return ERR_PARSE_ERROR;
}
Node *n = nullptr;
int constant = (int)tk.constant * sign;
if (tk.type != TK_INT_CONSTANT) {
bool correct_constant_expression = false;
DataType data_type;
if (tk.type == TK_IDENTIFIER) {
bool is_const;
_find_identifier(p_block, false, p_function_info, tk.text, &data_type, nullptr, &is_const);
if (is_const) {
if (data_type == TYPE_INT) {
correct_constant_expression = true;
}
}
}
if (!correct_constant_expression) {
_set_error("Expected integer constant");
return ERR_PARSE_ERROR;
}
VariableNode *vn = alloc_node<VariableNode>();
vn->name = tk.text;
n = vn;
} else {
ConstantNode::Value v;
v.sint = (int)tk.constant * sign;
ConstantNode *cn = alloc_node<ConstantNode>();
cn->values.push_back(v);
cn->datatype = TYPE_INT;
n = cn;
}
tk = _get_token();
@ -5484,12 +5575,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
ControlFlowNode *cf = alloc_node<ControlFlowNode>();
cf->flow_op = FLOW_OP_CASE;
ConstantNode *n = alloc_node<ConstantNode>();
ConstantNode::Value v;
v.sint = constant;
n->values.push_back(v);
n->datatype = TYPE_INT;
BlockNode *case_block = alloc_node<BlockNode>();
case_block->block_type = BlockNode::BLOCK_TYPE_CASE;
case_block->parent_block = p_block;

View File

@ -437,6 +437,7 @@ public:
DataType datatype = TYPE_VOID;
String struct_name;
bool is_const = false;
Node *size_expression = nullptr;
struct Declaration {
StringName name;
@ -496,6 +497,7 @@ public:
int line; //for completion
int array_size;
bool is_const;
ConstantNode::Value value;
};
Map<StringName, Variable> variables;
@ -819,7 +821,7 @@ private:
IDENTIFIER_CONSTANT,
};
bool _find_identifier(const BlockNode *p_block, bool p_allow_reassign, const FunctionInfo &p_function_info, const StringName &p_identifier, DataType *r_data_type = nullptr, IdentifierType *r_type = nullptr, bool *r_is_const = nullptr, int *r_array_size = nullptr, StringName *r_struct_name = nullptr);
bool _find_identifier(const BlockNode *p_block, bool p_allow_reassign, const FunctionInfo &p_function_info, const StringName &p_identifier, DataType *r_data_type = nullptr, IdentifierType *r_type = nullptr, bool *r_is_const = nullptr, int *r_array_size = nullptr, StringName *r_struct_name = nullptr, ConstantNode::Value *r_constant_value = nullptr);
bool _is_operator_assign(Operator p_op) const;
bool _validate_assign(Node *p_node, const FunctionInfo &p_function_info, String *r_message = nullptr);
bool _validate_operator(OperatorNode *p_op, DataType *r_ret_type = nullptr);