0%

总感觉用账号密码提交代码是反人类的🙂

解决方法:

SourceTree -> 偏好设置-> Git -> 使用系统安装的Git

好长时间不写博客了,能水一篇是一篇.

–EOF–

位运算了解一下,哈哈哈哈哈哈…

Person.swift

import Foundation

extension Bool {
    init(_ integer: Int){
        self.init(integer != 0)
    }
}

struct Person {
    
    let TallMask = (0b00000001 << 0b00000000)
    let RichMask = (0b00000001 << 0b00000001)
    let HandsomeMask = (0b00000001 << 0b00000010)
    
    var _tallRichHandsome = 0b00000000
    
    mutating func setTall(_ tall: Bool) {
        if tall {
            _tallRichHandsome = (_tallRichHandsome | TallMask)
        } else {
            _tallRichHandsome = (_tallRichHandsome & ~TallMask)
        }
    }
    
    func isTall() -> Bool {
        return Bool(_tallRichHandsome & TallMask)
    }
    
    mutating func setRich(_ rich: Bool) {
        if rich {
            _tallRichHandsome = (_tallRichHandsome | RichMask)
        } else {
            _tallRichHandsome = (_tallRichHandsome & ~RichMask)
        }
    }
    
    func isRich() -> Bool {
        return Bool(_tallRichHandsome & RichMask)
    }
    
    mutating func setHandsome(_ handsome: Bool) {
        if handsome {
            _tallRichHandsome = (_tallRichHandsome | HandsomeMask)
        } else {
            _tallRichHandsome = (_tallRichHandsome & ~HandsomeMask)
        }
    }
    
    func isHandsome() -> Bool {
        return Bool(_tallRichHandsome & HandsomeMask)
    }
}

main.swift

import Foundation


var person = Person()

print(person.isTall())
print(person.isRich())
print(person.isHandsome())
print("================")
print(person._tallRichHandsome)
print("===================")
person.setTall(true)
person.setRich(true)
person.setHandsome(true)
print(person.isTall())
print(person.isRich())
print(person.isHandsome())

print("===================")
//print(person.TallMask)
//print(person.RichMask)
//print(person.HandsomeMask)
person.setTall(false)
print(person.isTall())
print(person.isRich())
print(person.isHandsome())

print("==================")
//print(0b00000000)
//print(0b00000001)
//print(0b00000010)

print("==================")

print(person._tallRichHandsome)

–EOF–

//实例对象(instance对象)
    //isa指针
    //变量
//类对象(Class对象)
    //每个类有且只有一个类对象
    //class对象在内存中存储的主要信息有:
    //isa指针
    //superclass指针
    //类属性信息(@property), 类的对象信息(instance method)
    //类的协议信息(protocol),成员变量信息(ivar)
//元类对象(meta class)
    //每个类只有一个元类对象
    //元类对象跟类对象内存结构是一样的
    //包括:
    //isa指针
    //superclass指针
    //类的类方法信息 (class method,+号开头)

#import <Foundation/Foundation.h>
#import <objc/runtime.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        //实例对象(instance对象)
        NSObject *obj1 = [[NSObject alloc] init];
        NSObject *obj2 = [[NSObject alloc] init];
        
        //类对象(Class对象)
        Class objClass1 = [obj1 class]; //类对象
        Class objClass2 = [obj2 class];
        Class objClass3 = object_getClass(obj2);
        Class objClass4 = object_getClass(obj1);
        Class objClass5 = [NSObject class];
        NSLog(@"%p", objClass1);
        NSLog(@"%p", objClass2);
        NSLog(@"%p", objClass3);
        NSLog(@"%p", objClass4);
        NSLog(@"%p", objClass5);
        
        //元类对象(meta class对象)
        Class metaClass = object_getClass([NSObject class]);
    }
    return 0;
}

–EOF–

A protocol defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality. The protocol can then be adopted by a class, structure, or enumeration to provide an actual implementation of those requirements. Any type that satisfies the requirements of a protocol is said to conform to that protocol.

import Foundation

//协议语法
protocol SomeProtocol {
    
}

struct SomeStructure: SomeProtocol {}
class SomeClass: SomeProtocol {}

