clang을 llvm IR로 컴파일하는 방법


150

clang이 C/C++코드를 LLVM이진 실행 파일이 아닌 바이트 코드 로 컴파일하기를 원합니다 . 어떻게하면 되나요? 그리고 LLVM바이트 코드를 얻는다면 바이너리 실행 파일로 추가 컴파일하기 위해 어떻게 취할 수 있습니까?

기본적으로 LLVM바이너리 실행 파일로 컴파일하기 전에 자체 코드 중 일부를 바이트 코드에 추가하고 싶습니다 .


나는 그것이 LLVM의 비트 코드로라고 생각
PreeJackie

답변:


204

C / C ++ 파일이 있습니다 foo.c.

> clang -S -emit-llvm foo.c

생산 foo.llLLVM IR 파일이다.

-emit-llvm옵션은 다음과 같은 방법으로 드라이버가 아닌 컴파일러 프런트 엔드로 직접 전달 될 수도 있습니다 -cc1.

> clang -cc1 foo.c -emit-llvm

foo.llIR로 제작 합니다. -cc1과 같은 멋진 옵션을 추가합니다 -ast-print. -cc1 --help자세한 내용을 확인 하십시오.


LLVM IR을 어셈블리로 추가 컴파일하려면 다음 llc도구를 사용하십시오 .

> llc foo.ll

foo.s어셈블리로 생산합니다 (기본값은 기계 아키텍처를 실행 함). llcLLVM 도구 중 하나입니다 . 여기에 해당 문서가 있습니다.


7
-S는 여기서 무엇을합니까?
meawoppl

13
@meawoppl : GCC는 말한다에 같이 -S 개의 발광 텍스트 조립이 아닌 바이너리 조립
엘리 Bendersky

아하 나는 그것에 대해 문서에서 무엇인가를 찾는 데 어려움을 겪고있었습니다. clang 미러 gcc 플래그 구조의 많은 플래그를 가정하는 것이 안전합니까?
meawoppl

@EliBendersky 'lli theIrFile'을 사용하여 IR을 실행할 수 있도록 여러 개의 .c 및 .h 파일을 사람이 읽을 수있는 IR로 컴파일하는 방법을 알고 있습니까? 감사합니다
캐시

1
@cache : 각각을 자체 IR 파일로 컴파일 한 다음 LLVM 링커를 사용하여 결합
Eli Bendersky

20

사용하다

clang -emit-llvm -o foo.bc -c foo.c
clang -o foo foo.bc

9
확장 의미를 그대로 유지하는 것이 좋습니다. IOW .o는 이진 객체 파일, .s어셈블리 파일 및 .llLLVM IR 파일에 대한 다른 규칙을 참조해야합니다. 그렇지 않으면 혼동되기 쉽습니다. Clang / LLVM에는 이제 바이너리 객체에 대한 자체 링커가 없습니다 (하나는 작품에 있습니다). LLVM 링커 llvm-ld는 여러 IR 파일을 하나로 결합합니다
Eli Bendersky

1
@EliBendersky : 파일 확장자가 관련된 정확한 위치입니다. clang 프론트 엔드가 실제로 .bc사용 되면 올바른 일을합니다 . 또한 llvm-ld시스템 툴체인의 프론트 엔드 역할 을 할 수 있음을 명심 하십시오. 예를 들어, 이전의 답변 llvm-ld -native은 예상대로 작동해야합니다 ....
Christoph

1
@rickfoosusa : 저에게 효과적입니다 – foo.bcLLVM 비트 코드 파일입니다
Christoph

1
나를 위해 작동합니다 clang -emit-llvm -o test.bc -c test.c && file test.bc: test.bc: LLVM IR bitcode.
ntc2

18

소스 파일이 여러 개인 경우 실제로 링크 시간 최적화를 사용하여 전체 프로그램에 대해 하나의 비트 코드 파일을 출력하려고합니다. 주어진 다른 답변은 모든 소스 파일에 대한 비트 코드 파일로 끝납니다.

대신 링크 시간 최적화를 사용하여 컴파일하려고합니다.

clang -flto -c program1.c -o program1.o
clang -flto -c program2.c -o program2.o

최종 연결 단계에서 -Wl, -plugin-opt = also-emit-llvm 인수를 추가하십시오.

clang -flto -Wl,-plugin-opt=also-emit-llvm program1.o program2.o -o program

이것은 당신에게주는 모두 컴파일 된 프로그램과 (program.bc)에 해당하는 비트 코드를. 그런 다음 원하는 방식으로 program.bc를 수정하고 언제든지 수정 된 프로그램을 다시 컴파일 할 수 있습니다.

clang program.bc -o program

이 단계에서 필요한 링커 플래그 (외부 라이브러리 등)를 다시 포함해야합니다.

이 작업을하려면 골드 링커를 사용해야합니다. clang이 특정 링커를 사용하도록하려면 컴퓨터의 "fakebin"이라는 특수 디렉토리에 "ld"라는 링커에 대한 심볼릭 링크를 작성하고 옵션을 추가하십시오.

-B/home/jeremy/fakebin

위의 모든 연결 단계


13

여러 파일이 있고 각 파일을 입력하지 않으려면 다음과 같은 간단한 단계를 따르는 것이 좋습니다 (사용 clang-3.8중이지만 다른 버전을 사용할 수 있음).

  1. 모든 .ll파일을 생성

    clang-3.8 -S -emit-llvm *.c
  2. 그것들을 하나의 것으로 연결

    llvm-link-3.8 -S -v -o single.ll *.ll
  3. (선택 사항) 코드 최적화 (일부 별칭 분석 일 수 있음)

    opt-3.8 -S -O3 -aa -basicaaa -tbaa -licm single.ll -o optimised.ll
  4. 어셈블리 생성 ( optimised.s파일 생성 )

    llc-3.8 optimised.ll
  5. 실행 파일 만들기 ( a.out)

    clang-3.8 optimised.s

귀하의 솔루션은 매우 독특합니다. 이진 출력으로 그대로 두지 않고 "-S"를 사용했습니다. "-S"와 "-S"의 차이점은 무엇입니까?
피터 테오

@PeterTeoh -S옵션 (2 단계)을 사용하고 LLVM IR에서 출력을 생성하도록 지정합니다. 기본적으로 모든 * .ll 파일을 단일 파일에 넣습니다. 최적화가 실제로 코드를 변경하는지 확인하기 위해이 작업을 수행합니다. 즉 single.ll, optimised.ll코드가 다르게 보일 수 있으며 보고서에 차이가 있는지 확인할 수도 있습니다.
키코 페르난데스

-basicaaa잘못된 플래그이므로 -basicaa대신 사용해야합니다.
anton_rh

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.