Como fazer clang compilar para llvm IR

150

Eu quero que o clang compile meu C/C++código em LLVMbytecode, em vez de executável binário. Como posso conseguir isso? E se eu obtiver o LLVMbytecode, como posso levá-lo para compilá-lo ainda mais no executável binário.

Basicamente, quero adicionar um pouco do meu próprio código ao LLVMbytecode antes de compilar no executável binário.

pitônico
fonte
Eu acho que ele é chamado como bitcode LLVM
PreeJackie

Respostas:

204

Dado algum arquivo C / C ++ foo.c:

> clang -S -emit-llvm foo.c

Produz foo.llum arquivo IR LLVM.

A -emit-llvmopção também pode ser passada diretamente para o front-end do compilador e não para o driver por meio de -cc1:

> clang -cc1 foo.c -emit-llvm

Produz foo.llcom o IR. -cc1adiciona algumas opções legais como -ast-print. Confira -cc1 --helppara mais detalhes.


Para compilar o LLVM IR ainda mais na montagem, use a llcferramenta:

> llc foo.ll

Produz foo.scom montagem (por padrão, na arquitetura da máquina em que você a executa). llcé uma das ferramentas do LLVM - aqui está sua documentação .

Eli Bendersky
fonte
7
O que -S faz aqui?
27414
13
@meawoppl: -S como no gcc diz emitem textual montagem em vez de montado binário
Eli Bendersky
Ahha. Eu estava tendo dificuldade para encontrar algo nos documentos sobre isso. É seguro supor que muitas bandeiras na estrutura de bandeira clang mirror gcc?
28414
@EliBendersky Você sabe compilar vários arquivos .c e .h em um IR legível por humanos, para que eu possa executar o IR usando 'lli theIrFile'? Obrigado
cache
1
@cache: compilar cada um em seu próprio arquivo de IR e, em seguida, usar o vinculador LLVM para combinar
Eli Bendersky
20

Usar

clang -emit-llvm -o foo.bc -c foo.c
clang -o foo foo.bc
Christoph
fonte
9
Eu recomendo manter intactos os significados das extensões. IOW, .odeve se referir a arquivos de objetos binários, arquivos .sde montagem e algo mais (por convenção .ll) a arquivos IR do LLVM. Caso contrário, é fácil ficar confuso. O Clang / LLVM agora não possui vinculador próprio para objetos binários (embora um esteja em andamento). O vinculador LLVM llvm-ldapenas junta vários arquivos de IR em um
Eli Bendersky
1
@ EliBendersky: você está correto no que diz respeito às extensões de arquivo - e o front-end do clang realmente faz a coisa certa se .bcfor usado; Além disso, mantenha em mente que llvm-ldpode atuar como interface para o conjunto de ferramentas do sistema, ou seja, a minha resposta anterior usando llvm-ld -nativedeve funcionar como esperado ....
Christoph
1
@rickfoosusa: funciona para mim - foo.bcé um arquivo de código de bits LLVM #
Christoph
1
Funciona para mim: clang -emit-llvm -o test.bc -c test.c && file test.bc: test.bc: LLVM IR bitcode.
Ntc2 12/04/19
18

Se você possui vários arquivos de origem, provavelmente deseja usar a otimização do tempo do link para gerar um arquivo de código de bits para todo o programa. As outras respostas fornecidas farão com que você termine com um arquivo de código de bit para cada arquivo de origem.

Em vez disso, você deseja compilar com a otimização do tempo do link

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

e para a etapa final de vinculação, inclua o argumento -Wl, -plugin-opt = also-emit-llvm

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

Isto dá-lhe tanto um programa compilado eo bitcode correspondente a ele (program.bc). Você pode modificar o program.bc da maneira que desejar e recompilar o programa modificado a qualquer momento, executando

clang program.bc -o program

embora esteja ciente de que você precisa incluir todos os sinalizadores de vinculador necessários (para bibliotecas externas, etc.) nesta etapa novamente.

Observe que você precisa usar o vinculador dourado para que isso funcione. Se você deseja forçar o clang a usar um vinculador específico, crie um link simbólico para esse vinculador chamado "ld" em um diretório especial chamado "fakebin" em algum lugar do seu computador e adicione a opção

-B/home/jeremy/fakebin

a todas as etapas de vinculação acima.

Jeremy Salwen
fonte
13

Se você possui vários arquivos e não deseja digitar cada arquivo, recomendo que você siga estas etapas simples (estou usando, clang-3.8mas você pode usar qualquer outra versão):

  1. gerar todos os .llarquivos

    clang-3.8 -S -emit-llvm *.c
  2. ligá-los em um único

    llvm-link-3.8 -S -v -o single.ll *.ll
  3. (Opcional) Otimize seu código (talvez alguma análise de alias)

    opt-3.8 -S -O3 -aa -basicaaa -tbaa -licm single.ll -o optimised.ll
  4. Gerar montagem (gera um optimised.sarquivo)

    llc-3.8 optimised.ll
  5. Criar executável (nomeado a.out)

    clang-3.8 optimised.s
Kiko Fernandez
fonte
Sua solução é única: você usou "-S" em vez de apenas deixá-lo como saída binária. Existe alguma diferença entre ter "-S" e não ter "-S"?
Peter Teoh
@PeterTeoh Eu uso a -Sopção (na etapa 2), especifiquei que gostaria de produzir a saída no LLVM IR. Basicamente, coloque todos os arquivos * .ll em um único. Faço isso para verificar se as otimizações realmente alteram o código, ou seja, single.lle optimised.llagora devem parecer diferentes (em termos de código) e você também pode mostrar o relatório para ver se há alguma diferença.
Kiko Fernandez
-basicaaaé uma bandeira errada, -basicaadeve ser usada.
anton_rh 14/07/19