//属性要求
//如果属性标注了(set get),则不能通过常量存储属性和只读计算属性来实现
//如果属性只设置了(get),那么任何类型都可以满足,包括变量存储属性

protocol SomeProtocol1 {
    var mustBeSettable: Int { get set }
    var doesNotNeedToBeSettable: Int { get }
}

//协议中用static修饰时,实现中用static或者class实现都行
protocol AnotherProtocol {
    static var someTypeProperty: Int { get set }
}

protocol FullyNamed {
    var fullName: String { get }
}

struct Person: FullyNamed {
    var fullName: String
}
//可set 可 get
let john = Person(fullName: "Tom")

class Starship: FullyNamed {
    var prefix: String?
    var name: String
    
    init(name: String, prefix: String? = nil) {
        self.name = name
        self.prefix = prefix
    }
    
    var fullName: String {
        return (prefix != nil ? prefix!+" " : "") + name
    }
}

var ncc1701 = Starship(name: "Enterprise", prefix: "USS")

//方法要求

//不能在协议方法中指定默认值

protocol SomeProtocol2 {
    static func someTypeMethod()
}

protocol RandomNumberGenerator {
    func random() -> Double
}

//线性同余生成器的伪随机数生成器算法,好高大上有木有...
class LinearCongruentialGenerator: RandomNumberGenerator {
    var lastRandom = 42.0
    let m = 139968.0
    let a = 3877.0
    let c = 29573.0
    func random() -> Double {
        lastRandom = ((lastRandom * a + c).truncatingRemainder(dividingBy: m))
        return lastRandom / m
    }
}

let generator = LinearCongruentialGenerator()
print(generator.random())
print(generator.random())

//变异方法要求 mutating method requirements
//如果希望实现协议的任何类型(类,结构体,枚举)要修改实例或者实例中的任何属性
//得在func前加mutating关键字
//类实现时,无需加mutating,结构体,枚举需要加
protocol Toggleable {
    mutating func toggle()
}

enum OnOffSwitch: Toggleable {
    case off, on
    mutating func toggle() {
        switch self {
        case .on:
            self = .off
        case .off:
            self = .on
        }
    }
}

var lightSwitch = OnOffSwitch.off
print(lightSwitch)
lightSwitch.toggle()
print(lightSwitch)

//初始化程序要求
protocol SomeProtocol3 {
    init(someParameter: Int)
}

//required 方便子类继承,从而遵守SomeProtocol3协议
//如果给类加上final,则required可以省略
final class SomeClass3: SomeProtocol3 {
    required init(someParameter: Int) {
        //在这进行初始化实现
    }
}

//如果子类重写父类中init方法,并且这个init也是协议中的实现,则需要用
//`required`和`override`修饰
protocol SomeProtocol4 {
    init()
}

class SomeSuperClass {
    init() {
        
    }
}

class SomeSubClass: SomeSuperClass, SomeProtocol4 {
    required override init() {
        //good job
    }
}

//协议还可以定义可失败构造器

//协议作为类型
//协议本身不实现任何功能,但是,创建的任何协议都会变成代码中成熟的类型.
//可以用协议的地方:
//1. 在函数,方法或初始化方法中作为参数或返回值
//2. 作为常量,变量,或者属性的类型
//3. 作为数组,字典或其他容器类型的元素类型

class Dice {
    let sides: Int
    let generator: RandomNumberGenerator
    init(sides: Int, generator: RandomNumberGenerator) {
        self.sides = sides
        self.generator = generator
    }
    func roll() -> Int {
        return Int(generator.random() * Double(sides)) + 1
    }
}
var d6 = Dice(sides: 6, generator: LinearCongruentialGenerator())
for _ in 1...5 {
    print("Random dice roll is \(d6.roll())")
}

//委托
//响应特定操作或者从外部检索数据
protocol DiceGame {
    var dice: Dice { get }
    func play()
}

protocol DiceGameDelegate: AnyObject {
    func gameDidStart(_ game: DiceGame)
    func game(_ game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int)
    func gameDidEnd(_ game: DiceGame)
}

class SnakesAndLadders: DiceGame {
    let finalSquare = 25
    let dice = Dice(sides: 6, generator: LinearCongruentialGenerator())
    var square = 0
    var board: [Int]
    
