2016-09-18 4 views
1

LLVM 패스에서 Polymorphic 클래스인지 아닌지를 구별하는 것에 대한 질문이 있습니다.LLVM PASS에서 비 다형성과 다형성 클래스를 구별하는 방법은 무엇입니까?

나는 clang에서 비 다형성과 다형성 클래스를 쉽게 구별 할 수 있다고 생각합니다.

그러나 LLVM 패스에서이 작업을 수행하는 방법을 알지 못합니다.

또한 아래 링크를 검색했습니다. 그러나 유용한 기능을 찾지 못했습니다.

당신이 줄 수 나에게 대답 어떻게 다형성 클래스인지 여부 StructType를 구별?

 
For example, In the LLVM Pass, 

Type *AI 
......... 
StructType *STy = dyn_cast(AI) 
(question) How to check whether STy is polymorphic class ?? 
.........`` 

답변

2

TLDR : 당신은 할 수 없습니다 .LLVM 클래스에 대한 지식이 없습니다. Clang은 그것들을 구조체로 낮추었습니다. 어느 시점에서 구조체와 실제로 다르지 않습니다.

당신은 패턴 그것은 vtable을 가지고 있다는 사실과 일치 할 수 있습니다 :

struct MyClass { 
    virtual void foo() {} 
}; 
void bar(MyClass &C) { C.foo(); } 

IR이 포함 %class.MyClass = type { i32 (...)** }

주이 파일이 MyClass의 인스턴스를하지 않기 때문에, 테이블이 너무 방출되지 않도록를 너는 그것을 검사 할 수 없다. 소스가 이런 식으로 변경되는 경우,

define linkonce_odr void @_ZN7MyClassC2Ev(%struct.MyClass*) unnamed_addr #1 align 2 { %2 = alloca %struct.MyClass*, align 8 store %struct.MyClass* %0, %struct.MyClass** %2, align 8 %3 = load %struct.MyClass*, %struct.MyClass** %2, align 8 %4 = bitcast %struct.MyClass* %3 to i32 (...)*** store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV7MyClass, i64 0, i64 2) to i32 (...)**), i32 (...)*** %4, align 8 ret void }

이 최적화가 가능하지만 함께 : 초기화

%struct.MyClass = type { i32 (...)** } 

@C = global %struct.MyClass zeroinitializer, align 8 
@_ZTV7MyClass = linkonce_odr unnamed_addr constant [3 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI7MyClass to i8*), i8* bitcast (void (%struct.MyClass*)* @_ZN7MyClass3fooEv to i8*)], align 8 
@_ZTVN10__cxxabiv117__class_type_infoE = external global i8* 
@_ZTS7MyClass = linkonce_odr constant [9 x i8] c"7MyClass\00" 
@_ZTI7MyClass = linkonce_odr constant { i8*, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv117__class_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @_ZTS7MyClass, i32 0, i32 0) } 
@llvm.global_ctors = appending global [1 x { i32, void()*, i8* }] [{ i32, void()*, i8* } { i32 65535, void()* @_GLOBAL__sub_I_class.cpp, i8* null }] 

그리고 나중에 생성자 :

struct MyClass { 
    virtual void foo() {} 
}; 
MyClass C; 
void bar() { C.foo(); } 

지금 당신은 vtable을 얻을 이 모든 것이 사라집니다.

또한 ABI에만 해당됩니다 (예 : Windows 및 Linux에서는 동일하게 보이지 않음)