今回はGCCとLLVMを読んでいきます
#
環境構築
mercurialのoriginalのソースコードをそれぞれ最新版にする
#
コンパイラのバージョンアップ方法
- とりあえず古いリポジトリにあるファイルを
rm -rf
する
-
最新版を持ってくる
-
hg add *
する
-
hg statusを書き出す
-
egrepで egrep '^!' /tmp/hg_status.log
とかして、消えたファイルを確認する
-
!がついてたファイルを削除する
- hg commit してpushする
#
gccの最新版
なんかGitになったらしい
1
|
$ git clone git://gcc.gnu.org/git/gcc.git
|
#
llvmの最新版
これはGitHubになったみたい
1
|
$ git clone https://github.com/llvm/llvm-project
|
#
gccのビルド
あたたかみのあるConfigure
1
2
3
|
$ ~/src/CbC_gcc/configure CFLAGS="-g3 -O0" --prefix=$PWD \
--disable-nls --disable-bootstrap --enable-languages=c \
--enable-checking=tree,rtl,assert,types
|
#
llvmのビルド
cmake+ninjaを使う
- libstd関連でエラーが出るのでrpathを指定しておく
1
|
$cmake3 -G Ninja -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:PATH=/usr/local/llvm -DLLVM_ENABLE_PROJECTS="clang;libgcc;libcxx;libcxxabi" -DCMAKE_CXX_LINK_FLAGS="-Wl,-rpath,/usr/local/gcc9/lib64 -L/usr/local/gcc9/lib64" ~/src/LLVM_original/llvm
|
#
LLVMのデバッグをするとき
起動する
1
|
lldb -- "/mnt/dalmore-home/one/build/build_llvm_origin/bin/clang-11" -cc1 -triple x86_64-unknown-linux-gnu -S -disable-free -main-file-name hello.c -mrelocation-model static -mthread-model posix -mframe-pointer=all -fmath-errno -fdenormal-fp-math=ieee,ieee -fdenormal-fp-math-f32=ieee,ieee -ffp-contract=on -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -v -resource-dir /mnt/dalmore-home/one/build/build_llvm_origin/lib/clang/11.0.0 -internal-isystem /usr/local/include -internal-isystem /mnt/dalmore-home/one/build/build_llvm_origin/lib/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir /mnt/dalmore-home/one/build/build_llvm_origin -ferror-limit 19 -fmessage-length 0 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -fcolor-diagnostics -faddrsig -o hello.s -x c /mnt/dalmore-home//one/src/test/hello.c
|
なんかlldbだとおもすぎて駄目なのでgdbにした
例えばこういうコードををデバッグしたい時
//clang/lib/Parse/ParseStmt.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
/// Parse an expression statement.
StmtResult Parser::ParseExprStatement(ParsedStmtContext StmtCtx) {
// If a case keyword is missing, this is where it should be inserted.
Token OldToken = Tok;
ExprStatementTokLoc = Tok.getLocation();
// expression[opt] ';'
ExprResult Expr(ParseExpression());
if (Expr.isInvalid()) {
// If the expression is invalid, skip ahead to the next semicolon or '}'.
// Not doing this opens us up to the possibility of infinite loops if
// ParseExpression does not consume any tokens.
SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
if (Tok.is(tok::semi))
ConsumeToken();
return Actions.ActOnExprStmtError();
|
何故か Parser::ParseExpr...
ではbreak pointに設定出来ない。
このParser::ParseExprStatement
をbreakpointにしたい場合はclang::Parser::ParseExprStatement
をbreak pointにする
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
#0 clang::Parser::ParseExprStatement (this=0xe696330, StmtCtx=clang::Parser::Compound)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Parse/ParseStmt.cpp:428
#1 0x0000000005a39e80 in clang::Parser::ParseStatementOrDeclarationAfterAttributes (this=0xe696330, Stmts=..., StmtCtx=clang::Parser::Compound,
TrailingElseLoc=0x0, Attrs=...) at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Parse/ParseStmt.cpp:233
#2 0x0000000005a3965c in clang::Parser::ParseStatementOrDeclaration (this=0xe696330, Stmts=..., StmtCtx=clang::Parser::Compound, TrailingElseLoc=0x0)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Parse/ParseStmt.cpp:107
#3 0x0000000005a3cec9 in clang::Parser::ParseCompoundStatementBody (this=0xe696330, isStmtExpr=false)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Parse/ParseStmt.cpp:1079
#4 0x0000000005a411fb in clang::Parser::ParseFunctionStatementBody (this=0xe696330, Decl=0xe6bda30, BodyScope=...)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Parse/ParseStmt.cpp:2204
#5 0x0000000005977d9f in clang::Parser::ParseFunctionDefinition (this=0xe696330, D=..., TemplateInfo=..., LateParsedAttrs=0x7fffffff9a80)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Parse/Parser.cpp:1349
#6 0x00000000059941d8 in clang::Parser::ParseDeclGroup (this=0xe696330, DS=..., Context=clang::FileContext, DeclEnd=0x0, FRI=0x0)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Parse/ParseDecl.cpp:2068
#7 0x0000000005976df4 in clang::Parser::ParseDeclOrFunctionDefInternal (this=0xe696330, attrs=..., DS=..., AS=clang::AS_none)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Parse/Parser.cpp:1109
#8 0x0000000005976eae in clang::Parser::ParseDeclarationOrFunctionDefinition (this=0xe696330, attrs=..., DS=0x0, AS=clang::AS_none)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Parse/Parser.cpp:1125
#9 0x0000000005976391 in clang::Parser::ParseExternalDeclaration (this=0xe696330, attrs=..., DS=0x0)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Parse/Parser.cpp:945
#10 0x0000000005975419 in clang::Parser::ParseTopLevelDecl (this=0xe696330, Result=..., IsFirstDecl=false)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Parse/Parser.cpp:696
#11 0x0000000005970f3a in clang::ParseAST (S=..., PrintStats=false, SkipFunctionBodies=false)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Parse/ParseAST.cpp:158
#12 0x0000000003ce5a91 in clang::ASTFrontendAction::ExecuteAction (this=0xe63c1a0)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Frontend/FrontendAction.cpp:1047
#13 0x0000000004572303 in clang::CodeGenAction::ExecuteAction (this=0xe63c1a0)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CodeGenAction.cpp:1176
#14 0x0000000003ce53fd in clang::FrontendAction::Execute (this=0xe63c1a0)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Frontend/FrontendAction.cpp:940
#15 0x0000000003c7db31 in clang::CompilerInstance::ExecuteAction (this=0xe6381d0, Act=...)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Frontend/CompilerInstance.cpp:969
#16 0x0000000003e40b1d in clang::ExecuteCompilerInvocation (Clang=0xe6381d0)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:292
|
#
GCC
c_parser_expr_no_commas
で止めてみる
- この関数自体は再帰下降でパースが実行されている最中に呼び出される
- テストコードがexternから始まっていたので、
c_parser_external_declaration
から呼び出されているみたい
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
(gdb) bt
#0 c_parser_expr_no_commas (parser=parser@entry=0x7ffff7ff8ab0,
after=after@entry=0x0, omp_atomic_lhs=omp_atomic_lhs@entry=0x0)
at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:7557
#1 0x000000000083fc05 in c_parser_expression (
parser=parser@entry=0x7ffff7ff8ab0)
at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:10630
#2 0x000000000084046c in c_parser_expression_conv (
parser=parser@entry=0x7ffff7ff8ab0)
at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:10663
#3 0x000000000085b72a in c_parser_statement_after_labels (
parser=parser@entry=0x7ffff7ff8ab0, if_p=if_p@entry=0x0,
chain=chain@entry=0x0)
at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:6294
#4 0x0000000000856d04 in c_parser_compound_statement_nostart (
parser=parser@entry=0x7ffff7ff8ab0)
at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:5800
#5 0x00000000008572d7 in c_parser_compound_statement (
parser=parser@entry=0x7ffff7ff8ab0)
at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:5616
#6 0x0000000000858c56 in c_parser_declaration_or_fndef (
parser=parser@entry=0x7ffff7ff8ab0, fndef_ok=fndef_ok@entry=true,
static_assert_ok=static_assert_ok@entry=true,
empty_ok=empty_ok@entry=true, nested=nested@entry=false,
start_attr_ok=start_attr_ok@entry=true,
objc_foreach_object_declaration=objc_foreach_object_declaration@entry=0x0, omp_declare_simd_clauses=..., omp_declare_simd_clauses@entry=...,
have_attrs=<optimized out>, have_attrs@entry=false,
attrs=attrs@entry=0x0, oacc_routine_data=oacc_routine_data@entry=0x0,
fallthru_attr_p=fallthru_attr_p@entry=0x0)
at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:2504
#7 0x0000000000861c81 in c_parser_external_declaration (
parser=0x7ffff7ff8ab0)
at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:1747
#8 0x0000000000862872 in c_parser_translation_unit (
parser=0x7ffff7ff8ab0)
at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:1619
#9 c_parse_file ()
---Type <return> to continue, or q <return> to quit---
at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:21710
#10 0x00000000008c708b in c_common_parse_file ()
at /mnt/dalmore-home//one/src/GCC_original/gcc/c-family/c-opts.c:1186
#11 0x0000000000ebad8f in compile_file ()
at /mnt/dalmore-home//one/src/GCC_original/gcc/toplev.c:458
#12 0x0000000000742efd in do_compile ()
at /mnt/dalmore-home//one/src/GCC_original/gcc/toplev.c:2273
#13 toplev::main (this=this@entry=0x7fffffffde70, argc=argc@entry=2,
argv=argv@entry=0x7fffffffdf78)
at /mnt/dalmore-home//one/src/GCC_original/gcc/toplev.c:2412
#14 0x00000000007c1527 in main (argc=2, argv=0x7fffffffdf78)
at /mnt/dalmore-home//one/src/GCC_original/gcc/main.c:39
|
#
2020/02/14 (2日目)
午前中はgccから
#
テストコード
1
2
3
4
5
6
7
8
9
10
11
12
13
|
extern int printf(const char*, ...);
extern void g(int* p);
int f(int arg) {
int loq;
g(&loq);
}
int main() {
f(3);
return 0;
}
|
#
gcc
build したディレクトリに移動
#
gdb起動
1
|
$ gdb --args gcc/cc1 ~/src/test/hello.c
|
#
break point
昨日と同じところから
1
|
#0 c_parser_expr_no_commas (parser=parser@entry=0x7ffff7ff8ab0,
|
- ソースコード的には
gcc/c/c-parser.c
を読んでいく世界観
#
C言語のおさらい
C言語でstaticがついている関数は自分自身のファイルだけからしか参照できない関数
c_parser
がGCCのパース関連の色々入っている構造体っぽい
#
parser 構造体
- なんかtokensのアドレスとか、tokenのbufとかが入っている
- この時点でソースコードのlocationが知りたい
https://gcc.gnu.org/onlinedocs/gccint/Guidelines-for-Diagnostics.html#Location-Information
#
c_parser_conditional_expression
#
c_parser_binary_expression
- 引数は
parser
, after
, omp_atomic_lhs
- 今は
extern void g();
のg()
を見てそう
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
static struct c_expr
c_parser_binary_expression (c_parser *parser, struct c_expr *after,
tree omp_atomic_lhs)
{
/* A binary expression is parsed using operator-precedence parsing,
with the operands being cast expressions. All the binary
operators are left-associative. Thus a binary expression is of
form:
E0 op1 E1 op2 E2 ...
which we represent on a stack. On the stack, the precedence
levels are strictly increasing. When a new operator is
encountered of higher precedence than that at the top of the
stack, it is pushed; its LHS is the top expression, and its RHS
is everything parsed until it is popped. When a new operator is
encountered with precedence less than or equal to that at the top
of the stack, triples E[i-1] op[i] E[i] are popped and replaced
by the result of the operation until the operator at the top of
the stack has lower precedence than the new operator or there is
only one element on the stack; then the top expression is the LHS
of the new operator. In the case of logical AND and OR
expressions, we also need to adjust c_inhibit_evaluation_warnings
as appropriate when the operators are pushed and popped. */
struct {
/* The expression at this stack level. */
struct c_expr expr;
/* The precedence of the operator on its left, PREC_NONE at the
bottom of the stack. */
enum c_parser_prec prec;
/* The operation on its left. */
enum tree_code op;
/* The source location of this operation. */
location_t loc;
/* The sizeof argument if expr.original_code == SIZEOF_EXPR. */
tree sizeof_arg;
} stack[NUM_PRECS];
int sp;
/* Location of the binary operator. */
location_t binary_loc = UNKNOWN_LOCATION; /* Quiet warning. */
|
left-associative
1+2+3
と来た場合
(1+2)+3
に変換するやつ
- 再帰下降と相性が悪い(無限ループするので), whileに書き直すオペレーションが入る
#define POP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
#define POP \
do { \
switch (stack[sp].op) \
{ \
case TRUTH_ANDIF_EXPR: \
c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value \
== truthvalue_false_node); \
....
& ((1 << PREC_BITOR) | (1 << PREC_BITXOR) | (1 << PREC_BITAND) \
| (1 << PREC_SHIFT) | (1 << PREC_ADD) | (1 << PREC_MULT))) \
&& stack[sp].op != TRUNC_MOD_EXPR \
&& stack[0].expr.value != error_mark_node \
&& stack[1].expr.value != error_mark_node \
&& (c_tree_equal (stack[0].expr.value, omp_atomic_lhs) \
|| c_tree_equal (stack[1].expr.value, omp_atomic_lhs))) \
stack[0].expr.value \
= build2 (stack[1].op, TREE_TYPE (stack[0].expr.value), \
stack[0].expr.value, stack[1].expr.value); \
else \
stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc, \
stack[sp].op, \
stack[sp - 1].expr, \
stack[sp].expr); \
sp--; \
} while (0)
|
stackに代入するタイミングでc_parser_cast_expression
が呼ばれていそう
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
/* Parse a cast expression (C90 6.3.4, C99 6.5.4, C11 6.5.4). If AFTER
is not NULL then it is an Objective-C message expression which is the
primary-expression starting the expression as an initializer.
cast-expression:
unary-expression
( type-name ) unary-expression
*/
static struct c_expr
c_parser_cast_expression (c_parser *parser, struct c_expr *after)
{
location_t cast_loc = c_parser_peek_token (parser)->location;
gcc_assert (!after || c_dialect_objc ());
if (after)
return c_parser_postfix_expression_after_primary (parser,
cast_loc, *after);
|
下のifで処理されるのは次のケースみたい
(int )0.1
j = ({ i = 1;})
1
2
3
4
5
6
7
8
|
/* If the expression begins with a parenthesized type name, it may
be either a cast or a compound literal; we need to see whether
the next character is '{' to tell the difference. If not, it is
an unary expression. Full detection of unknown typenames here
would require a 3-token lookahead. */
if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
&& c_token_starts_typename (c_parser_peek_2nd_token (parser)))
{
|
次にここを読む
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
/* Parse an unary expression (C90 6.3.3, C99 6.5.3, C11 6.5.3).
unary-expression:
postfix-expression
++ unary-expression
-- unary-expression
unary-operator cast-expression
sizeof unary-expression
sizeof ( type-name )
unary-operator: one of
& * + - ~ !
GNU extensions:
unary-expression:
__alignof__ unary-expression
__alignof__ ( type-name )
&& identifier
(C11 permits _Alignof with type names only.)
unary-operator: one of
__extension__ __real__ __imag__
Transactional Memory:
unary-expression:
transaction-expression
In addition, the GNU syntax treats ++ and -- as unary operators, so
they may be applied to cast expressions with errors for non-lvalues
given later. */
static struct c_expr
c_parser_unary_expression (c_parser *parser)
{
int ext;
struct c_expr ret, op;
location_t op_loc = c_parser_peek_token (parser)->location;
location_t exp_loc;
location_t finish;
ret.original_code = ERROR_MARK;
ret.original_type = NULL;
switch (c_parser_peek_token (parser)->type)
|
例えばこのcaseは++i
のとき
1
2
3
4
5
6
7
8
9
|
switch (c_parser_peek_token (parser)->type)
{
case CPP_PLUS_PLUS:
c_parser_consume_token (parser);
exp_loc = c_parser_peek_token (parser)->location;
op = c_parser_cast_expression (parser, NULL);
op = default_function_array_read_conversion (exp_loc, op);
return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op);
|
#
c_parser_peek_token(parser)をgdbで読む
p c_parser_peek_token(parser)
するとポインタが返ってくる
p *c_parser_peek_token(parser)
とかすると中身が見れる
このあたりのデバッグサポートライブラリはConfigureで指定するとリンクされて使えるようになるらしい
p *c_parser_peek_token(parser)
したところ、fieldにvalue
がある
#
c_parser_postfix_expression
8983行目くらい
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
static struct c_expr
c_parser_postfix_expression (c_parser *parser)
{
struct c_expr expr, e1;
struct c_type_name *t1, *t2;
location_t loc = c_parser_peek_token (parser)->location;
source_range tok_range = c_parser_peek_token (parser)->get_range ();
expr.original_code = ERROR_MARK;
expr.original_type = NULL;
switch (c_parser_peek_token (parser)->type)
{
case CPP_NUMBER:
expr.value = c_parser_peek_token (parser)->value;
set_c_expr_source_range (&expr, tok_range);
loc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
if (TREE_CODE (expr.value) == FIXED_CST
&& !targetm.fixed_point_supported_p ())
{
error_at (loc, "fixed-point types not supported for this target");
expr.set_error ();
}
break;
case CPP_CHAR:
case CPP_CHAR16:
case CPP_CHAR32:
case CPP_UTF8CHAR:
case CPP_WCHAR:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
case CPP_NAME:
switch (c_parser_peek_token (parser)->id_kind)
{
case C_ID_ID:
{
tree id = c_parser_peek_token (parser)->value;
c_parser_consume_token (parser);
expr.value = build_external_ref (loc, id,
(c_parser_peek_token (parser)->type
== CPP_OPEN_PAREN),
&expr.original_type);
set_c_expr_source_range (&expr, tok_range);
break;
}
case C_ID_CLASSNAME:
{
/* Here we parse the Objective-C 2.0 Class.name dot
syntax. */
tree class_name = c_parser_peek_token (parser)->value;
tree component;
c_parser_consume_token (parser);
gcc_assert (c_dialect_objc ());
if (!c_parser_require (parser, CPP_DOT, "expected %<.%>"))
{
expr.set_error ();
break;
}
if (c_parser_next_token_is_not (parser, CPP_NAME))
{
c_parser_error (parser, "expected identifier");
expr.set_error ();
break;
}
|
C言語だとreturnで値がコピーされるので、ローカル変数の構造体をそのまま返すことができる
#
build_external_ref (location_t loc, tree id, bool fun, tree *type)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
/* Build an external reference to identifier ID. FUN indicates
whether this will be used for a function call. LOC is the source
location of the identifier. This sets *TYPE to the type of the
identifier, which is not the same as the type of the returned value
for CONST_DECLs defined as enum constants. If the type of the
identifier is not available, *TYPE is set to NULL. */
tree
build_external_ref (location_t loc, tree id, bool fun, tree *type)
{
tree ref;
tree decl = lookup_name (id);
/* In Objective-C, an instance variable (ivar) may be preferred to
whatever lookup_name() found. */
decl = objc_lookup_ivar (decl, id);
*type = NULL;
if (decl && decl != error_mark_node)
{
ref = decl;
*type = TREE_TYPE (ref);
}
else if (fun)
/* Implicit function declaration. */
ref = implicitly_declare (loc, id);
else if (decl == error_mark_node)
/* Don't complain about something that's already been
complained about. */
return error_mark_node;
else
{
undeclared_variable (loc, id);
return error_mark_node;
}
if (TREE_TYPE (ref) == error_mark_node)
return error_mark_node;
if (TREE_DEPRECATED (ref))
warn_deprecated_use (ref, NULL_TREE);
/* Recursive call does not count as usage. */
if (ref != current_function_decl)
{
TREE_USED (ref) = 1;
|
昔のCは型を定義しないで名前を定義して、後から型を定義できるようになっていた
ここまではIDが来ていて、具体的にすでに登録されているかの確認はしていない
tree decl = lookup_name (id);
で確認していそう
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
#0 build_external_ref (loc=loc@entry=184896, id=id@entry=0x7ffff64518c0,
fun=<optimized out>, type=type@entry=0x7fffffffd010)
at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-typeck.c:2744
#1 0x0000000000830a63 in c_parser_postfix_expression (
parser=parser@entry=0x7ffff7ff8ab0)
at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:9043
#2 0x000000000083c8d3 in c_parser_unary_expression (
parser=parser@entry=0x7ffff7ff8ab0)
at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:8269
#3 0x000000000083db87 in c_parser_cast_expression (
parser=parser@entry=0x7ffff7ff8ab0, after=0x0)
at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:8108
#4 0x000000000083de3d in c_parser_binary_expression (
parser=parser@entry=0x7ffff7ff8ab0, after=<optimized out>,
omp_atomic_lhs=0x0)
at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:7911
#5 0x000000000083f186 in c_parser_conditional_expression (
parser=parser@entry=0x7ffff7ff8ab0, after=<optimized out>,
omp_atomic_lhs=<optimized out>)
at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:7645
#6 0x000000000083f971 in c_parser_expr_no_commas (
parser=parser@entry=0x7ffff7ff8ab0, after=after@entry=0x0,
omp_atomic_lhs=omp_atomic_lhs@entry=0x0)
|
#
午後
午後はCbCのupgradeをしていきます
#
CbC_gccのupgrade
1
2
|
$ cd ~/src/CbC_gcc
$ hg pull ../GCC_original
|
1
2
|
$hg updat -C 145
$hg resolve
|
conflictしたやつ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
merging gcc/c-family/c-common.c
merging gcc/c/c-decl.c
merging gcc/c/c-parser.c
merging gcc/calls.c
merging gcc/config/i386/i386.c
merging gcc/gimple.c
merging gcc/ipa-inline.c
3 files to edit
merging gcc/c-family/c-common.c failed!
3 files to edit
merging gcc/c/c-decl.c failed!
3 files to edit
merging gcc/c/c-parser.c failed!
3 files to edit
merging gcc/calls.c failed!
3 files to edit
merging gcc/config/i386/i386.c failed!
3 files to edit
merging gcc/gimple.c failed!
3 files to edit
merging gcc/ipa-inline.c failed!
|
変更点を探して、中のCbCの記述を探す
1
2
3
4
|
$hg diff gcc/c-family/c-common.c -r -1
$grep CbC gcc/c-family/c-common.c
$hg cat -r 145 gcc/c-family/c-common.c > gcc/c-family/c-common.c
$hg diff gcc/c-family/c-common.c
|
あとはvimを使っていい感じに修正する
1
|
$hg resolve -m gcc/c-family/c-common.c
|
なんか直前のcommitが最新になっていて、今のcommitが古いやつになっていた。
なので一回pull
してupdate -r 145
して、直前の古い状態に戻しておく
#
なおしたところ
__code
-> void
への関数型の変換部分(function declaration)
#
LLVM側のupdate
新しいのをpullしてきて、新しい方にupdateする
vimdiffが起動したら:cq
で抜けられるらしい
- 今回はファイルに
>>>>
====
<<<<
は書き出さない
1
2
3
4
5
6
|
$cd ~/CbC_llvm
$hg log | less
$hg pull ../LLVM_original
$hg log | less
$hg update -r 150 -C
$hg merge -r 149
|
was deleted in local
これみたいなエラーが出たら、 d で消しちゃっていい
#
llvm側で変数の寿命を管理しているとこを見てみる
clang/lib/Parse/ParseExpr.cpp
を見ていく
llvmのcppはまぁ正気なcppらしい
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
// Function designators are allowed to be undeclared (C99 6.5.1p2), so we
// need to know whether or not this identifier is a function designator or
// not.
UnqualifiedId Name;
CXXScopeSpec ScopeSpec;
SourceLocation TemplateKWLoc;
Token Replacement;
CastExpressionIdValidator Validator(
/*Next=*/Tok,
/*AllowTypes=*/isTypeCast != NotTypeCast,
/*AllowNonTypes=*/isTypeCast != IsTypeCast);
Validator.IsAddressOfOperand = isAddressOfOperand;
if (Tok.isOneOf(tok::periodstar, tok::arrowstar)) {
Validator.WantExpressionKeywords = false;
Validator.WantRemainingKeywords = false;
} else {
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
/// Once the leading part of a postfix-expression is parsed, this
/// method parses any suffixes that apply.
///
/// \verbatim
/// postfix-expression: [C99 6.5.2]
/// primary-expression
/// postfix-expression '[' expression ']'
/// postfix-expression '[' braced-init-list ']'
/// postfix-expression '(' argument-expression-list[opt] ')'
/// postfix-expression '.' identifier
/// postfix-expression '->' identifier
/// postfix-expression '++'
/// postfix-expression '--'
/// '(' type-name ')' '{' initializer-list '}'
/// '(' type-name ')' '{' initializer-list ',' '}'
///
/// argument-expression-list: [C99 6.5.2]
/// argument-expression ...[opt]
/// argument-expression-list ',' assignment-expression ...[opt]
/// \endverbatim
ExprResult
Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
// Now that the primary-expression piece of the postfix-expression has been
// parsed, see if there are any postfix-expression pieces here.
SourceLocation Loc;
auto SavedType = PreferredType;
while (1) {
// Each iteration relies on preferred type for the whole expression.
PreferredType = SavedType;
switch (Tok.getKind()) {
case tok::code_completion:
if (InMessageExpression)
return LHS;
Actions.CodeCompletePostfixExpression(
getCurScope(), LHS, PreferredType.get(Tok.getLocation()));
cutOffParsing();
return ExprError();
|
- 大文字
Tok
が先読み部分っぽい
- さらに大域変数?
- debug traceしたらインスタンス変数だった
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
case tok::l_paren: // p-e: p-e '(' argument-expression-list[opt] ')'
case tok::lesslessless: { // p-e: p-e '<<<' argument-expression-list '>>>'
// '(' argument-expression-list[opt] ')'
tok::TokenKind OpKind = Tok.getKind();
InMessageExpressionRAIIObject InMessage(*this, false);
Expr *ExecConfig = nullptr;
BalancedDelimiterTracker PT(*this, tok::l_paren);
if (OpKind == tok::lesslessless) {
ExprVector ExecConfigExprs;
CommaLocsTy ExecConfigCommaLocs;
SourceLocation OpenLoc = ConsumeToken();
if (ParseSimpleExpressionList(ExecConfigExprs, ExecConfigCommaLocs)) {
(void)Actions.CorrectDelayedTyposInExpr(LHS);
LHS = ExprError();
}
SourceLocation CloseLoc;
if (TryConsumeToken(tok::greatergreatergreater, CloseLoc)) {
} else if (LHS.isInvalid()) {
SkipUntil(tok::greatergreatergreater, StopAtSemi);
} else {
// There was an error closing the brackets
Diag(Tok, diag::err_expected) << tok::greatergreatergreater;
Diag(OpenLoc, diag::note_matching) << tok::lesslessless;
SkipUntil(tok::greatergreatergreater, StopAtSemi);
LHS = ExprError();
}
if (!LHS.isInvalid()) {
if (ExpectAndConsume(tok::l_paren))
LHS = ExprError();
else
|
たぶん上のが関数呼び出し部分っぽい気がする
- というわけで
Parser::ParsePostfixExpressionSuffix(ExprResult LHS)
をbreak pointに設定する
#
Parser::ParsePostfixExpressionSuffix(ExprResult LHS)
b clang::Parser::ParsePostfixExpressionSuffix
でbreak point設定
- llvmは
this
が色々入っている環境っぽい
- この関数自体は関数化なんなのかをチェックしているので、必ずしも関数の場合に突入してない
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
1895 ExprVector ArgExprs;
1896 CommaLocsTy CommaLocs;
1897 auto RunSignatureHelp = [&]() -> QualType {
1898 QualType PreferredType = Actions.ProduceCallSignatureHelp(
1899 getCurScope(), LHS.get(), ArgExprs, PT.getOpenLocation());
1900 CalledSignatureHelp = true;
1901 return PreferredType;
1902 };
1903 if (OpKind == tok::l_paren || !LHS.isInvalid()) {
1904 if (Tok.isNot(tok::r_paren)) {
1905 if (ParseExpressionList(ArgExprs, CommaLocs, [&] {
1906 PreferredType.enterFunctionArgument(Tok.getLocation(),
1907 RunSignatureHelp);
1908 })) {
1909 (void)Actions.CorrectDelayedTyposInExpr(LHS);
1910 // If we got an error when parsing expression list, we don't call
1911 // the CodeCompleteCall handler inside the parser. So call it here
1912 // to make sure we get overload suggestions even when we are in the
1913 // middle of a parameter.
1914 if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
1915 RunSignatureHelp();
1916 LHS = ExprError();
1917 } else if (LHS.isInvalid()) {
1918 for (auto &E : ArgExprs)
1919 Actions.CorrectDelayedTyposInExpr(E);
1920 }
1921 }
1922 }
1923
|
このあたりで引数を設定していそうだが…
1
2
3
4
|
1905 if (ParseExpressionList(ArgExprs, CommaLocs, [&] {
1906 PreferredType.enterFunctionArgument(Tok.getLocation(),
1907 RunSignatureHelp);
1908 })) {
|
- このParseExpressionListが
,
区切りの引数のリストがきていそう
#
llvmIRを出力してみる
1
|
$clang -S -emit-llvm hello.c
|
#
2020/02/15(3日目)
今日は変数のライフタイム/コード生成を追っていきます
#
LLVMのselectionと呼ばれるところ
- clangレベルでIRを出力しているところ
- IRからnativeを吐き出しているところ
コード生成を追うことに
#
clangレベルのコード生成っぽいところを探す
clang/lib/CodeGen
がそれっぽい
*selection
を探す
./lib/CodeGen/CGExpr.cpp
を読んで見る
194:RValue CodeGenFunction::EmitAnyExpr(const Expr *E,
をbreak pointにする
#
LLVMのdebug
こういうシェルスクリプトが生まれたので使う
1
|
gdb --args "/mnt/dalmore-home/one/build/build_llvm_origin/bin/clang-11" -cc1 -triple x86_64-unknown-linux-gnu -S -disable-free -main-file-name hello.c -mrelocation-model static -mthread-model posix -mframe-pointer=all -fmath-errno -fdenormal-fp-math=ieee,ieee -fdenormal-fp-math-f32=ieee,ieee -ffp-contract=on -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -v -resource-dir /mnt/dalmore-home/one/build/build_llvm_origin/lib/clang/11.0.0 -internal-isystem /usr/local/include -internal-isystem /mnt/dalmore-home/one/build/build_llvm_origin/lib/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir /mnt/dalmore-home/one/build/build_llvm_origin -ferror-limit 19 -fmessage-length 0 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -fcolor-diagnostics -faddrsig -o hello.s -x c /mnt/dalmore-home//one/src/test/hello.c
|
#
CodeGenFunction::EmitAnyExpr
clang::CodeGen::CodeGenFunction::EmitAnyExpr
をbreak pointにする
CGExpr.cpp
の先頭にnamespaceが切られているので、これの通りに先頭につける必要があるらしい
1
2
|
using namespace clang;
using namespace CodeGen;
|
上の場合は clang::CodeGen
EmitAnyExprで止まったのでback traceを確認してみる
CodeGenはAbstractFactoryパターンで書かれているので、CodeGeneratorImpl::HandleTopLevelDecl
を経由して呼び出されている
- これはclangレベルなのでIRの出力のみしている
- Nativeは多分あまりなにもしてない
この関数はclang::ParseAST
から呼び出される
#
ParseAST.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
//===----------------------------------------------------------------------===//
// Public interface to the file
//===----------------------------------------------------------------------===//
/// ParseAST - Parse the entire file specified, notifying the ASTConsumer as
/// the file is parsed. This inserts the parsed decls into the translation unit
/// held by Ctx.
///
void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer,
ASTContext &Ctx, bool PrintStats,
TranslationUnitKind TUKind,
CodeCompleteConsumer *CompletionConsumer,
bool SkipFunctionBodies) {
std::unique_ptr<Sema> S(
new Sema(PP, Ctx, *Consumer, TUKind, CompletionConsumer));
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(S.get());
ParseAST(*S.get(), PrintStats, SkipFunctionBodies);
}
void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) {
// Collect global stats on Decls/Stmts (until we have a module streamer).
if (PrintStats) {
Decl::EnableStatistics();
Stmt::EnableStatistics();
}
// Also turn on collection of stats inside of the Sema object.
|
Interfaceに対応するpublic APIのじっそう
- 上の
void clang::Parse((Preprocessor &PP, ASTConsumer *Consumer,)
はコンスタクタでなくてただのメソッドっぽい
- 実際に呼び出されているのは下のParseASTみたい
#
Consumerで呼び出されているGen
Gen
とかいうオブジェクトがあった。定義はこれ
std::unique_ptr<CodeGenerator> Gen;
- スマートポインタみたい
Get.get()
で中身が取れる
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
ASTConsumer *Consumer = &S.getASTConsumer();
std::unique_ptr<Parser> ParseOP(
new Parser(S.getPreprocessor(), S, SkipFunctionBodies));
Parser &P = *ParseOP.get();
llvm::CrashRecoveryContextCleanupRegistrar<const void, ResetStackCleanup>
CleanupPrettyStack(llvm::SavePrettyStackState());
PrettyStackTraceParserEntry CrashInfo(P);
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<Parser>
CleanupParser(ParseOP.get());
S.getPreprocessor().EnterMainSourceFile();
ExternalASTSource *External = S.getASTContext().getExternalSource();
if (External)
External->StartTranslationUnit(Consumer);
// If a PCH through header is specified that does not have an include in
// the source, or a PCH is being created with #pragma hdrstop with nothing
// after the pragma, there won't be any tokens or a Lexer.
bool HaveLexer = S.getPreprocessor().getCurrentLexer();
if (HaveLexer) {
llvm::TimeTraceScope TimeScope("Frontend");
P.Initialize();
Parser::DeclGroupPtrTy ADecl;
for (bool AtEOF = P.ParseFirstTopLevelDecl(ADecl); !AtEOF;
AtEOF = P.ParseTopLevelDecl(ADecl)) {
// If we got a null return and something *was* parsed, ignore it. This
// is due to a top-level semicolon, an action override, or a parse error
// skipping something.
if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get()))
return;
}
}
|
Sema経由でConsumerとかを取ってきてそう
for分の中に出てきているAdecl
は参照になっていて、順次updateされていくらしい
#
Semaを見に行く
lib/Sema/Sema.cpp
を見る
1
2
|
// This file implements the actions class which performs semantic analysis and
// builds an AST out of a parse stream.
|
よくわからんのでヘッダファイルを見に行く
include/clang/Sema/Sema.h
Parseは構文解析をしてパースするだけ
- ASTを作りたい
- このASTにセマンティクスをつける必要がある
- ASTのFactoryが必要になる
- これがSemaっぽい
なのでAST Factoryっぽい
336行目に書かれてる
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/// Sema - This implements semantic analysis and AST building for C.
class Sema final {
Sema(const Sema &) = delete;
void operator=(const Sema &) = delete;
/// A key method to reduce duplicate debug info from Sema.
virtual void anchor();
///Source of additional semantic information.
ExternalSemaSource *ExternalSource;
///Whether Sema has generated a multiplexer and has to delete it.
bool isMultiplexExternalSource;
static bool mightHaveNonExternalLinkage(const DeclaratorDecl *FD);
|
- finalは virtual function のoverrideの防止らしい
(const Sema &) = delete
とは一体?
#
試しにソートしてみた
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
14 43 527 include/clang/Frontend/PCHContainerOperations.h
14 43 545 include/clang/Serialization/SerializationDiagnostic.h
14 43 610 include/clang/Tooling/Refactoring/RefactoringDiagnostic.h
14 44 496 include/clang/Lex/LexDiagnostic.h
14 44 501 include/clang/Sema/SemaDiagnostic.h
14 44 506 include/clang/Parse/ParseDiagnostic.h
14 44 511 include/clang/Driver/DriverDiagnostic.h
14 44 521 include/clang/Analysis/AnalysisDiagnostic.h
14 44 521 include/clang/Frontend/FrontendDiagnostic.h
14 47 558 include/clang/CrossTU/CrossTUDiagnostic.h
15 46 509 include/clang/AST/CommentDiagnostic.h
23 62 770 include/clang/Tooling/ToolExecutorPluginRegistry.h
24 66 662 include/clang/Basic/CapturedStmt.h
24 69 749 include/clang/Basic/BitmaskEnum.h
25 66 717 include/clang/Basic/ExpressionTraits.h
25 73 757 include/clang/Basic/DiagnosticCategories.h
26 68 877 include/clang/Frontend/FrontendPluginRegistry.h
26 103 963 include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h
27 82 907 include/clang/AST/AST.h
27 87 875 include/clang/StaticAnalyzer/Checkers/LocalCheckers.h
28 82 951 include/clang/Basic/DiagnosticRefactoring.h
28 84 962 include/clang/Basic/DiagnosticSerialization.h
28 85 903 include/clang/Basic/DiagnosticLex.h
28 85 909 include/clang/Basic/DiagnosticSema.h
28 85 915 include/clang/Basic/DiagnosticParse.h
28 85 921 include/clang/Basic/DiagnosticDriver.h
28 85 933 include/clang/Basic/DiagnosticAnalysis.h
28 85 933 include/clang/Basic/DiagnosticFrontend.h
28 86 927 include/clang/Basic/DiagnosticCrossTU.h
28 87 903 include/clang/Basic/DiagnosticAST.h
28 87 927 include/clang/Basic/DiagnosticComment.h
30 86 877 include/clang/Frontend/MigratorOptions.h
30 90 868 include/clang/Basic/PragmaKinds.h
31 91 922 include/clang/AST/AbstractTypeReader.h
31 93 957 include/clang/Basic/AttrSubjectMatchRules.h
31 100 896 include/clang/Driver/Util.h
31 100 924 include/clang/Basic/FileSystemOptions.h
31 117 1268 include/clang/Lex/PreprocessorExcludedConditionalDirectiveSkipMapping.h
32 93 944 include/clang/AST/AbstractTypeWriter.h
32 111 1266 include/clang-c/FatalErrorHandler.h
33 102 929 include/clang/Basic/AttrKinds.h
33 104 980 include/clang/Edit/EditsReceiver.h
33 110 1270 include/clang/Tooling/Syntax/BuildTree.h
34 108 1208 include/clang/Rewrite/Frontend/Rewriters.h
35 143 1379 include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h
36 97 1031 include/clang/AST/ASTFwd.h
36 105 1226 include/clang/Analysis/SelectorExtras.h
36 142 1369 include/clang/AST/ASTDiagnostic.h
37 108 895 include/clang/Driver/Phases.h
37 137 1293 include/clang/Basic/PrettyStackTrace.h
37 151 1367 include/clang/AST/ASTContextAllocate.h
37 162 1506 include/clang/Tooling/Syntax/Mutations.h
38 91 1103 include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
38 113 1124 include/clang/Basic/CommentOptions.h
38 124 1653 include/clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h
38 139 1290 include/clang/FrontendTool/Utils.h
39 100 1166 include/clang/Edit/Rewriters.h
39 112 2007 include/clang-c/ExternC.h
39 139 1315 include/clang/Sema/SemaLambda.h
...
2456 6337 72088 include/clang/AST/TypeLoc.h
2518 9954 84357 include/clang/Format/Format.h
2562 11342 93946 include/clang/AST/DeclBase.h
2702 10276 100082 include/clang/Sema/DeclSpec.h
2922 10503 104051 include/clang/AST/DeclObjC.h
3103 13260 122386 include/clang/AST/ASTContext.h
3175 11308 130885 include/clang/Parse/Parser.h
3283 12371 124927 include/clang/AST/DeclTemplate.h
3495 9816 126411 include/clang/AST/RecursiveASTVisitor.h
3594 12701 114449 include/clang/AST/Stmt.h
3981 16688 151945 include/clang/AST/DeclCXX.h
4525 19376 170110 include/clang/AST/Decl.h
4599 18407 181669 include/clang/AST/StmtOpenMP.h
4840 18045 175567 include/clang/AST/ExprCXX.h
6009 25804 230882 include/clang/AST/Expr.h
6663 25974 244789 include/clang/AST/OpenMPClause.h
6782 28711 220435 include/clang-c/Index.h
7107 28644 251058 include/clang/AST/Type.h
7108 25250 212553 include/clang/ASTMatchers/ASTMatchers.h
12190 48469 560994 include/clang/Sema/Sema.h
217079 840657 7819915 total
|
#
lib/CodeGen/CGExprScalar.cpp
1
2
3
4
5
6
7
8
9
|
/// Emit the computation of the specified expression of scalar type, ignoring
/// the result.
Value *CodeGenFunction::EmitScalarExpr(const Expr *E, bool IgnoreResultAssign) {
assert(E && hasScalarEvaluationKind(E->getType()) &&
"Invalid scalar expression to emit");
return ScalarExprEmitter(*this, IgnoreResultAssign)
.Visit(const_cast<Expr *>(E));
}
|
- Expressionを受け取って、これからLLVM IRを生成する
1
2
|
p E->getType()
(gdb) { Value = { Value = 2415319184 }}
|
ScalarExprEmitter
- Exprを付けとって、それをたどっていく
.Visit
はvisitor patternっぽい
#
C++ の( …)
…はthree dot operatorとかいうらしい
https://stackoverflow.com/questions/23485643/understanding-the-dots-in-variadic-template-function
#
午後
直前のvisitor パターンがなんであるかを見に行きます
#
clang::CodeGen::CodeGenFunction::EmitScalarExpr
b clang::CodeGen::CodeGenFunction::EmitScalarExpr
してbreak pointをかけておく
lib/CodeGen/CGExprScalar.cpp
の中っぽい
1
2
3
4
5
6
7
8
9
10
11
|
//===--------------------------------------------------------------------===//
// Visitor Methods
//===--------------------------------------------------------------------===//
Value *Visit(Expr *E) {
ApplyDebugLocation DL(CGF, E);
return StmtVisitor<ScalarExprEmitter, Value*>::Visit(E);
}
Value *VisitStmt(Stmt *S) {
|
#
include/clang/AST/StmtVisitor.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
namespace clang {
/// StmtVisitorBase - This class implements a simple visitor for Stmt
/// subclasses. Since Expr derives from Stmt, this also includes support for
/// visiting Exprs.
template<template <typename> class Ptr, typename ImplClass, typename RetTy=void,
class... ParamTys>
class StmtVisitorBase {
public:
#define PTR(CLASS) typename Ptr<CLASS>::type
#define DISPATCH(NAME, CLASS) \
return static_cast<ImplClass*>(this)->Visit ## NAME( \
static_cast<PTR(CLASS)>(S), std::forward<ParamTys>(P)...)
RetTy Visit(PTR(Stmt) S, ParamTys... P) {
// If we have a binary expr, dispatch to the subcode of the binop. A smart
// optimizer (e.g. LLVM) will fold this comparison into the switch stmt
// below.
if (PTR(BinaryOperator) BinOp = dyn_cast<BinaryOperator>(S)) {
switch (BinOp->getOpcode()) {
case BO_PtrMemD: DISPATCH(BinPtrMemD, BinaryOperator);
case BO_PtrMemI: DISPATCH(BinPtrMemI, BinaryOperator);
case BO_Mul: DISPATCH(BinMul, BinaryOperator);
case BO_Div: DISPATCH(BinDiv, BinaryOperator);
case BO_Rem: DISPATCH(BinRem, BinaryOperator);
case BO_Add: DISPATCH(BinAdd, BinaryOperator);
case BO_Sub: DISPATCH(BinSub, BinaryOperator);
|
実際に飛ばされたのはこれ(105行目)
1
2
3
4
5
6
7
8
|
// Top switch stmt: dispatch to VisitFooStmt for each FooStmt.
switch (S->getStmtClass()) {
default: llvm_unreachable("Unknown stmt kind!");
#define ABSTRACT_STMT(STMT)
#define STMT(CLASS, PARENT) \
case Stmt::CLASS ## Class: DISPATCH(CLASS, CLASS);
#include "clang/AST/StmtNodes.inc"
}
|
- StmtNodes.incはclang/include/clang/Basic/StmtNodes.tdを元にビルド時に生成される
#
実際に呼ばれた箇所
1
2
3
4
5
6
7
8
9
10
11
12
13
|
return VisitCastExpr(E);
}
Value *VisitCastExpr(CastExpr *E);
Value *VisitCallExpr(const CallExpr *E) {
if (E->getCallReturnType(CGF.getContext())->isReferenceType())
return EmitLoadOfLValue(E);
Value *V = CGF.EmitCallExpr(E).getScalarVal();
EmitLValueAlignmentAssumption(E, V);
return V;
}
|
- Visitorパターンなので、
VisitCallExpr
を実装すれば、マクロで解決されてこれが呼び出される
- ここでコード生成が行われている
- コード生成している箇所を見るには
VisitCall*
をみること!!!
#
back trace
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
#0 (anonymous namespace)::ScalarExprEmitter::VisitCallExpr (this=0x7fffffff76e0, E=0xe6bdc10)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CGExprScalar.cpp:580
#1 0x00000000039f9b02 in clang::StmtVisitorBase<std::add_pointer, (anonymous namespace)::ScalarExprEmitter, llvm::Value*>::Visit (this=0x7fffffff76e0, S=0xe6bdc10) at tools/clang/include/clang/AST/StmtNodes.inc:801
#2 0x00000000039e1bf2 in (anonymous namespace)::ScalarExprEmitter::Visit (this=0x7fffffff76e0, E=0xe6bdc10)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CGExprScalar.cpp:426
#3 0x00000000039f71c2 in clang::CodeGen::CodeGenFunction::EmitScalarExpr (this=0x7fffffff7bc0, E=0xe6bdc10,
IgnoreResultAssign=true) at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CGExprScalar.cpp:4572
#4 0x00000000039955ec in clang::CodeGen::CodeGenFunction::EmitAnyExpr (this=0x7fffffff7bc0, E=0xe6bdc10,
aggSlot=..., ignoreResult=true) at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CGExpr.cpp:199
#5 0x000000000399556b in clang::CodeGen::CodeGenFunction::EmitIgnoredExpr (this=0x7fffffff7bc0, E=0xe6bdc10)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CGExpr.cpp:184
#6 0x00000000035f731d in clang::CodeGen::CodeGenFunction::EmitStmt (this=0x7fffffff7bc0, S=0xe6bdc10, Attrs=...)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CGStmt.cpp:113
#7 0x00000000035f8398 in clang::CodeGen::CodeGenFunction::EmitCompoundStmtWithoutScope (this=0x7fffffff7bc0,
S=..., GetLast=false, AggSlot=...)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CGStmt.cpp:444
#8 0x000000000367eddc in clang::CodeGen::CodeGenFunction::EmitFunctionBody (this=0x7fffffff7bc0, Body=0xe6bdc38)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CodeGenFunction.cpp:1170
#9 0x000000000367f976 in clang::CodeGen::CodeGenFunction::GenerateCode (this=0x7fffffff7bc0, GD=...,
Fn=0xe69af68, FnInfo=...)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CodeGenFunction.cpp:1335
#10 0x00000000036a5adc in clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition (this=0xe65b7a0, GD=...,
GV=0xe69af68) at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CodeGenModule.cpp:4484
#11 0x000000000369f182 in clang::CodeGen::CodeGenModule::EmitGlobalDefinition (this=0xe65b7a0, GD=..., GV=0x0)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CodeGenModule.cpp:2874
#12 0x000000000369de1e in clang::CodeGen::CodeGenModule::EmitGlobal (this=0xe65b7a0, GD=...)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CodeGenModule.cpp:2577
#13 0x00000000036a96e6 in clang::CodeGen::CodeGenModule::EmitTopLevelDecl (this=0xe65b7a0, D=0xe6bda30)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CodeGenModule.cpp:5289
#14 0x000000000457a4f6 in (anonymous namespace)::CodeGeneratorImpl::HandleTopLevelDecl (this=0xe65ad70, DG=...)
---Type <return> to continue, or q <return> to quit---
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/ModuleBuilder.cpp:170
#15 0x0000000004574165 in clang::BackendConsumer::HandleTopLevelDecl (this=0xe65aba0, D=...)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CodeGenAction.cpp:214
#16 0x0000000005970f01 in clang::ParseAST (S=..., PrintStats=false, SkipFunctionBodies=false)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Parse/ParseAST.cpp:162
#17 0x0000000003ce5a91 in clang::ASTFrontendAction::ExecuteAction (this=0xe63c1a0)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Frontend/FrontendAction.cpp:1047
#18 0x0000000004572303 in clang::CodeGenAction::ExecuteAction (this=0xe63c1a0)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CodeGenAction.cpp:1176
#19 0x0000000003ce53fd in clang::FrontendAction::Execute (this=0xe63c1a0)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Frontend/FrontendAction.cpp:940
#20 0x0000000003c7db31 in clang::CompilerInstance::ExecuteAction (this=0xe6381d0, Act=...)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Frontend/CompilerInstance.cpp:969
#21 0x0000000003e40b1d in clang::ExecuteCompilerInvocation (Clang=0xe6381d0)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:292
#22 0x0000000000a586fb in cc1_main (Argv=...,
Argv0=0x7fffffffde32 "/mnt/dalmore-home/one/build/build_llvm_origin/bin/clang-11",
MainAddr=0xa4ce20 <GetExecutablePath[abi:cxx11](char const*, bool)>)
at /mnt/dalmore-home/one/src/LLVM_original/clang/tools/driver/cc1_main.cpp:240
#23 0x0000000000a4e4c9 in ExecuteCC1Tool (ArgV=...)
at /mnt/dalmore-home/one/src/LLVM_original/clang/tools/driver/driver.cpp:328
#24 0x0000000000a4ebc3 in main (argc_=53, argv_=0x7fffffffd9c8)
at /mnt/dalmore-home/one/src/LLVM_original/clang/tools/driver/driver.cpp:402
|
#
中身の確認
1
|
if (E->getCallReturnType(CGF.getContext())->isReferenceType())
|
-
だいたいこれはfalseになるはず
-
stepして中身をおっていく
-
そのあと北場所
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
//===--------------------------------------------------------------------===//
// Expression Emission
//===--------------------------------------------------------------------===//
RValue CodeGenFunction::EmitCallExpr(const CallExpr *E,
ReturnValueSlot ReturnValue) {
// Builtins never have block type.
if (E->getCallee()->getType()->isBlockPointerType())
return EmitBlockCallExpr(E, ReturnValue);
if (const auto *CE = dyn_cast<CXXMemberCallExpr>(E))
return EmitCXXMemberCallExpr(CE, ReturnValue);
if (const auto *CE = dyn_cast<CUDAKernelCallExpr>(E))
return EmitCUDAKernelCallExpr(CE, ReturnValue);
if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(E))
if (const CXXMethodDecl *MD =
dyn_cast_or_null<CXXMethodDecl>(CE->getCalleeDecl()))
return EmitCXXOperatorMemberCallExpr(CE, MD, ReturnValue);
CGCallee callee = EmitCallee(E->getCallee());
if (callee.isBuiltin()) {
return EmitBuiltinExpr(callee.getBuiltinDecl(), callee.getBuiltinID(),
E, ReturnValue);
}
|
- 呼び出す関数を計算しないと行けない可能性があるのでEmitCalle
1
|
CGCallee callee = EmitCallee(E->getCallee());
|
- callするfunctionはcalleeが戻ってくるっぽい
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee,
const CallExpr *E, ReturnValueSlot ReturnValue,
llvm::Value *Chain) {
// Get the actual function type. The callee type will always be a pointer to
// function type or a block pointer type.
assert(CalleeType->isFunctionPointerType() &&
"Call must have function pointer type!");
const Decl *TargetDecl =
OrigCallee.getAbstractInfo().getCalleeDecl().getDecl();
CalleeType = getContext().getCanonicalType(CalleeType);
auto PointeeType = cast<PointerType>(CalleeType)->getPointeeType();
CGCallee Callee = OrigCallee;
if (getLangOpts().CPlusPlus && SanOpts.has(SanitizerKind::Function) &&
(!TargetDecl || !isa<FunctionDecl>(TargetDecl))) {
if (llvm::Constant *PrefixSig =
CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM)) {
SanitizerScope SanScope(this);
// Remove any (C++17) exception specifications, to allow calling e.g. a
// noexcept function through a non-noexcept pointer.
auto ProtoTy =
|
#
back trace
1
2
3
4
5
6
7
|
#0 clang::CodeGen::CodeGenFunction::EmitCall (this=0x7fffffff7bc0, CalleeType=..., OrigCallee=..., E=0xe6bdc10,
ReturnValue=..., Chain=0x0) at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CGExpr.cpp:4881
#1 0x00000000039ae87e in clang::CodeGen::CodeGenFunction::EmitCallExpr (this=0x7fffffff7bc0, E=0xe6bdc10,
ReturnValue=...) at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CGExpr.cpp:4630
#2 0x00000000039e282e in (anonymous namespace)::ScalarExprEmitter::VisitCallExpr (this=0x7fffffff76e0,
E=0xe6bdc10) at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CGExprScalar.cpp:583
#3 0x00000000039f9b02 in clang::StmtVisitorBase<std::add_pointer, (anonymous namespace)::ScalarExprEmitter, llvm::Value*>::Visit (this=0x7fffffff76e0, S=0xe6bdc10) at tools/clang/include/clang/AST/StmtNodes.inc:801
|
#
emi call
./clang/lib/CodeGen/CodeGenFunction.h
っぽい
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
//===--------------------------------------------------------------------===//
// Scalar Expression Emission
//===--------------------------------------------------------------------===//
/// EmitCall - Generate a call of the given function, expecting the given
/// result type, and using the given argument list which specifies both the
/// LLVM arguments and the types they were derived from.
RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee,
ReturnValueSlot ReturnValue, const CallArgList &Args,
llvm::CallBase **callOrInvoke, SourceLocation Loc);
RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee,
ReturnValueSlot ReturnValue, const CallArgList &Args,
llvm::CallBase **callOrInvoke = nullptr) {
return EmitCall(CallInfo, Callee, ReturnValue, Args, callOrInvoke,
SourceLocation());
}
RValue EmitCall(QualType FnType, const CGCallee &Callee, const CallExpr *E,
ReturnValueSlot ReturnValue, llvm::Value *Chain = nullptr);
RValue EmitCallExpr(const CallExpr *E,
|
#
EmitCall
./clang/lib/CodeGen/CGCall.cpp
を見ていく
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
/// Helper data structure to emit `AllocAlignAttr`.
class AllocAlignAttrEmitter final
: public AbstractAssumeAlignedAttrEmitter<AllocAlignAttr> {
public:
AllocAlignAttrEmitter(CodeGenFunction &CGF_, const Decl *FuncDecl,
const CallArgList &CallArgs)
: AbstractAssumeAlignedAttrEmitter(CGF_, FuncDecl) {
if (!AA)
return;
// Alignment may or may not be a constant, and that is okay.
Alignment = CallArgs[AA->getParamIndex().getLLVMIndex()]
.getRValue(CGF)
.getScalarVal();
}
};
} // namespace
RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
const CGCallee &Callee,
ReturnValueSlot ReturnValue,
const CallArgList &CallArgs,
llvm::CallBase **callOrInvoke,
SourceLocation Loc) {
// FIXME: We no longer need the types from CallArgs; lift up and simplify.
assert(Callee.isOrdinary() || Callee.isVirtual());
// Handle struct-return functions by passing a pointer to the
// location that we would like to return into.
QualType RetTy = CallInfo.getReturnType();
const ABIArgInfo &RetAI = CallInfo.getReturnInfo();
llvm::FunctionType *IRFuncTy = getTypes().GetFunctionType(CallInfo);
const Decl *TargetDecl = Callee.getAbstractInfo().getCalleeDecl().getDecl();
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl))
// We can only guarantee that a function is called from the correct
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
unsigned FirstIRArg, NumIRArgs;
std::tie(FirstIRArg, NumIRArgs) = IRFunctionArgs.getIRArgs(ArgNo);
switch (ArgInfo.getKind()) {
case ABIArgInfo::InAlloca: {
assert(NumIRArgs == 0);
assert(getTarget().getTriple().getArch() == llvm::Triple::x86);
if (I->isAggregate()) {
Address Addr = I->hasLValue()
? I->getKnownLValue().getAddress(*this)
: I->getKnownRValue().getAggregateAddress();
llvm::Instruction *Placeholder =
cast<llvm::Instruction>(Addr.getPointer());
if (!ArgInfo.getInAllocaIndirect()) {
// Replace the placeholder with the appropriate argument slot GEP.
CGBuilderTy::InsertPoint IP = Builder.saveIP();
Builder.SetInsertPoint(Placeholder);
Addr = Builder.CreateStructGEP(ArgMemory,
ArgInfo.getInAllocaFieldIndex());
Builder.restoreIP(IP);
} else {
// For indirect things such as overaligned structs, replace the
// placeholder with a regular aggregate temporary alloca. Store the
// address of this alloca into the struct.
Addr = CreateMemTemp(info_it->type, "inalloca.indirect.tmp");
Address ArgSlot = Builder.CreateStructGEP(
ArgMemory, ArgInfo.getInAllocaFieldIndex());
Builder.CreateStore(Addr.getPointer(), ArgSlot);
}
deferPlaceholderReplacement(Placeholder, Addr.getPointer());
} else if (ArgInfo.getInAllocaIndirect()) {
// Make a temporary alloca and store the address of it into the argument
// struct.
Address Addr = CreateMemTempWithoutCast(
I->Ty, getContext().getTypeAlignInChars(I->Ty),
"indirect-arg-temp");
I->copyInto(*this, Addr);
Address ArgSlot =
|
なんかLifeTimeSizeとか出てきた
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
if (NeedCopy) {
// Create an aligned temporary, and copy to it.
Address AI = CreateMemTempWithoutCast(
I->Ty, ArgInfo.getIndirectAlign(), "byval-temp");
IRCallArgs[FirstIRArg] = AI.getPointer();
// Emit lifetime markers for the temporary alloca.
uint64_t ByvalTempElementSize =
CGM.getDataLayout().getTypeAllocSize(AI.getElementType());
llvm::Value *LifetimeSize =
EmitLifetimeStart(ByvalTempElementSize, AI.getPointer());
// Add cleanup code to emit the end lifetime marker after the call.
if (LifetimeSize) // In case we disabled lifetime markers.
CallLifetimeEndAfterCall.emplace_back(AI, LifetimeSize);
// Generate the copy.
I->copyInto(*this, AI);
} else {
// Skip the extra memcpy call.
auto *T = V->getType()->getPointerElementType()->getPointerTo(
CGM.getDataLayout().getAllocaAddrSpace());
IRCallArgs[FirstIRArg] = getTargetHooks().performAddrSpaceCast(
*this, V, LangAS::Default, CGM.getASTAllocaAddressSpace(), T,
true);
}
}
|
このfunction call時のclean upなLifeTime操作
- このルーチンが有効化されていると、TailCall最適化できない
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
4543 // If we made a temporary, be sure to clean up after ourselves. Note that we
4544 // can't depend on being inside of an ExprWithCleanups, so we need to manually
4545 // pop this cleanup later on. Being eager about this is OK, since this
4546 // temporary is 'invisible' outside of the callee.
4547 if (UnusedReturnSizePtr)
4548 pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, SRetAlloca,
4549 UnusedReturnSizePtr);
4550
4551 llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest();
4552
4553 SmallVector<llvm::OperandBundleDef, 1> BundleList =
4554 getBundlesForFunclet(CalleePtr);
4555
4556 if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurFuncDecl))
4557 if (FD->usesFPIntrin())
4558 // All calls within a strictfp function are marked strictfp
4559 Attrs =
4560 Attrs.addAttribute(getLLVMContext(), llvm::AttributeList::FunctionIndex,
4561 llvm::Attribute::StrictFP);
4562
4563 AssumeAlignedAttrEmitter AssumeAlignedAttrEmitter(*this, TargetDecl);
4564 Attrs = AssumeAlignedAttrEmitter.TryEmitAsCallSiteAttribute(Attrs);
4565
4566 AllocAlignAttrEmitter AllocAlignAttrEmitter(*this, TargetDecl, CallArgs);
4567 Attrs = AllocAlignAttrEmitter.TryEmitAsCallSiteAttribute(Attrs);
|
このあたりも関係してそう
1
2
3
4
5
6
7
8
9
|
4789 }
4790
4791 // Explicitly call CallLifetimeEnd::Emit just to re-use the code even though
4792 // we can't use the full cleanup mechanism.
4793 for (CallLifetimeEnd &LifetimeEnd : CallLifetimeEndAfterCall)
4794 LifetimeEnd.Emit(*this, /*Flags=*/{});
4795
4796 return Ret;
4797 }
|
Tail Call関連
1
2
3
4
5
6
|
4619 // Suppress tail calls if requested.
4620 if (llvm::CallInst *Call = dyn_cast<llvm::CallInst>(CI)) {
4621 if (TargetDecl && TargetDecl->hasAttr<NotTailCalledAttr>())
(gdb) l
4622 Call->setTailCallKind(llvm::CallInst::TCK_NoTail);
4623 }
|
#
使ったbreak point
1
2
3
4
5
6
7
|
Num Type Disp Enb Address What
3 breakpoint keep y 0x00000000039b0d76 in clang::CodeGen::CodeGenFunction::EmitCall(clang::QualType, clang::CodeGen::CGCallee const&, clang::CallExpr const*, clang::CodeGen::ReturnValueSlot, llvm::Value*)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CGExpr.cpp:5047
breakpoint already hit 1 time
4 breakpoint keep y 0x000000000393619f in clang::CodeGen::CodeGenFunction::EmitCall(clang::CodeGen::CGFunctionInfo const&, clang::CodeGen::CGCallee const&, clang::CodeGen::ReturnValueSlot, clang::CodeGen::CallArgList const&, llvm::CallBase**, clang::SourceLocation)
at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CGCall.cpp:4547
breakpoint already hit 1 time
|
#
作ってそう?
CreateCall
とかcreateBasicBlock
とかしている
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
4566 AllocAlignAttrEmitter AllocAlignAttrEmitter(*this, TargetDecl, CallArgs);
4567 Attrs = AllocAlignAttrEmitter.TryEmitAsCallSiteAttribute(Attrs);
4568
4569 // Emit the actual call/invoke instruction.
4570 llvm::CallBase *CI;
4571 if (!InvokeDest) {
4572 CI = Builder.CreateCall(IRFuncTy, CalleePtr, IRCallArgs, BundleList);
4573 } else {
4574 llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
4575 CI = Builder.CreateInvoke(IRFuncTy, CalleePtr, Cont, InvokeDest, IRCallArgs,
4576 BundleList);
4577 EmitBlock(Cont);
4578 }
4579 if (callOrInvoke)
4580 *callOrInvoke = CI;
4
|
#
コード生成文
return Insert(CI, Name)
で呼び出しているのが生成してそう
- 多分
llvm/include/llvm/IR/IRBuilder.h
で呼ばれているもの
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
llvm::IRBuilder<llvm::ConstantFolder, clang::CodeGen::CGBuilderInserter>::Insert<llvm::CallInst> (
this=0x7fffffff7ca8, I=0xe6c2ee0, Name=...)
at /mnt/dalmore-home/one/src/LLVM_original/llvm/include/llvm/IR/IRBuilder.h:993
993 this->InsertHelper(I, Name, BB, InsertPt);
(gdb) l
988 const T &getFolder() { return Folder; }
989
990 /// Insert and return the specified instruction.
991 template<typename InstTy>
992 InstTy *Insert(InstTy *I, const Twine &Name = "") const {
993 this->InsertHelper(I, Name, BB, InsertPt);
994 this->SetInstDebugLocation(I);
995 return I;
996 }
|
ここのllvm::IRBuilder
でコード生成されていそう
- このInsertHelperが何をしているかによりそう
- これ自体はtemplateなので109個のInsertが存在している
- instruction typeの数だけ
- call/add/条件分岐, 代入とか…