../compiler-note

Compiler Note(从Xcode的角度)

Makefile
% clang -ccc-print-phases hello.m

0: input, "hello.m", objective-c
1: preprocessor, {0}, objective-c-cpp-output
2: compiler, {1}, assembler
3: assembler, {2}, object
4: linker, {3}, image
5: bind-arch, "x86_64", {4}, image


a.预处理
    i. 处理宏(宏扩展):将源码中的宏表达替换为其定义值
    ii. 有时做一些内联的工作
        - 但有时会出错:考虑用 static inline函数来替代一些宏表达
b.token化
    i. 什么是token?
        - Eg
        ```objective-c
        Objective-C
        // token化前:(宏扩展前的源码)
        int main() {
        NSLog(@"hello, %@", @"world");
        return 0;
        }


        Groovy
        // token化后(location对应的是宏扩展前的位置)
        int 'int'        [StartOfLine]  Loc=<hello.m:4:1>
        identifier 'main'        [LeadingSpace] Loc=<hello.m:4:5>
        l_paren '('             Loc=<hello.m:4:9>
        r_paren ')'             Loc=<hello.m:4:10>
        l_brace '{'      [LeadingSpace] Loc=<hello.m:4:12>
        identifier 'NSLog'       [StartOfLine] [LeadingSpace]   Loc=<hello.m:5:3>
        l_paren '('             Loc=<hello.m:5:8>
        at '@'          Loc=<hello.m:5:9>
        string_literal '"hello, %@"'            Loc=<hello.m:5:10>
        comma ','               Loc=<hello.m:5:21>
        at '@'   [LeadingSpace] Loc=<hello.m:5:23>
        string_literal '"world"'                Loc=<hello.m:5:24>
        r_paren ')'             Loc=<hello.m:5:31>
        semi ';'                Loc=<hello.m:5:32>
        return 'return'  [StartOfLine] [LeadingSpace]   Loc=<hello.m:6:3>
        numeric_constant '0'     [LeadingSpace] Loc=<hello.m:6:10>
        semi ';'                Loc=<hello.m:6:11>
        r_brace '}'      [StartOfLine]  Loc=<hello.m:7:1>
        eof ''          Loc=<hello.m:7:2>


        ```

c.解析
    i.token将被解析成为一棵抽象的语法树(AbstractSyntaxTree)
        - Eg
        ```objective-c
        Objective-C
        // 高阶语言的源码
        #import <Foundation/Foundation.h>
        @interface World
        - (void)hello;@end
        @implementation World
        - (void)hello {
        NSLog(@"hello, world");
        }@end
        int main() {
        World* world = [World new];
        [world hello];
        }


        Groovy
        // 打印出来的语法树
        @interface World- (void) hello;
        @end
        @implementation World
        - (void) hello (CompoundStmt 0x10372ded0 <hello.m:8:15, line:10:1>
        (CallExpr 0x10372dea0 <line:9:3, col:24> 'void'
            (ImplicitCastExpr 0x10372de88 <col:3> 'void (*)(NSString *, ...)' <FunctionToPointerDecay>
            (DeclRefExpr 0x10372ddd8 <col:3> 'void (NSString *, ...)' Function 0x1023510d0 'NSLog' 'void (NSString *, ...)'))
            (ObjCStringLiteral 0x10372de38 <col:9, col:10> 'NSString *'
            (StringLiteral 0x10372de00 <col:10> 'char [13]' lvalue "hello, world"))))


        @end
        int main() (CompoundStmt 0x10372e118 <hello.m:13:12, line:16:1>
        (DeclStmt 0x10372e090 <line:14:4, col:30>
            0x10372dfe0 "World *world =
            (ImplicitCastExpr 0x10372e078 <col:19, col:29> 'World *' <BitCast>
                (ObjCMessageExpr 0x10372e048 <col:19, col:29> 'id':'id' selector=new class='World'))")
        (ObjCMessageExpr 0x10372e0e8 <line:15:4, col:16> 'void' selector=hello
            (ImplicitCastExpr 0x10372e0d0 <col:5> 'World *' <LValueToRValue>
            (DeclRefExpr 0x10372e0a8 <col:5> 'World *' lvalue Var 0x10372dfe0 'world' 'World *'))))


        ```
        - clang根据AST中的<line, col>来给出代码错误的位置(如果有错的话)
d. 静态检查
    - 有了 抽象语法树AST 之后,可以对TA进行错误检查,eg 类型检查
    i. 类型检查
        - ' Check if the program send the correct messages to the correct objects & calls the correct functions on the correct values.'
        - 动态类型、静态类型?前者在运行时检查,后者在编译时检查
    ii. 一些其他检查
        - 对于clang,lib/StaticAnalyzer/Checkers/ 下有TA使用的checker.cpp。eg ObjCUnuserdIVarsChecker.cpp, ObjCSelfInitChecker.cpp, etc (you can tell the usage by their names)
e. 代码生成:前面都正确执行完之后,可以生成LLVM代码了(存放在 xxx.ll 文件里)
    i.代码优化:给clang命令加上-O3参数
    ii.To compare with clang:可以参考[gcc做了哪些代码优化](https://ridiculousfish.com/blog/posts/will-it-optimize.html)

/note/ /compiler/