Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
T
tic
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wenyuanbo
tic
Commits
d82db909
Commit
d82db909
authored
Jul 18, 2019
by
Andrew Tulloch
Committed by
Tianqi Chen
Jul 18, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Emit DWARF debug information (#3420)
parent
e686da79
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
206 additions
and
9 deletions
+206
-9
src/codegen/llvm/codegen_cpu.cc
+84
-2
src/codegen/llvm/codegen_cpu.h
+9
-2
src/codegen/llvm/codegen_llvm.cc
+17
-0
src/codegen/llvm/codegen_llvm.h
+11
-0
src/codegen/llvm/llvm_common.h
+3
-2
src/codegen/llvm/llvm_module.cc
+9
-3
tests/python/unittest/test_codegen_llvm.py
+73
-0
No files found.
src/codegen/llvm/codegen_cpu.cc
View file @
d82db909
...
...
@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
...
...
@@ -128,6 +128,88 @@ void CodeGenCPU::AddFunction(const LoweredFunc& f) {
export_system_symbols_
.
emplace_back
(
std
::
make_pair
(
f
->
name
,
builder_
->
CreatePointerCast
(
function_
,
t_void_p_
)));
}
AddDebugInformation
(
function_
);
}
// Following Glow |DebugInfo::generateFunctionDebugInfo|, https://git.io/fjadv
void
CodeGenCPU
::
AddDebugInformation
(
llvm
::
Function
*
function
)
{
#if TVM_LLVM_VERSION >= 50
CHECK
(
!
function
->
getSubprogram
());
llvm
::
SmallVector
<
llvm
::
Metadata
*
,
4
>
paramTys
;
llvm
::
DIType
*
returnTy
=
getDebugType
(
builder_
.
get
(),
dbg_info_
->
di_builder_
.
get
(),
function
->
getReturnType
());
paramTys
.
push_back
(
returnTy
);
for
(
size_t
i
=
0
;
i
<
function
->
arg_size
();
++
i
)
{
paramTys
.
push_back
(
getDebugType
(
builder_
.
get
(),
dbg_info_
->
di_builder_
.
get
(),
function
->
getFunctionType
()
->
getParamType
(
i
)));
}
auto
*
DIFunctionTy
=
dbg_info_
->
di_builder_
->
createSubroutineType
(
dbg_info_
->
di_builder_
->
getOrCreateTypeArray
(
paramTys
));
auto
*
DIFunction
=
dbg_info_
->
di_builder_
->
createFunction
(
dbg_info_
->
file_
,
function
->
getName
(),
""
,
dbg_info_
->
file_
,
0
/* line number */
,
DIFunctionTy
,
false
/* internal linkage */
,
true
/* definition */
,
0
/* line number */
,
llvm
::
DINode
::
FlagPrototyped
,
true
/* isOptimized */
);
CHECK
(
DIFunction
);
function
->
setSubprogram
(
DIFunction
);
CHECK_EQ
(
function
->
getSubprogram
(),
DIFunction
);
IRBuilder
builder
(
&
function
->
getEntryBlock
());
if
(
!
function
->
getEntryBlock
().
empty
())
{
builder
.
SetInsertPoint
(
&
function
->
getEntryBlock
().
front
());
}
llvm
::
DebugLoc
DL
;
builder
.
SetCurrentDebugLocation
(
DL
);
for
(
size_t
i
=
0
;
i
<
function
->
arg_size
();
++
i
)
{
auto
*
paramAlloca
=
builder
.
CreateAlloca
(
function
->
getFunctionType
()
->
getParamType
(
i
));
std
::
string
paramName
=
"arg"
+
std
::
to_string
(
i
+
1
);
auto
param
=
dbg_info_
->
di_builder_
->
createParameterVariable
(
DIFunction
,
paramName
,
i
+
1
,
dbg_info_
->
file_
,
0
,
getDebugType
(
builder_
.
get
(),
dbg_info_
->
di_builder_
.
get
(),
function
->
getFunctionType
()
->
getParamType
(
i
)),
/* alwaysPreserve */
true
);
auto
*
store
=
builder
.
CreateStore
(
function
->
arg_begin
()
+
i
,
paramAlloca
);
dbg_info_
->
di_builder_
->
insertDeclare
(
paramAlloca
,
param
,
dbg_info_
->
di_builder_
->
createExpression
(),
llvm
::
DebugLoc
::
get
(
0
,
0
,
DIFunction
),
store
);
}
dbg_info_
->
di_builder_
->
finalizeSubprogram
(
function
->
getSubprogram
());
auto
*
scope
=
function
->
getSubprogram
();
if
(
!
scope
)
{
return
;
}
for
(
auto
&
BB
:
*
function
)
{
for
(
auto
&
I
:
BB
)
{
if
(
I
.
getDebugLoc
())
{
continue
;
}
I
.
setDebugLoc
(
llvm
::
DebugLoc
::
get
(
0
,
0
,
scope
));
}
}
#endif
}
llvm
::
DIType
*
CodeGenCPU
::
getDebugType
(
IRBuilder
*
builder
,
llvm
::
DIBuilder
*
di_builder
,
llvm
::
Type
*
ty
)
{
if
(
ty
==
builder
->
getVoidTy
())
{
return
nullptr
;
}
else
if
(
ty
==
builder
->
getFloatTy
())
{
return
di_builder
->
createBasicType
(
"float"
,
32
,
llvm
::
dwarf
::
DW_ATE_float
);
}
else
if
(
ty
==
builder
->
getInt8Ty
())
{
return
di_builder
->
createBasicType
(
"int8"
,
8
,
llvm
::
dwarf
::
DW_ATE_signed
);
}
else
if
(
ty
==
builder
->
getInt32Ty
())
{
return
di_builder
->
createBasicType
(
"int32"
,
32
,
llvm
::
dwarf
::
DW_ATE_signed
);
}
else
if
(
ty
->
isPointerTy
())
{
return
di_builder
->
createPointerType
(
getDebugType
(
builder
,
di_builder
,
ty
->
getPointerElementType
()),
ty
->
getPrimitiveSizeInBits
());
}
else
{
std
::
string
type_str
;
llvm
::
raw_string_ostream
rso
(
type_str
);
ty
->
print
(
rso
);
LOG
(
FATAL
)
<<
"Unknown LLVM type:"
<<
rso
.
str
();
}
return
nullptr
;
}
void
CodeGenCPU
::
AddMainFunction
(
const
std
::
string
&
entry_func_name
)
{
...
...
src/codegen/llvm/codegen_cpu.h
View file @
d82db909
...
...
@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
...
...
@@ -139,6 +139,13 @@ class CodeGenCPU : public CodeGenLLVM {
std
::
unordered_map
<
std
::
string
,
llvm
::
GlobalVariable
*>
func_handle_map_
;
// List of symbols to be exported to TVM system lib.
std
::
vector
<
std
::
pair
<
std
::
string
,
llvm
::
Value
*>
>
export_system_symbols_
;
// Get the DWARF type corresponding to the LLVM type |ty|. The current API in practice only
// generates |int32|, and |int8*|.
static
llvm
::
DIType
*
getDebugType
(
IRBuilder
*
builder
,
llvm
::
DIBuilder
*
di_builder
,
llvm
::
Type
*
ty
);
// Adds the DWARF debug information for |function| to |dbg_info_|.
void
AddDebugInformation
(
llvm
::
Function
*
function
);
};
}
// namespace codegen
...
...
src/codegen/llvm/codegen_llvm.cc
View file @
d82db909
...
...
@@ -73,6 +73,7 @@ void CodeGenLLVM::Init(const std::string& module_name,
md_tbaa_root_
=
md_builder_
->
createTBAARoot
(
"tvm-tbaa"
);
md_tbaa_alias_set_
=
md_builder_
->
createTBAANode
(
"tvm-alias"
,
md_tbaa_root_
);
this
->
InitTarget
(
tm
);
dbg_info_
=
CreateDebugInfo
(
module_
.
get
());
}
void
CodeGenLLVM
::
InitTarget
(
llvm
::
TargetMachine
*
tm
)
{
...
...
@@ -109,6 +110,7 @@ void CodeGenLLVM::InitFuncState() {
analyzer_
.
reset
(
new
arith
::
Analyzer
());
}
void
CodeGenLLVM
::
AddFunctionInternal
(
const
LoweredFunc
&
f
,
bool
ret_void
)
{
this
->
InitFuncState
();
std
::
vector
<
llvm
::
Type
*>
arg_types
;
...
...
@@ -166,9 +168,11 @@ void CodeGenLLVM::AddFunctionInternal(const LoweredFunc& f, bool ret_void) {
}
}
std
::
unique_ptr
<
llvm
::
Module
>
CodeGenLLVM
::
Finish
()
{
this
->
AddStartupFunction
();
// link modules
dbg_info_
->
di_builder_
->
finalize
();
for
(
size_t
i
=
0
;
i
<
link_modules_
.
size
();
++
i
)
{
CHECK
(
!
llvm
::
Linker
::
linkModules
(
*
module_
,
std
::
move
(
link_modules_
[
i
])))
<<
"Failed to link modules"
;
...
...
@@ -419,6 +423,19 @@ void CodeGenLLVM::GetAlignment(Type t,
*
p_alignment
=
align_bits
/
8
;
}
std
::
unique_ptr
<
CodeGenLLVM
::
DebugInfo
>
CodeGenLLVM
::
CreateDebugInfo
(
llvm
::
Module
*
module
)
{
auto
debug_info
=
llvm
::
make_unique
<
CodeGenLLVM
::
DebugInfo
>
();
debug_info
->
di_builder_
=
llvm
::
make_unique
<
llvm
::
DIBuilder
>
(
*
module
);
// TODO(tulloch): pass this information through relay::Span classes to the LoweredFunc instance?
debug_info
->
file_
=
debug_info
->
di_builder_
->
createFile
(
"model.tvm"
,
"/tmp/"
);
debug_info
->
compilation_unit_
=
debug_info
->
di_builder_
->
createCompileUnit
(
llvm
::
dwarf
::
DW_LANG_C
,
debug_info
->
file_
,
"TVM"
,
0
,
""
,
0
,
""
,
llvm
::
DICompileUnit
::
DebugEmissionKind
::
FullDebug
,
/* SplitDebugInlining */
true
,
/* DebugInfoForProfiling */
true
);
return
debug_info
;
}
llvm
::
Value
*
CodeGenLLVM
::
CreateBroadcast
(
llvm
::
Value
*
value
,
int
lanes
)
{
llvm
::
Constant
*
undef
=
llvm
::
UndefValue
::
get
(
llvm
::
VectorType
::
get
(
value
->
getType
(),
lanes
));
...
...
src/codegen/llvm/codegen_llvm.h
View file @
d82db909
...
...
@@ -293,6 +293,17 @@ class CodeGenLLVM :
std
::
unordered_set
<
const
Variable
*>
alias_var_set_
;
// set of volatile buffer.
std
::
unordered_set
<
const
Variable
*>
volatile_buf_
;
struct
DebugInfo
{
std
::
unique_ptr
<
llvm
::
DIBuilder
>
di_builder_
;
llvm
::
DICompileUnit
*
compilation_unit_
{
nullptr
};
llvm
::
DIFile
*
file_
{
nullptr
};
};
std
::
unique_ptr
<
DebugInfo
>
dbg_info_
;
// Create a new DebugInfo struct from the given Module that initializes the |file_| and
// |compilation_unit_| to TVM defaults.
static
std
::
unique_ptr
<
DebugInfo
>
CreateDebugInfo
(
llvm
::
Module
*
module
);
};
}
// namespace codegen
}
// namespace tvm
...
...
src/codegen/llvm/llvm_common.h
View file @
d82db909
...
...
@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
...
...
@@ -38,6 +38,7 @@
#include <llvm/IR/BasicBlock.h>
#include <llvm/IR/Constants.h>
#include <llvm/IR/DerivedTypes.h>
#include <llvm/IR/DIBuilder.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/Instructions.h>
...
...
src/codegen/llvm/llvm_module.cc
View file @
d82db909
...
...
@@ -187,14 +187,20 @@ class LLVMModuleNode final : public runtime::ModuleNode {
}
cg
->
AddMainFunction
(
funcs
[
0
]
->
name
);
module_
=
cg
->
Finish
();
module_
->
addModuleFlag
(
llvm
::
Module
::
Warning
,
"tvm_target"
,
llvm
::
MDString
::
get
(
*
ctx_
,
target
));
module_
->
addModuleFlag
(
llvm
::
Module
::
Override
,
"Debug Info Version"
,
llvm
::
DEBUG_METADATA_VERSION
);
if
(
tm_
->
getTargetTriple
().
isOSDarwin
())
{
module_
->
addModuleFlag
(
llvm
::
Module
::
Override
,
"Dwarf Version"
,
2
);
}
std
::
string
verify_errors_storage
;
llvm
::
raw_string_ostream
verify_errors
(
verify_errors_storage
);
LOG_IF
(
FATAL
,
llvm
::
verifyModule
(
*
module_
,
&
verify_errors
))
<<
"LLVM module verification failed with the following errors:
\n
"
<<
verify_errors
.
str
();
module_
->
addModuleFlag
(
llvm
::
Module
::
Warning
,
"tvm_target"
,
llvm
::
MDString
::
get
(
*
ctx_
,
target
));
target_
=
target
;
mptr_
=
module_
.
get
();
}
...
...
tests/python/unittest/test_codegen_llvm.py
View file @
d82db909
...
...
@@ -471,6 +471,78 @@ def test_llvm_fp_math():
check_llvm_sigmoid
(
8
)
check_llvm_sigmoid
(
16
)
def
test_dwarf_debug_information
():
nn
=
1024
n
=
tvm
.
convert
(
nn
)
A
=
tvm
.
placeholder
((
n
,),
name
=
'A'
)
B
=
tvm
.
placeholder
((
n
,),
name
=
'B'
)
C
=
tvm
.
compute
(
A
.
shape
,
lambda
*
i
:
A
(
*
i
)
+
B
(
*
i
),
name
=
'C'
)
s
=
tvm
.
create_schedule
(
C
.
op
)
xo
,
xi
=
s
[
C
]
.
split
(
C
.
op
.
axis
[
0
],
factor
=
4
)
s
[
C
]
.
parallel
(
xo
)
s
[
C
]
.
vectorize
(
xi
)
def
check_llvm_object
():
if
not
tvm
.
module
.
enabled
(
"llvm"
):
return
if
tvm
.
codegen
.
llvm_version_major
()
<
5
:
return
# build two functions
f2
=
tvm
.
lower
(
s
,
[
A
,
B
,
C
],
name
=
"fadd1"
)
f1
=
tvm
.
lower
(
s
,
[
A
,
B
,
C
],
name
=
"fadd2"
)
m
=
tvm
.
build
([
f1
,
f2
],
"llvm"
)
temp
=
util
.
tempdir
()
o_path
=
temp
.
relpath
(
"temp.o"
)
m
.
save
(
o_path
)
import
re
import
shutil
import
subprocess
import
sys
# Try the dwarfdump utility (OS X)
if
shutil
.
which
(
"dwarfdump"
):
output
=
subprocess
.
check_output
([
"dwarfdump"
,
o_path
])
assert
re
.
search
(
r"""DW_AT_name\\t\("fadd1"\)"""
,
str
(
output
))
assert
re
.
search
(
r"""DW_AT_name\\t\("fadd2"\)"""
,
str
(
output
))
# Try gobjdump (OS X)
if
shutil
.
which
(
"gobjdump"
):
output
=
subprocess
.
check_output
([
"gobjdump"
,
"--dwarf"
,
o_path
])
assert
re
.
search
(
r"""DW_AT_name.*fadd1"""
,
str
(
output
))
assert
re
.
search
(
r"""DW_AT_name.*fadd2"""
,
str
(
output
))
# Try objdump (Linux) - Darwin objdump has different DWARF syntax.
if
shutil
.
which
(
"objdump"
)
and
sys
.
platform
!=
'darwin'
:
output
=
subprocess
.
check_output
([
"objdump"
,
"--dwarf"
,
o_path
])
assert
re
.
search
(
r"""DW_AT_name.*fadd1"""
,
str
(
output
))
assert
re
.
search
(
r"""DW_AT_name.*fadd2"""
,
str
(
output
))
def
check_llvm_ir
():
if
not
tvm
.
module
.
enabled
(
"llvm"
):
return
if
tvm
.
codegen
.
llvm_version_major
()
<
5
:
return
# build two functions
f2
=
tvm
.
lower
(
s
,
[
A
,
B
,
C
],
name
=
"fadd1"
)
f1
=
tvm
.
lower
(
s
,
[
A
,
B
,
C
],
name
=
"fadd2"
)
m
=
tvm
.
build
([
f1
,
f2
],
target
=
"llvm -target=aarch64-linux-gnu"
)
ll
=
m
.
get_source
(
"ll"
)
# On non-Darwin OS, don't explicitly specify DWARF version.
import
re
assert
not
re
.
search
(
r""""Dwarf Version"""""
,
ll
)
assert
re
.
search
(
r"""llvm.dbg.value"""
,
ll
)
# Try Darwin, require DWARF-2
m
=
tvm
.
build
([
f1
,
f2
],
target
=
"llvm -target=x86_64-apple-darwin-macho"
)
ll
=
m
.
get_source
(
"ll"
)
assert
re
.
search
(
r"""i32 4, !"Dwarf Version", i32 2"""
,
ll
)
assert
re
.
search
(
r"""llvm.dbg.value"""
,
ll
)
check_llvm_object
()
check_llvm_ir
()
if
__name__
==
"__main__"
:
test_llvm_import
()
test_alignment
()
...
...
@@ -489,3 +561,4 @@ if __name__ == "__main__":
test_llvm_lookup_intrin
()
test_llvm_div
()
test_llvm_fp_math
()
test_dwarf_debug_information
()
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment