void Parser::start() { while(buffer->getSize()) { Token* token = buffer->peek(0); switch(token->type) { case IN: { match(IN); Token* tokType = match(TYPE); Token* tokName = match(VARIABLE); match(END); Variable* variable = variables->find(variables->root, tokName->data, ¤tFunction); if(variable == NULL) { Variable *variable = (Variable*) malloc(sizeof(Variable)); variable->name = (char*)malloc(sizeof(tokName->data)); strncpy(variable->name, tokName->data, strlen(tokName->data)); variable->type = VariableType(variabletypes->find(variabletypes->root, tokType->data)->type); variable->function = currentFunction; in->push(variables->insert(variables->root, variable)); } else { printf("[Parser Error] Redefinition of variable %s\n", variable->name); free(variable); } break; } case OUT: { match(OUT); Token* tokType = match(TYPE); Token* tokName = match(VARIABLE); match(END); Variable* variable = variables->find(variables->root, tokName->data, ¤tFunction); if(variable == NULL) { Variable *variable = (Variable*) malloc(sizeof(Variable)); variable->name = (char*)malloc(sizeof(tokName->data)); strncpy(variable->name, tokName->data, strlen(tokName->data)); variable->type = VariableType(variabletypes->find(variabletypes->root, tokType->data)->type); variable->function = currentFunction; out->push(variables->insert(variables->root, variable)); } else { printf("[Parser Error] Redefinition of variable %s\n", variable->name); free(variable); } break; } case UNIFORM: { match(UNIFORM); Token* tokType = match(TYPE); Token* tokName = match(VARIABLE); match(END); Variable* variable = variables->find(variables->root, tokName->data, ¤tFunction); if(variable == NULL) { Variable *variable = (Variable*) malloc(sizeof(Variable)); variable->name = (char*)malloc(sizeof(tokName->data)); strncpy(variable->name, tokName->data, strlen(tokName->data)); variable->type = VariableType(variabletypes->find(variabletypes->root, tokType->data)->type); variable->function = currentFunction; uniform->push(variables->insert(variables->root, variable)); } else { printf("[Parser Error] Redefinition of variable %s\n", variable->name); free(variable); } break; } case TYPE: { Token* tokType = match(TYPE); Token* tokName = match(VARIABLE); if(buffer->peek(0)->type == LPAR) { match(LPAR); Function* function = functions->findFunction(functions->root, tokName->data); if(function != NULL) { printf("[Parser Error] Redefinition of function %s\n", function->name); free(function); break; } Block* block = new Block(); blockList->push(block); int blockId = blockList->getSize(); Function* function = (Function*) malloc(sizeof(Function)); strncpy(function->name, tokName->data, strlen(tokName->data)); function->ret = VariableType(variabletypes->find(variabletypes->root, tokType->data)->type); function->arguments = getArguments(); function->block = blockId; currentFunction = functions->addFunction(functions->root, function); processBlock(block); currentFunction = 0; break; } Variable* variable = variables->find(variables->root, tokName->data, ¤tFunction); if(variable == NULL) { Variable *variable = (Variable*) malloc(sizeof(Variable)); variable->name = (char*)malloc(sizeof(tokName->data)); strncpy(variable->name, tokName->data, strlen(tokName->data)); variable->type = VariableType(variabletypes->find(variabletypes->root, tokType->data)->type); variable->function = currentFunction; variables->insert(variables->root, variable); } else { printf("[Parser Error] Redefinition of variable %s\n", variable->name); free(variable); } break; } default: { printf("[Parser Error] Invalid token %s(%d) detected!\n", token->data, token->type); return; } } } }
VariableType StringNode::getType() const { return VariableType(BuiltIns::ASCII_string_type, true); }
void LabelAttributes::SetFromNode(DataNode *parentNode) { if(parentNode == 0) return; DataNode *searchNode = parentNode->GetNode("LabelAttributes"); if(searchNode == 0) return; DataNode *node; if((node = searchNode->GetNode("varType")) != 0) { // Allow enums to be int or string in the config file if(node->GetNodeType() == INT_NODE) { int ival = node->AsInt(); if(ival >= 0 && ival < 10) SetVarType(VariableType(ival)); } else if(node->GetNodeType() == STRING_NODE) { VariableType value; if(VariableType_FromString(node->AsString(), value)) SetVarType(value); } } if((node = searchNode->GetNode("legendFlag")) != 0) SetLegendFlag(node->AsBool()); if((node = searchNode->GetNode("showNodes")) != 0) SetShowNodes(node->AsBool()); if((node = searchNode->GetNode("showCells")) != 0) SetShowCells(node->AsBool()); if((node = searchNode->GetNode("restrictNumberOfLabels")) != 0) SetRestrictNumberOfLabels(node->AsBool()); if((node = searchNode->GetNode("drawLabelsFacing")) != 0) { // Allow enums to be int or string in the config file if(node->GetNodeType() == INT_NODE) { int ival = node->AsInt(); if(ival >= 0 && ival < 3) SetDrawLabelsFacing(LabelDrawFacing(ival)); } else if(node->GetNodeType() == STRING_NODE) { LabelDrawFacing value; if(LabelDrawFacing_FromString(node->AsString(), value)) SetDrawLabelsFacing(value); } } if((node = searchNode->GetNode("labelDisplayFormat")) != 0) { // Allow enums to be int or string in the config file if(node->GetNodeType() == INT_NODE) { int ival = node->AsInt(); if(ival >= 0 && ival < 3) SetLabelDisplayFormat(LabelIndexDisplay(ival)); } else if(node->GetNodeType() == STRING_NODE) { LabelIndexDisplay value; if(LabelIndexDisplay_FromString(node->AsString(), value)) SetLabelDisplayFormat(value); } } if((node = searchNode->GetNode("numberOfLabels")) != 0) SetNumberOfLabels(node->AsInt()); if((node = searchNode->GetNode("specifyTextColor1")) != 0) SetSpecifyTextColor1(node->AsBool()); if((node = searchNode->GetNode("textColor1")) != 0) textColor1.SetFromNode(node); if((node = searchNode->GetNode("textHeight1")) != 0) SetTextHeight1(node->AsFloat()); if((node = searchNode->GetNode("specifyTextColor2")) != 0) SetSpecifyTextColor2(node->AsBool()); if((node = searchNode->GetNode("textColor2")) != 0) textColor2.SetFromNode(node); if((node = searchNode->GetNode("textHeight2")) != 0) SetTextHeight2(node->AsFloat()); if((node = searchNode->GetNode("horizontalJustification")) != 0) { // Allow enums to be int or string in the config file if(node->GetNodeType() == INT_NODE) { int ival = node->AsInt(); if(ival >= 0 && ival < 3) SetHorizontalJustification(LabelHorizontalAlignment(ival)); } else if(node->GetNodeType() == STRING_NODE) { LabelHorizontalAlignment value; if(LabelHorizontalAlignment_FromString(node->AsString(), value)) SetHorizontalJustification(value); } } if((node = searchNode->GetNode("verticalJustification")) != 0) { // Allow enums to be int or string in the config file if(node->GetNodeType() == INT_NODE) { int ival = node->AsInt(); if(ival >= 0 && ival < 3) SetVerticalJustification(LabelVerticalAlignment(ival)); } else if(node->GetNodeType() == STRING_NODE) { LabelVerticalAlignment value; if(LabelVerticalAlignment_FromString(node->AsString(), value)) SetVerticalJustification(value); } } if((node = searchNode->GetNode("depthTestMode")) != 0) { // Allow enums to be int or string in the config file if(node->GetNodeType() == INT_NODE) { int ival = node->AsInt(); if(ival >= 0 && ival < 3) SetDepthTestMode(DepthTestMode(ival)); } else if(node->GetNodeType() == STRING_NODE) { DepthTestMode value; if(DepthTestMode_FromString(node->AsString(), value)) SetDepthTestMode(value); } } if((node = searchNode->GetNode("formatTemplate")) != 0) SetFormatTemplate(node->AsString()); }
LabelAttributes::VariableType LabelAttributes::GetVarType() const { return VariableType(varType); }
void ShaderGenerator::generate (const ShaderParameters& shaderParams, Shader& shader, const vector<ShaderInput*>& outputs) { // Global scopes VariableScope& globalVariableScope = shader.getGlobalScope(); ValueScope globalValueScope; // Init state m_state.setShader(shaderParams, shader); DE_ASSERT(m_state.getExpressionFlags() == 0); // Reserve some scalars for gl_Position & dEQP_Position ReservedScalars reservedScalars; if (shader.getType() == Shader::TYPE_VERTEX) m_state.getVariableManager().reserve(reservedScalars, 4*2); // Push global scopes m_varManager.pushVariableScope(globalVariableScope); m_varManager.pushValueScope(globalValueScope); // Init shader outputs. { for (vector<ShaderInput*>::const_iterator i = outputs.begin(); i != outputs.end(); i++) { const ShaderInput* input = *i; Variable* variable = m_state.getVariableManager().allocate(input->getVariable()->getType(), Variable::STORAGE_SHADER_OUT, input->getVariable()->getName()); m_state.getVariableManager().setValue(variable, input->getValueRange()); } if (shader.getType() == Shader::TYPE_FRAGMENT) { // gl_FragColor // \todo [2011-11-22 pyry] Multiple outputs from fragment shader! Variable* fragColorVar = m_state.getVariableManager().allocate(VariableType(VariableType::TYPE_FLOAT, 4), Variable::STORAGE_SHADER_OUT, getFragColorName(m_state)); ValueRange valueRange(fragColorVar->getType()); valueRange.getMin() = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f); valueRange.getMax() = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f); fragColorVar->setLayoutLocation(0); // Bind color output to location 0 (applies to GLSL ES 3.0 onwards). m_state.getVariableManager().setValue(fragColorVar, valueRange.asAccess()); } } // Construct shader code. { Function& main = shader.getMain(); main.setReturnType(VariableType(VariableType::TYPE_VOID)); if (shaderParams.randomize) { FunctionGenerator funcGen(m_state, main); // Mandate assignment into to all shader outputs in main() const vector<Variable*>& liveVars = globalVariableScope.getLiveVariables(); for (vector<Variable*>::const_iterator i = liveVars.begin(); i != liveVars.end(); i++) { Variable* variable = *i; if (variable->getStorage() == Variable::STORAGE_SHADER_OUT) funcGen.requireAssignment(variable); } funcGen.generate(); } else { if (shader.getType() == Shader::TYPE_VERTEX) genVertexPassthrough(m_state, shader); else { DE_ASSERT(shader.getType() == Shader::TYPE_FRAGMENT); genFragmentPassthrough(m_state, shader); } } if (shader.getType() == Shader::TYPE_VERTEX) { // Add gl_Position = dEQP_Position; m_state.getVariableManager().release(reservedScalars); Variable* glPosVariable = m_state.getVariableManager().allocate(VariableType(VariableType::TYPE_FLOAT, 4), Variable::STORAGE_SHADER_OUT, "gl_Position"); Variable* qpPosVariable = m_state.getVariableManager().allocate(VariableType(VariableType::TYPE_FLOAT, 4), Variable::STORAGE_SHADER_IN, "dEQP_Position"); ValueRange valueRange(glPosVariable->getType()); valueRange.getMin() = tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f); valueRange.getMax() = tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f); m_state.getVariableManager().setValue(qpPosVariable, valueRange.asAccess()); // \todo [2011-05-24 pyry] No expression should be able to use gl_Position or dEQP_Position.. createAssignment(main.getBody(), glPosVariable, qpPosVariable); } } // Declare live global variables. { vector<Variable*> liveVariables; std::copy(globalVariableScope.getLiveVariables().begin(), globalVariableScope.getLiveVariables().end(), std::inserter(liveVariables, liveVariables.begin())); vector<Variable*> createDeclarationStatementVars; for (vector<Variable*>::iterator i = liveVariables.begin(); i != liveVariables.end(); i++) { Variable* variable = *i; const char* name = variable->getName(); bool declare = !deStringBeginsWith(name, "gl_"); // Do not declare built-in types. // Create input entries (store value range) if necessary vector<ShaderInput*>& inputs = shader.getInputs(); vector<ShaderInput*>& uniforms = shader.getUniforms(); switch (variable->getStorage()) { case Variable::STORAGE_SHADER_IN: { const ValueEntry* value = m_state.getVariableManager().getValue(variable); inputs.reserve(inputs.size()+1); inputs.push_back(new ShaderInput(variable, value->getValueRange())); break; } case Variable::STORAGE_UNIFORM: { const ValueEntry* value = m_state.getVariableManager().getValue(variable); uniforms.reserve(uniforms.size()+1); uniforms.push_back(new ShaderInput(variable, value->getValueRange())); break; } default: break; } if (declare) createDeclarationStatementVars.push_back(variable); else { // Just move to global scope without declaration statement. m_state.getVariableManager().declareVariable(variable); } } // All global initializers must be constant expressions, no variable allocation is allowed DE_ASSERT(m_state.getExpressionFlags() == 0); m_state.pushExpressionFlags(CONST_EXPR|NO_VAR_ALLOCATION); // Create declaration statements for (vector<Variable*>::iterator i = createDeclarationStatementVars.begin(); i != createDeclarationStatementVars.end(); i++) { shader.getGlobalStatements().reserve(shader.getGlobalStatements().size()); shader.getGlobalStatements().push_back(new DeclarationStatement(m_state, *i)); } m_state.popExpressionFlags(); } // Pop global scopes m_varManager.popVariableScope(); m_varManager.popValueScope(); // Fill undefined (unused) components in inputs with dummy values fillUndefinedShaderInputs(shader.getInputs()); fillUndefinedShaderInputs(shader.getUniforms()); // Tokenize shader and write source { TokenStream tokenStr; shader.tokenize(m_state, tokenStr); std::ostringstream str; PrettyPrinter printer(str); // Append #version if necessary. if (m_state.getProgramParameters().version == VERSION_300) str << "#version 300 es\n"; printer.append(tokenStr); shader.setSource(str.str().c_str()); } }
void BuiltIns::defineBuiltIns() { auto factory = SymbolFactory{ }; auto makeRef = [](auto&& type, bool is_const) { return VariableType(TypeFactory::getReference(type.get()), is_const); }; auto global_scope = std::make_shared<GlobalScope>(); auto int_ = factory.makeStruct("int", new StructScope("int", global_scope.get())); auto ref_int = makeRef(int_, false); auto const_ref_int = makeRef(int_, true); auto char_ = factory.makeStruct("char", new StructScope("char", global_scope.get())); auto ref_char = makeRef(char_, false); auto const_ref_char = makeRef(char_, true); auto str = factory.makeStruct("string", new StructScope("string", global_scope.get())); auto ref_str = makeRef(str, false); auto const_ref_str = makeRef(str, true); auto int_builtin = VariableType(new BuiltInTypeSymbol("~~int", Comp::config().int_size), false); auto char_builtin = VariableType(new BuiltInTypeSymbol("~~char", Comp::config().int_size), false); auto simple_traits = FunctionTraits::simple(); auto op_traits = FunctionTraits::methodOper(); auto meth_traits = FunctionTraits::method(); auto constr_traits = FunctionTraits::constructor(); auto tp = FunctionType(int_.get(), {ref_int, int_.get()}); auto void_type = std::make_unique<BuiltInTypeSymbol>("void", 0); global_scope -> define(factory.makeFunction("putchar", FunctionType(void_type.get(), {char_.get()}), simple_traits, false)); global_scope -> define(factory.makeFunction("getchar", FunctionType(int_.get(), { }), simple_traits, false)); auto string_builtin = VariableType(new BuiltInTypeSymbol("~~string", 256), false); str -> defineMember(factory.makeVariable("~~impl", string_builtin, VariableSymbolType::FIELD)); auto str_tp = FunctionType(ref_str, {ref_str, const_ref_str}); int_ -> defineMember(factory.makeVariable("~~impl", int_builtin, VariableSymbolType::FIELD)); int_ -> defineMethod(factory.makeFunction("int", FunctionType(ref_int, {ref_int}), constr_traits, false)); int_ -> defineMethod(factory.makeFunction("int", FunctionType(ref_int, {ref_int, const_ref_int}), constr_traits, false)); int_ -> defineMethod(factory.makeFunction("operator=", FunctionType(ref_int, {ref_int, const_ref_int}), op_traits, false)); int_ -> defineMethod(factory.makeFunction("operator+", tp, op_traits, false)); int_ -> defineMethod(factory.makeFunction("operator-", tp, op_traits, false)); int_ -> defineMethod(factory.makeFunction("operator*", tp, op_traits, false)); int_ -> defineMethod(factory.makeFunction("operator/", tp, op_traits, false)); int_ -> defineMethod(factory.makeFunction("operator%", tp, op_traits, false)); int_ -> defineMethod(factory.makeFunction("operator==", tp, op_traits, false)); int_ -> defineMethod(factory.makeFunction("operator!=", tp, op_traits, false)); int_ -> defineMethod(factory.makeFunction("operator&&", tp, op_traits, false)); int_ -> defineMethod(factory.makeFunction("operator||", tp, op_traits, false)); int_ -> defineMethod(factory.makeFunction("int", FunctionType(ref_int, {ref_int, char_.get()}), constr_traits, false)); char_ -> defineMember(factory.makeVariable("~~impl", char_builtin, VariableSymbolType::FIELD)); char_ -> defineMethod(factory.makeFunction("char", FunctionType(ref_char, {ref_char}), constr_traits, false)); char_ -> defineMethod(factory.makeFunction("char", FunctionType(ref_char, {ref_char, const_ref_char}), constr_traits, false)); char_ -> defineMethod(factory.makeFunction("char", FunctionType(ref_char, {ref_char, const_ref_int}), constr_traits, false)); char_ -> defineMethod(factory.makeFunction("operator=", FunctionType(ref_char, {ref_char, const_ref_char}), constr_traits, false)); str -> defineMethod(factory.makeFunction("string", str_tp, constr_traits, false)); str -> defineMethod(factory.makeFunction("length", FunctionType(int_.get(), {ref_str}), meth_traits, false)); str -> defineMethod(factory.makeFunction("operator[]", FunctionType(ref_char, {ref_str, int_.get()}), op_traits, false)); str -> defineMethod(factory.makeFunction("operator+", FunctionType(str.get(), {ref_str, const_ref_str}), op_traits, false)); str -> defineMethod(factory.makeFunction("operator=", str_tp, op_traits, false)); global_scope -> define(factory.makeFunction("print", FunctionType(void_type.get(), {const_ref_str}), simple_traits, false)); BuiltIns::int_type = int_.get(); BuiltIns::char_type = char_.get(); BuiltIns::ASCII_string_type = str.get(); BuiltIns::void_type = void_type.get(); global_scope -> define(std::move(void_type)); global_scope -> define(std::move(int_)); global_scope -> define(std::move(str)); global_scope -> define(std::move(char_)); BuiltIns::global_scope = global_scope; }
void CheckVisitor::visit(ReturnNode* node) { node -> expr() -> accept(*this); if ( node -> isInInlineCall() ) return; if ( function_scopes.empty() ) throw SemanticError("return is not in a function"); auto enclosing_function = function_scopes.top() -> func; node -> function(enclosing_function); auto unqualified_type = node -> expr() -> getType().unqualified(); if ( unqualified_type -> isObjectType() ) { auto obj_type = static_cast<const ObjectType*>(unqualified_type); auto ref_to_obj_type = TypeFactory::getReference(obj_type); // auto copy_constr = obj_type -> resolveMethod(obj_type -> typeName(), {VariableType(TypeFactory::getReference(obj_type), true)}); auto copy_constr = obj_type -> methodWith(obj_type -> typeName(), {ref_to_obj_type, VariableType(ref_to_obj_type, true)}); if ( copy_constr == nullptr ) throw SemanticError("Cannot initialize return value of type '" + enclosing_function -> type().returnType().getName() + "' with value of type '" + obj_type -> typeName() + "'"); checkCall(copy_constr, {valueOf(node -> expr())}); } }