    init() {
        board = Array(repeating: 0, count: finalSquare + 1)
        board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
        board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
    }
    
    weak var delegate: DiceGameDelegate?
    func play() {
        square = 0
        delegate?.gameDidStart(self)
        gameLoop: while square != finalSquare {
            let diceRoll = dice.roll()
            delegate?.game(self, didStartNewTurnWithDiceRoll: diceRoll)
            switch square + diceRoll {
            case finalSquare:
                break gameLoop
            case let newSquare where newSquare > finalSquare:
                continue gameLoop
            default:
                square += diceRoll
                square += board[square]
            }
        }
        delegate?.gameDidEnd(self)
    }
}

class DiceGameTracker: DiceGameDelegate {
    var numberOfTurns = 0
    func gameDidStart(_ game: DiceGame) {
        numberOfTurns = 0
        if game is SnakesAndLadders {
            print("Started a new game of Snakes and Ladders")
        }
        print("The game is using a \(game.dice.sides)-sided dice")
    }
    func game(_ game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int) {
        numberOfTurns += 1
        print("Rolled a \(diceRoll)")
    }
    func gameDidEnd(_ game: DiceGame) {
        print("The game lasted for \(numberOfTurns) turns")
    }
}

let tracker = DiceGameTracker()
let game = SnakesAndLadders()
game.delegate = tracker
game.play()

//通过扩展遵守某个协议
protocol TextRepresentable {
    var textualDescription: String { get }
}

extension Dice: TextRepresentable {
    var textualDescription: String {
        return "A \(sides)-sided dice"
    }
}

let d12 = Dice(sides: 12, generator: LinearCongruentialGenerator())
print(d12.textualDescription)
// Prints "A 12-sided dice"

extension SnakesAndLadders: TextRepresentable {
    var textualDescription: String {
        return "A game of Snakes and Ladders with \(finalSquare) squares"
    }
}
print(game.textualDescription)

//有条件的遵守协议
extension Array: TextRepresentable where Element: TextRepresentable {
    var textualDescription: String {
        let itemsAsText = self.map { $0.textualDescription }
        return "[" + itemsAsText.joined(separator: ", ") + "]"
    }
}
let myDice = [d6, d12]
print(myDice.textualDescription)

//通过协议适应某种类型
//如果某个类型已经符合协议的所有要求,但尚未声明它采用该协议,则可以使其采用带有空扩展的协议
struct Hamster {
    var name: String
    var textualDescription: String {
        return "A hamster named \(name)"
    }
}
extension Hamster: TextRepresentable {}
let simonTheHamster = Hamster(name: "Simon")
let somethingTextRepresentable: TextRepresentable = simonTheHamster
print(somethingTextRepresentable.textualDescription)
// Prints "A hamster named Simon"

//协议类型的集合
let things: [TextRepresentable] = [game, d12, simonTheHamster]
for thing in things {
    print(thing.textualDescription)
}

//协议继承

还是有点烧脑….

–EOF–

通用代码使您能够根据您定义的要求编写可以使用任何类型的灵活,可重用的函数和类型。您可以编写避免重复的代码,并以清晰,抽象的方式表达其意图。

泛型是Swift最强大的功能之一,Swift标准库的大部分内容都是使用通用代码构建的。

import Foundation

//泛型函数
func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
    let tmp = a
    a = b
    b = tmp
}

var a = 1, b = 2
print("\(a)====\(b)")
swapTwoValues(&a, &b)
print("\(a)====\(b)")

//泛型类型(泛型类,泛型结构体,泛型枚举),听起来挺高大上,其实就是给自定义类加个泛型
struct Stack<Element> {
    var items: [Element] = []
    mutating func push(_ item: Element) {
        items.append(item)
    }
    
    mutating func pop() -> Element {
        return items.removeLast()
    }
}
//扩展泛型类型
extension Stack {
    var topItem: Element? {
        return items.isEmpty ? nil : items[items.count - 1]
    }
}

var strings = Stack<String>()
strings.push("hello")
print(strings.topItem)
print(strings.pop())

//泛型约束(不限于泛型类型,除了泛型类型就是TM的泛型函数)
//泛型约束不能省略,如果省略value == v就不能运行了,没法玩了.
//泛型约束必须是特定类继承,或符合特定协议或协议组合
//这里Equable不能被替换为String,因为String是结构体,不能被继承.Int, Bool, Double, anything else...
//返回值不能用泛型,🙂because the type to use for T is inferred from the types of values passed to the function.
// (因为类型都是从传递给函数的值的类型推断出来的),除非再传一个参数,类似:
// func findIndex1<T: Equatable, S: SignedInteger>(of value: T,in array: [T], _ type: S) -> S?
// 告诉一下Swift,接下来会发生什么,不然Swift心里会发慌...
func findIndex1<T: Equatable>(of value: T,in array: [T]) -> Int? {
    for (i, v) in array.enumerated() {
        if value == v {
            return i
        }
    }
    return nil
}

let arr = ["a", "b", "c", "d", "e"]
let index = findIndex1(of: "a", in: arr)
print(index)


//关联类型
//协议中的泛型,实现具体类型的时候,由自己指定泛型类型为某种具体类型.
protocol Container {
    associatedtype Item
    mutating func append(_ item: Item)
    var count: Int { get }
    subscript(i: Int) -> Item { get }
}

//这里typealias item不能等于协议,例如typealias Item = Equatable
//这样Swift就不知道`EquableStack`应该怎么分配内存了有木有...,谁TM知道`EquableStack`实现了几个协议
//脚踏了几只船?
//typealias Item = Int删掉也可以,可以通过append,推断出Item类型
struct IntStack: Container {
    
    mutating func push(_ item: Item) {
        items.append(item)
    }
    
    mutating func pop() -> Item {
        return items.removeLast()
    }
    
    typealias Item = Int
    var items: [Item] = []
    mutating func append(_ item: Item) {
        items.append(item)
    }
    var count: Int {
        return items.count
    }
    
    subscript(i: Int) -> Item {
        return items[i]
    }
}

//上面的Stack可以写作下面方式
//因为通过append可以知道Element为Item的具体类型,所以typealias可以省略
//又因为Stack1是泛型类型,Element创建实例对象时具体指出,所以,一下代码完全正确.
//可以写typealias Item = Element, 然后Element跟Item可以互相交叉替换🙂
struct Stack1<Element>: Container {
    var items = [Element]()
    mutating func push(_ item: Element) {
        items.append(item)
    }

    mutating func pop() -> Element {
        return items.removeLast()
    }
    //conformance to the Container
    mutating func append(_ item: Element) {
        push(item)
    }
    var count: Int {
        return items.count
    }
    subscript(i: Int) -> Element {
        return items[i]
    }
}

var strings1 = Stack1<String>()
strings.push("hello")
print(strings.topItem)
print(strings.pop())

//扩展现有类型以指定关联类型
//array 中有append用来推断具体类型,并且有count,有下标
//所以以后完全可以使用Array作为Container
//但是typealias Container = Array也是不错的
extension Array: Container {}

//将约束添加到关联类型
//如果这样定义,得像下面这样搞
//struct Stack1<Element: Equatable>: Container
protocol Container1 {
    associatedtype Item: Equatable
    mutating func append(_ item: Item)
    var count: Int { get }
    subscript(i: Int) -> Item { get }
}

//在关联类型的约束中使用协议
//这个JB关系有点乱,有木有...
//儿子有一个家,爹有一个家,儿子从爹那继承过来的家跟自己成立的家必须是一个家,不能搞分家...
//大概就是这样了....
protocol SuffixableContainer: Container {
    associatedtype Suffix: SuffixableContainer where Suffix.Item == Item
    func suffix(_ size: Int) -> Suffix
}

extension Stack1: SuffixableContainer {
    func suffix(_ size: Int) -> Stack1 {
        var result = Stack1()
        //max是用来防止程序崩溃的,🙂
        for index in max((count-size), 0)..<count {
            result.append(self[index])
        }
        return result
    }
    // Inferred that Suffix is Stack.
}

var stackOfInts = Stack1<Int>()
stackOfInts.append(10)
stackOfInts.append(20)
stackOfInts.append(30)
let suffix = stackOfInts.suffix(3)

//Generic Where Clauses(通用条款)
//泛型条件约束吧... where

func allItemsMatch<C1: Container, C2: Container>(_ someContainer: C1, _ anotherContainer: C2) -> Bool where C1.Item == C2.Item, C1.Item: Equatable {
    // Check that both containers contain the same number of items.
    if someContainer.count != anotherContainer.count {
        return false
    }
    // Check each pair of items to see if they're equivalent.
    for i in 0..<someContainer.count {
        if someContainer[i] != anotherContainer[i] {
            return false
        }
    }
    // All items match, so return true.
    return true
}

var stackOfStrings = Stack1<String>()
stackOfStrings.push("uno")
stackOfStrings.push("dos")
stackOfStrings.push("tres")

var arrayOfStrings = ["uno", "dos", "tres"]

if allItemsMatch(stackOfStrings, arrayOfStrings) {
    print("All items match.")
} else {
    print("Not all items match.")
}

extension Stack1 where Element: Equatable {
    func isTop(_ item: Element) -> Bool {
        guard let last = items.last else {
            return false
        }
        return item == last
    }
}
//如果将没有遵守Equatable用于该方法,会报错
if stackOfStrings.isTop("tres") {
    print("Top element is tres.")
} else {
    print("Top element is something else.")
}

//上面where扩展类型,下面where扩展协议,这TM就比较6了...
extension Container where Item: Equatable {
    func startsWith(_ item: Item) -> Bool {
        return count >= 1 && self[0] == item
    }
}
if [9, 9, 9].startsWith(42) {
    print("Starts with 42.")
} else {
    print("Starts with something else.")
}

//Item是特定类型的where子句
extension Container where Item == Double {
    func average() -> Double {
        var sum = 0.0
        for index in 0..<count {
            sum += self[index]
        }
        return sum / Double(count)
    }
}
print([1260.0, 1200.0, 98.6, 37.0].average())


//关联类型和泛型子句
protocol Container2 {
    associatedtype Item
    mutating func append(_ item: Item)
    var count: Int { get }
    subscript(i: Int) -> Item { get }
    
    associatedtype Iterator: IteratorProtocol where Iterator.Element == Item
    
    func makeIterator() -> Iterator
}

protocol ComparableContainer: Container2 where Item: Comparable {}

//泛型下标
extension Container2 {
    subscript<Indices: Sequence>(indices: Indices) -> [Item]
        where Indices.Iterator.Element == Int {
            var result = [Item]()
            for index in indices {
                result.append(self[index])
            }
            return result
    }
}

真是烧脑的玩意……

–EOF–

LLVM:

模块化,可重用的编译器以及工具链技术集合.

创始人: Chris Lattner

LLVM不是Low Level Virtual Machine(低级虚拟机)的缩写,LLVM就是他的项目全名.

传统编译器:

GCC
Clang

传统编译器架构:

ping-mu-kuai-zhao-2018-10-26-xia-wu-9-53-38

  • Frontend: 前端

词法分析,语法分析,语义分析,生成中间代码

  • Opotimizer: 优化器

中间代码优化

  • Backend: 后端

生成机器码

LLVM架构

ping-mu-kuai-zhao-2018-10-26-xia-wu-9-58-59

  • 不同的前端后端使用统一的中间代码 LLVM Intermediate Representation(LLVM IR).
  • 如果需要支持一种新的编程语言,只需要实现一个新的前端.
  • 如果需要支持一种新的硬件设备,只需要增加一个新的后端.
  • 优化阶段是一个通用阶段,它针对的是统一的LLVM IR,无论是支持新的编程语言,还是支持新的硬件设备,都不需要对优化阶段做修改.
  • 相比之下,GCC的前端和后端没分的泰开,前端后端耦合在一起.所以GCC为了来支持一门新的语言或者新的硬件设备,就变得很困难.
  • LLVM现在被用作为实现各种静态和运行时变易语言的通用基础结构.(GCC家族,Java,.net,Python等)

Clang

  • LLVM一个子项目
  • 基于LVVM架构的C/C++/Objective-C编译器前端

