美文网首页
Objective-C代码转为带有ARC代码的C++代码

Objective-C代码转为带有ARC代码的C++代码

作者: 传说中的汽水枪 | 来源:发表于2019-07-08 12:15 被阅读0次

在《Objective-C高级编程iOS与OS X多线程和内存管理》这本书里经常有如下的Demo:

    @autoreleasepool {
        id __autoreleasing obj = [[NSObject alloc] init];
    }

编译器模拟代码:

id pool = objc_autoreleasePoolPush();
id obj = objc_msgSend(NSObject, @selector(alloc));
objc_msgSend(obj, @selector(init));
objc_autorelease(obj);
objc_autoreleasePoolPop(pool);

那么问题来了:该模拟代码是如何得到了?
查看Stack Overflow发现有一个类似的问题:
https://stackoverflow.com/questions/33950466/how-to-translate-objective-c-code-to-c-with-arc-enabling?answertab=oldest#tab-top

但是现在是无法好使了。
尝试了如下的两个命令:

clang -x objective-c -arch x86_64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk -rewrite-objc -fobjc-arc -mmacosx-version-min=10.14.5  -fobjc-runtime=macosx-10.14.5 -O0  second.m
clang -x objective-c -arch arm64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator12.2.sdk -rewrite-objc -fobjc-arc -fblocks -mmacosx-version-min=10.14.5  -fobjc-runtime=macosx-10.14.5 -O0

依然不好用。

然后在这篇文章发现如下的命令:

clang -S -fobjc-arc -emit-llvm first.m -o first2.ll 

上述的代码就会转换为如下:

  %3 = alloca i32, align 4
  %4 = alloca i8**, align 8
  %5 = alloca i8*, align 8
  store i32 %0, i32* %3, align 4
  store i8** %1, i8*** %4, align 8
  %6 = call i8* @objc_autoreleasePoolPush() #3
  %7 = load %struct._class_t*, %struct._class_t** @"OBJC_CLASSLIST_REFERENCES_$_.6", align 8
  %8 = load i8*, i8** @OBJC_SELECTOR_REFERENCES_, align 8, !invariant.load !9
  %9 = bitcast %struct._class_t* %7 to i8*
  %10 = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* %9, i8* %8)
  %11 = bitcast i8* %10 to %1*
  %12 = load i8*, i8** @OBJC_SELECTOR_REFERENCES_.2, align 8, !invariant.load !9
  %13 = bitcast %1* %11 to i8*
  %14 = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* %13, i8* %12)
  %15 = bitcast i8* %14 to %1*
  %16 = bitcast %1* %15 to i8*
  %17 = call i8* @objc_autorelease(i8* %16) #3
  store i8* %17, i8** %5, align 8
  call void @objc_autoreleasePoolPop(i8* %6)

里面的代码跟结果代码一直,应该就是这个命令然后简化一下得到模拟代码了。

还有一个优化后的命令:

clang -O3 -S -fobjc-arc -emit-llvm first.m -o first.ll

得到的代码如下:

  %3 = tail call i8* @objc_autoreleasePoolPush() #4
  %4 = load i8*, i8** bitcast (%struct._class_t** @"OBJC_CLASSLIST_REFERENCES_$_.6" to i8**), align 8
  %5 = load i8*, i8** @OBJC_SELECTOR_REFERENCES_, align 8, !invariant.load !9
  %6 = tail call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* %4, i8* %5), !clang.arc.no_objc_arc_exceptions !9
  %7 = load i8*, i8** @OBJC_SELECTOR_REFERENCES_.2, align 8, !invariant.load !9
  %8 = tail call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* %6, i8* %7), !clang.arc.no_objc_arc_exceptions !9
  call void @objc_release(i8* %8) #4, !clang.imprecise_release !9
  tail call void @objc_autoreleasePoolPop(i8* %3) #4, !clang.arc.no_objc_arc_exceptions !9

翻译成模拟代码如下:

id pool = objc_autoreleasePoolPush();
id obj = objc_msgSend(NSObject, @selector(alloc));
objc_msgSend(obj, @selector(init));
objc_release(obj);
objc_autoreleasePoolPop(pool);

objc_autorelease(obj);优化为objc_release(obj);这里完全是正确的!

相关文章

网友评论

      本文标题:Objective-C代码转为带有ARC代码的C++代码

      本文链接:https://www.haomeiwen.com/subject/swlohctx.html