1 /*
2 * Copyright (c) 2023-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "debug_data_builder.h"
17
18 #include <llvm/IR/Module.h>
19 #include <llvm/IR/Function.h>
20 #include <llvm/IR/DIBuilder.h>
21
22 namespace ark::llvmbackend {
23
24 using llvm::DIBuilder;
25 using llvm::DICompileUnit;
26 using llvm::DILocation;
27 using llvm::DISubprogram;
28 using llvm::Function;
29 using llvm::Instruction;
30
DebugDataBuilder(llvm::Module * module,const std::string & filename)31 DebugDataBuilder::DebugDataBuilder(llvm::Module *module, const std::string &filename) : builder_(new DIBuilder(*module))
32 {
33 auto file = builder_->createFile(filename, "/");
34 builder_->createCompileUnit(llvm::dwarf::DW_LANG_C_plus_plus_14, file, "ark-llvm-backend", true, "", 0, "",
35 DICompileUnit::DebugEmissionKind::NoDebug, 0, true, false,
36 DICompileUnit::DebugNameTableKind::None);
37 }
38
BeginSubprogram(Function * function,const std::string & filename,uint32_t line)39 void DebugDataBuilder::BeginSubprogram(Function *function, const std::string &filename, uint32_t line)
40 {
41 ASSERT(builder_ != nullptr);
42 auto file = builder_->createFile(filename, "/");
43 auto flags = DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized;
44 auto type = builder_->createSubroutineType(builder_->getOrCreateTypeArray(llvm::None));
45 auto sp = builder_->createFunction(file, function->getName(), function->getName(), file, line, type, line,
46 llvm::DINode::FlagZero, flags);
47 function->setSubprogram(sp);
48 }
49
EndSubprogram(Function * function)50 void DebugDataBuilder::EndSubprogram(Function *function)
51 {
52 ASSERT(builder_ != nullptr);
53 builder_->finalizeSubprogram(function->getSubprogram());
54 }
55
SetLocation(Instruction * inst,uint32_t line,uint32_t column)56 void DebugDataBuilder::SetLocation(Instruction *inst, uint32_t line, uint32_t column)
57 {
58 auto func = inst->getFunction();
59 inst->setDebugLoc(DILocation::get(func->getContext(), line, column, func->getSubprogram()));
60 }
61
AppendInlinedAt(llvm::Instruction * inst,llvm::Function * function,uint32_t line,uint32_t column)62 void DebugDataBuilder::AppendInlinedAt(llvm::Instruction *inst, llvm::Function *function, uint32_t line,
63 uint32_t column)
64 {
65 auto original = inst->getDebugLoc();
66
67 auto inlinedAtNode = DILocation::getDistinct(function->getContext(), line, column, original.getScope());
68 llvm::DenseMap<const llvm::MDNode *, llvm::MDNode *> cache;
69 auto inlinedAt = llvm::DebugLoc::appendInlinedAt(original, inlinedAtNode, function->getContext(), cache);
70 auto newDebugInfo = DILocation::getDistinct(function->getContext(), original.getLine(), original->getColumn(),
71 original.getScope(), inlinedAt);
72 inst->setDebugLoc(newDebugInfo);
73 }
74
Finalize()75 void DebugDataBuilder::Finalize()
76 {
77 builder_->finalize();
78 delete builder_;
79 builder_ = nullptr;
80 }
81
~DebugDataBuilder()82 DebugDataBuilder::~DebugDataBuilder()
83 {
84 delete builder_;
85 }
86
87 } // namespace ark::llvmbackend
88