优点:

  • 编译速度快,在某些平台上Clang的便以速度显著地快过GCC
  • 占用内存小,Clang生成的AST所占用的内训师CGG的五分之一左右
  • 模块化设计,基于库的模块化设计,易于IDE集成以及其他用途的重用
  • 诊断信息可读性强: 在编译过程中,Clang创建并保留了大量详细的元数据(metadata),有利于调试和错误解读.
  • 设计清晰简单,容易理解,易于扩展增强

Clang与LLVM

ping-mu-kuai-zhao-2018-10-26-xia-wu-10-17-23

  • 广义LLVM

整个LLVM架构

  • 狭义LLVM

LLVM后端(代码优化,目标代码生成等)

ping-mu-kuai-zhao-2018-10-26-xia-wu-10-22-37

OC源文件编译过程

命令行查看编译过程

clang -ccc-print-phases main.m

➜ TestSwift clang -ccc-print-phases main.swift
0: input, "main.swift", object
1: linker, {0}, image
2: bind-arch, "x86_64", {1}, image

➜ TestOC clang -ccc-print-phases main.m
0: input, "main.m", objective-c
1: preprocessor, {0}, objective-c-cpp-output
2: compiler, {1}, ir
3: backend, {2}, assembler
4: assembler, {3}, object
5: linker, {4}, image
6: bind-arch, "x86_64", {5}, image

Swift比OC少了4个编译阶段呐,有木有…

查看preprocessor(预处理)的结果

clang -E main.m

//源文件
print("Hello World")
//预处理输出
➜ TestSwift clang -E main.swift
clang: warning: main.swift: 'linker' input unused [-Wunused-command-line-argument]

//源文件
#define AGE 10

int main(int argc, const char * argv[]) {
    
    int a = 10;
    int b = 20;
    int c = a + b + AGE;
    
    return 0;
}
//预处理输出
➜ TestOC clang -E main.m
# 1 "main.m"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 373 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "main.m" 2
# 11 "main.m"
int main(int argc, const char * argv[]) {

    int a = 10;
    int b = 20;
    int c = a + b + 10;

    return 0;
}

词法分析

  • 词法分析,生成Token(类似英语中主语,谓语,宾语,宾补…)

clang -fmodules -E -Xclang -dump-tokens main.m

➜ TestSwift clang -fmodules -E -Xclang -dump-tokens main.swift
clang: warning: main.swift: 'linker' input unused [-Wunused-command-line-argument]
clang: warning: argument unused during compilation: '-fmodules' [-Wunused-command-line-argument]
clang: warning: argument unused during compilation: '-Xclang -dump-tokens' [-Wunused-command-line-argument]

➜ TestOC clang -fmodules -E -Xclang -dump-tokens main.m
int 'int' [StartOfLine]	Loc=<main.m:11:1>
identifier 'main' [LeadingSpace]	Loc=<main.m:11:5>
l_paren '(' Loc=<main.m:11:9>
int 'int' Loc=<main.m:11:10>
identifier 'argc' [LeadingSpace]	Loc=<main.m:11:14>
comma ',' Loc=<main.m:11:18>
const 'const' [LeadingSpace]	Loc=<main.m:11:20>
char 'char' [LeadingSpace]	Loc=<main.m:11:26>
star '*' [LeadingSpace]	Loc=<main.m:11:31>
identifier 'argv' [LeadingSpace]	Loc=<main.m:11:33>
l_square '[' Loc=<main.m:11:37>
r_square ']' Loc=<main.m:11:38>
r_paren ')' Loc=<main.m:11:39>
l_brace '{' [LeadingSpace]	Loc=<main.m:11:41>
int 'int' [StartOfLine] [LeadingSpace]	Loc=<main.m:13:5>
identifier 'a' [LeadingSpace]	Loc=<main.m:13:9>
equal '=' [LeadingSpace]	Loc=<main.m:13:11>
numeric_constant '10' [LeadingSpace]	Loc=<main.m:13:13>
semi ';' Loc=<main.m:13:15>
int 'int' [StartOfLine] [LeadingSpace]	Loc=<main.m:14:5>
identifier 'b' [LeadingSpace]	Loc=<main.m:14:9>
equal '=' [LeadingSpace]	Loc=<main.m:14:11>
numeric_constant '20' [LeadingSpace]	Loc=<main.m:14:13>
semi ';' Loc=<main.m:14:15>
int 'int' [StartOfLine] [LeadingSpace]	Loc=<main.m:15:5>
identifier 'c' [LeadingSpace]	Loc=<main.m:15:9>
equal '=' [LeadingSpace]	Loc=<main.m:15:11>
identifier 'a' [LeadingSpace]	Loc=<main.m:15:13>
plus '+' [LeadingSpace]	Loc=<main.m:15:15>
identifier 'b' [LeadingSpace]	Loc=<main.m:15:17>
plus '+' [LeadingSpace]	Loc=<main.m:15:19>
numeric_constant '10' [LeadingSpace]	Loc=<main.m:15:21 <Spelling=main.m:9:13>>
semi ';' Loc=<main.m:15:24>
return 'return' [StartOfLine] [LeadingSpace]	Loc=<main.m:17:5>
numeric_constant '0' [LeadingSpace]	Loc=<main.m:17:12>
semi ';' Loc=<main.m:17:13>
r_brace '}' [StartOfLine]	Loc=<main.m:18:1>
eof '' Loc=<main.m:18:2>

