diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc index f4ae4886dd..f9a3ccb900 100644 --- a/src/reader/spirv/function.cc +++ b/src/reader/spirv/function.cc @@ -426,6 +426,12 @@ class StructuredTraverser { std::unordered_set visited_; }; +/// @param src a source record +/// @returns true if |src| is a non-default Source +bool HasSource(const Source& src) { + return src.line != 0 || src.column != 0; +} + } // namespace BlockInfo::BlockInfo(const spvtools::opt::BasicBlock& bb) @@ -525,6 +531,14 @@ ast::Statement* FunctionEmitter::AddStatement( return result; } +ast::Statement* FunctionEmitter::AddStatementForInstruction( + std::unique_ptr statement, + const spvtools::opt::Instruction& inst) { + auto* node = AddStatement(std::move(statement)); + ApplySourceForInstruction(node, inst); + return node; +} + ast::Statement* FunctionEmitter::LastStatement() { assert(!statements_stack_.empty()); const auto& statement_list = statements_stack_.back().statements_; @@ -1655,7 +1669,7 @@ bool FunctionEmitter::EmitFunctionVariables() { // TODO(dneto): Add the initializer via Variable::set_constructor. auto var_decl_stmt = std::make_unique(std::move(var)); - AddStatement(std::move(var_decl_stmt)); + AddStatementForInstruction(std::move(var_decl_stmt), inst); // Save this as an already-named value. identifier_values_.insert(inst.result_id()); } @@ -2430,7 +2444,6 @@ bool FunctionEmitter::EmitStatementsInBasicBlock(const BlockInfo& block_info, // Only emit this part of the basic block once. return true; } - // Returns the given list of local definition IDs, sorted by their index. auto sorted_by_index = [this](const std::vector& ids) { auto sorted = ids; @@ -2514,8 +2527,8 @@ bool FunctionEmitter::EmitConstDefinition( } ast_const->set_constructor(std::move(ast_expr.expr)); ast_const->set_is_const(true); - AddStatement( - std::make_unique(std::move(ast_const))); + AddStatementForInstruction( + std::make_unique(std::move(ast_const)), inst); // Save this as an already-named value. identifier_values_.insert(inst.result_id()); return success(); @@ -2528,9 +2541,11 @@ bool FunctionEmitter::EmitConstDefOrWriteToHoistedVar( const auto* def_info = GetDefInfo(result_id); if (def_info && def_info->requires_hoisted_def) { // Emit an assignment of the expression to the hoisted variable. - AddStatement(std::make_unique( - std::make_unique(namer_.Name(result_id)), - std::move(ast_expr.expr))); + AddStatementForInstruction( + std::make_unique( + std::make_unique(namer_.Name(result_id)), + std::move(ast_expr.expr)), + inst); return true; } return EmitConstDefinition(inst, std::move(ast_expr)); @@ -2593,8 +2608,9 @@ bool FunctionEmitter::EmitStatement(const spvtools::opt::Instruction& inst) { // TODO(dneto): Order of evaluation? auto lhs = MakeExpression(ptr_id); auto rhs = MakeExpression(value_id); - AddStatement(std::make_unique( - std::move(lhs.expr), std::move(rhs.expr))); + AddStatementForInstruction(std::make_unique( + std::move(lhs.expr), std::move(rhs.expr)), + inst); return success(); } case SpvOpLoad: { @@ -3456,8 +3472,10 @@ bool FunctionEmitter::EmitFunctionCall(const spvtools::opt::Instruction& inst) { } if (result_type->IsVoid()) { - return nullptr != AddStatement(std::make_unique( - std::move(call_expr))); + return nullptr != + AddStatementForInstruction( + std::make_unique(std::move(call_expr)), + inst); } return EmitConstDefOrWriteToHoistedVar(inst, @@ -3491,6 +3509,18 @@ TypedExpression FunctionEmitter::MakeSimpleSelect( return {}; } +void FunctionEmitter::ApplySourceForInstruction( + ast::Node* node, + const spvtools::opt::Instruction& inst) { + if (!node) { + return; + } + const Source& existing = node->source(); + if (!HasSource(existing)) { + node->set_source(parser_impl_.GetSourceForInst(&inst)); + } +} + } // namespace spirv } // namespace reader } // namespace tint diff --git a/src/reader/spirv/function.h b/src/reader/spirv/function.h index 007c756e1e..b62994fe56 100644 --- a/src/reader/spirv/function.h +++ b/src/reader/spirv/function.h @@ -705,6 +705,23 @@ class FunctionEmitter { /// @returns a pointer to the statement. ast::Statement* AddStatement(std::unique_ptr statement); + /// Appends a new statement to the top of the statement stack, and attaches + /// source location information from the given instruction. Does nothing if + /// the statement is null. + /// @param statement the new statement + /// @returns a pointer to the statement. + ast::Statement* AddStatementForInstruction( + std::unique_ptr statement, + const spvtools::opt::Instruction& inst); + + /// Sets the source information for the given instruction to the given + /// node, if the node doesn't already have a source record. Does nothing + /// if |nodes| is null. + /// @param node the AST node + /// @param inst the SPIR-V instruction + void ApplySourceForInstruction(ast::Node* node, + const spvtools::opt::Instruction& inst); + /// @returns the last statetment in the top of the statement stack. ast::Statement* LastStatement(); diff --git a/src/reader/spirv/parser_impl.cc b/src/reader/spirv/parser_impl.cc index ee755f2957..70aed3bdd7 100644 --- a/src/reader/spirv/parser_impl.cc +++ b/src/reader/spirv/parser_impl.cc @@ -502,8 +502,12 @@ void ParserImpl::RegisterLineNumbers() { run_on_debug_insts); } -Source ParserImpl::GetSourceForResultIdForTest(uint32_t id) { - const auto* inst = def_use_mgr_->GetDef(id); +Source ParserImpl::GetSourceForResultIdForTest(uint32_t id) const { + return GetSourceForInst(def_use_mgr_->GetDef(id)); +} + +Source ParserImpl::GetSourceForInst( + const spvtools::opt::Instruction* inst) const { auto where = inst_source_.find(inst); if (where == inst_source_.end()) { return {}; diff --git a/src/reader/spirv/parser_impl.h b/src/reader/spirv/parser_impl.h index 28c3523ab8..deeed0ad98 100644 --- a/src/reader/spirv/parser_impl.h +++ b/src/reader/spirv/parser_impl.h @@ -362,11 +362,15 @@ class ParserImpl : Reader { return builtin_position_; } - /// Look up the source record for the SPIR-V instruction with the given + /// Returns the source record for the SPIR-V instruction with the given /// result ID. /// @param id the SPIR-V result id. /// @return the Source record, or a default one - Source GetSourceForResultIdForTest(uint32_t id); + Source GetSourceForResultIdForTest(uint32_t id) const; + /// Returns the soruce record for the given instruction. + /// @param inst the SPIR-V instruction + /// @return the Source record, or a default one + Source GetSourceForInst(const spvtools::opt::Instruction* inst) const; private: /// Converts a specific SPIR-V type to a Tint type. Integer case