语法分析

  • 语法分析,生成语法树(AST, Abstract Syntax Tree)

clang -fmodules -fsyntax-only -Xclang -ast-dump main.m

➜ Test clang -fmodules -fsyntax-only -Xclang -ast-dump main.swift
clang: warning: main.swift: 'linker' input unused [-Wunused-command-line-argument]
clang: warning: argument unused during compilation: '-fmodules' [-Wunused-command-line-argument]
clang: warning: argument unused during compilation: '-Xclang -ast-dump' [-Wunused-command-line-argument]

➜ TestOC clang -fmodules -fsyntax-only -Xclang -ast-dump main.m
TranslationUnitDecl 0x7ff3730298e8 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0x7ff373029e60 <<invalid sloc>> <invalid sloc> implicit __int128_t '__ int128'
| `-BuiltinType 0x7ff373029b80 '__int128'
|-TypedefDecl 0x7ff373029ed0 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned__ int128'
| `-BuiltinType 0x7ff373029ba0 'unsigned __int128'
|-TypedefDecl 0x7ff373029f70 <<invalid sloc>> <invalid sloc> implicit SEL 'SEL *'
| `-PointerType 0x7ff373029f30 'SEL *'
| `-BuiltinType 0x7ff373029dc0 'SEL'
|-TypedefDecl 0x7ff37302a058 <<invalid sloc>> <invalid sloc> implicit id 'id'
| `-ObjCObjectPointerType 0x7ff37302a000 'id'
| `-ObjCObjectType 0x7ff373029fd0 'id'
|-TypedefDecl 0x7ff37302a138 <<invalid sloc>> <invalid sloc> implicit Class 'Class'
| `-ObjCObjectPointerType 0x7ff37302a0e0 'Class'
| `-ObjCObjectType 0x7ff37302a0b0 'Class'
|-ObjCInterfaceDecl 0x7ff37302a190 <<invalid sloc>> <invalid sloc> implicit Protocol
|-TypedefDecl 0x7ff37302a4f8 <<invalid sloc>> <invalid sloc> implicit __NSConstantString 'struct__ NSConstantString_tag'
| `-RecordType 0x7ff37302a300 'struct __NSConstantString_tag'
| `-Record 0x7ff37302a260 '__NSConstantString_tag'
|-TypedefDecl 0x7ff37302a590 <<invalid sloc>> <invalid sloc> implicit __builtin_ms_va_list 'char *'
| `-PointerType 0x7ff37302a550 'char *'
| `-BuiltinType 0x7ff373029980 'char'
|-TypedefDecl 0x7ff373062488 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list 'struct__ va_list_tag [1]'
| `-ConstantArrayType 0x7ff373062430 'struct __va_list_tag [1]' 1
| `-RecordType 0x7ff3730622a0 'struct __va_list_tag'
| `-Record 0x7ff373062200 '__va_list_tag'
`-FunctionDecl 0x7ff373062758 <main.m:11:1, line:18:1> line:11:5 main 'int (int, const char **)'
  |-ParmVarDecl 0x7ff3730624f8 <col:10, col:14> col:14 argc 'int'
  |-ParmVarDecl 0x7ff373062610 <col:20, col:38> col:33 argv 'const char **':'const char**'
  `-CompoundStmt 0x7ff373062bd8 <col:41, line:18:1>
    |-DeclStmt 0x7ff373062928 <line:13:5, col:15>
    | `-VarDecl 0x7ff3730628a8 <col:5, col:13> col:9 used a 'int' cinit
    | `-IntegerLiteral 0x7ff373062908 <col:13> 'int' 10
    |-DeclStmt 0x7ff3730629d8 <line:14:5, col:15>
    | `-VarDecl 0x7ff373062958 <col:5, col:13> col:9 used b 'int' cinit
    | `-IntegerLiteral 0x7ff3730629b8 <col:13> 'int' 20
    |-DeclStmt 0x7ff373062b88 <line:15:5, col:24>
    | `-VarDecl 0x7ff373062a08 <col:5, line:9:13> line:15:9 c 'int' cinit
    | `-BinaryOperator 0x7ff373062b60 <col:13, line:9:13> 'int' '+'
    | |-BinaryOperator 0x7ff373062b18 <line:15:13, col:17> 'int' '+'
    | | |-ImplicitCastExpr 0x7ff373062ae8 <col:13> 'int' <LValueToRValue>
    | | | `-DeclRefExpr 0x7ff373062a68 <col:13> 'int' lvalue Var 0x7ff3730628a8 'a' 'int'
    | | `-ImplicitCastExpr 0x7ff373062b00 <col:17> 'int' <LValueToRValue>
    | | `-DeclRefExpr 0x7ff373062aa8 <col:17> 'int' lvalue Var 0x7ff373062958 'b' 'int'
    | `-IntegerLiteral 0x7ff373062b40 <line:9:13> 'int' 10
    `-ReturnStmt 0x7ff373062bc0 <line:17:5, col:12>
      `-IntegerLiteral 0x7ff373062ba0 <col:12> 'int' 0

LLVM IR

LLVM IR有三种表示形式(本质等价,好比水的气态,液态,固态)

1.text: 便于阅读的文本格式,类似于汇编语言,扩展名.ll

> clang -S -emit-llvm main.m

; ModuleID = 'main.m'
source_filename = "main.m"
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.14.0"

; Function Attrs: noinline nounwind optnone ssp uwtable
define i32 @main(i32, i8**) #0 {
  %3 = alloca i32, align 4
  %4 = alloca i32, align 4
  %5 = alloca i8**, align 8
  %6 = alloca i32, align 4
  %7 = alloca i32, align 4
  %8 = alloca i32, align 4
  store i32 0, i32* %3, align 4
  store i32 %0, i32* %4, align 4
  store i8 **%1, i8*** %5, align 8
  store i32 10, i32* %6, align 4
  store i32 20, i32* %7, align 4
  %9 = load i32, i32* %6, align 4
  %10 = load i32, i32* %7, align 4
  %11 = add nsw i32 %9, %10
  %12 = add nsw i32 %11, 10
  store i32 %12, i32* %8, align 4
  ret i32 0
}

attributes #0 = { noinline nounwind optnone ssp uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6}
!llvm.ident = !{!7}

!0 = !{i32 1, !"Objective-C Version", i32 2}
!1 = !{i32 1, !"Objective-C Image Info Version", i32 0}
!2 = !{i32 1, !"Objective-C Image Info Section", !" __DATA,__ objc_imageinfo,regular,no_dead_strip"}
!3 = !{i32 4, !"Objective-C Garbage Collection", i32 0}
!4 = !{i32 1, !"Objective-C Class Properties", i32 64}
!5 = !{i32 1, !"wchar_size", i32 4}
!6 = !{i32 7, !"PIC Level", i32 2}
!7 = !{!"Apple LLVM version 10.0.0 (clang-1000.11.45.2)"}
//什么鬼东西

2.memory: 内存格式
3.bitcode: 二进制格式,扩展名.bc

clang -c -emit-llvm main.m

IR基本语法

  • 注释以分号;开头
  • 全局标识符以@开头,局部标识符以%开头
  • alloca在当前函数栈帧中分配内存
  • i32,32bit,4个字节的意思
  • align,内存对齐
  • store,写入数据
  • load,读取数据

–EOF–

–EOF–