Comment faire une compilation de clang vers llvm IR

150

Je veux que clang compile mon C/C++code en LLVMbytecode plutôt qu'en exécutable binaire. Comment puis-je y parvenir? Et si j'obtiens le LLVMbytecode, comment puis-je l'utiliser pour le compiler davantage en exécutable binaire.

En gros, je veux ajouter une partie de mon propre code au LLVMbytecode avant de compiler en exécutable binaire.

pythonique
la source
Je suppose que cela s'appelle le bitcode LLVM
PreeJackie

Réponses:

204

Étant donné un fichier C / C ++ foo.c:

> clang -S -emit-llvm foo.c

Produit foo.llqui est un fichier LLVM IR.

L' -emit-llvmoption peut également être transmise directement au front-end du compilateur, et non au pilote au moyen de -cc1:

> clang -cc1 foo.c -emit-llvm

Produit foo.llavec l'IR. -cc1ajoute des options intéressantes comme -ast-print. Consultez -cc1 --helppour plus de détails.


Pour compiler LLVM IR suite à l'assemblage, utilisez l' llcoutil:

> llc foo.ll

Produit foo.savec l'assemblage (par défaut, l'architecture de la machine sur laquelle vous l'exécutez). llcest l'un des outils LLVM - voici sa documentation .

Eli Bendersky
la source
7
Que fait -S ici?
meawoppl
13
@meawoppl: -S comme dans gcc dit d'émettre un assemblage textuel plutôt qu'un binaire assemblé
Eli Bendersky
Ahha. J'avais du mal à trouver quoi que ce soit dans la documentation à ce sujet. Il est prudent de supposer que de nombreux indicateurs dans la structure des indicateurs clang mirror gcc?
meawoppl
@EliBendersky Savez-vous comment compiler plusieurs fichiers .c et .h en un seul IR lisible par l'homme afin que je puisse exécuter l'IR en utilisant «lli theIrFile»? Merci
cache le
1
@cache: compilez chacun dans son propre fichier IR, puis utilisez l'éditeur de liens LLVM pour combiner
Eli Bendersky
20

Utilisation

clang -emit-llvm -o foo.bc -c foo.c
clang -o foo foo.bc
Christoph
la source
9
Je recommanderais de garder les significations des extensions intactes. IOW, .odevrait faire référence aux fichiers d'objets binaires, .saux fichiers d'assemblage et autre chose (par convention .ll) aux fichiers LLVM IR. Sinon, il est facile de se tromper. Clang / LLVM n'ont plus d'éditeur de liens pour les objets binaires (bien qu'il y en ait un en préparation). L'éditeur de liens LLVM llvm-ldjoint simplement plusieurs fichiers IR en un seul
Eli Bendersky
1
@EliBendersky: vous avez raison en ce qui concerne les extensions de fichiers - et le frontend clang fait ce qu'il faut s'il .bcest utilisé; aussi, gardez à l'esprit que cela llvm-ldpeut servir d'interface pour la chaîne d'outils système, c'est-à-dire que ma réponse précédente en utilisant llvm-ld -nativedevrait fonctionner comme prévu ....
Christoph
1
@rickfoosusa: fonctionne pour moi - foo.bcest un fichier bitcode LLVM
Christoph
1
Fonctionne pour moi: clang -emit-llvm -o test.bc -c test.c && file test.bc: test.bc: LLVM IR bitcode.
ntc2
18

Si vous avez plusieurs fichiers source, vous souhaitez probablement utiliser l'optimisation du temps de liaison pour générer un fichier bitcode pour l'ensemble du programme. Les autres réponses données vous feront vous retrouver avec un fichier bitcode pour chaque fichier source.

Au lieu de cela, vous souhaitez compiler avec l'optimisation du temps de liaison

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

et pour la dernière étape de liaison, ajoutez l'argument -Wl, -plugin-opt = also-emit-llvm

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

Cela vous donne à la fois un programme compilé et le bitcode correspondant (program.bc). Vous pouvez ensuite modifier program.bc comme vous le souhaitez et recompiler le programme modifié à tout moment en faisant

clang program.bc -o program

mais sachez que vous devez inclure à nouveau tous les indicateurs de l'éditeur de liens nécessaires (pour les bibliothèques externes, etc.) à cette étape.

Notez que vous devez utiliser l'éditeur de liens Gold pour que cela fonctionne. Si vous voulez forcer clang à utiliser un éditeur de liens spécifique, créez un lien symbolique vers cet éditeur nommé "ld" dans un répertoire spécial appelé "fakebin" quelque part sur votre ordinateur, et ajoutez l'option

-B/home/jeremy/fakebin

à toutes les étapes de liaison ci-dessus.

Jeremy Salwen
la source
13

Si vous avez plusieurs fichiers et que vous ne voulez pas avoir à taper chaque fichier, je vous recommande de suivre ces étapes simples (j'utilise clang-3.8mais vous pouvez utiliser n'importe quelle autre version):

  1. générer tous les .llfichiers

    clang-3.8 -S -emit-llvm *.c
  2. liez-les en un seul

    llvm-link-3.8 -S -v -o single.ll *.ll
  3. (Facultatif) Optimisez votre code (peut-être une analyse d'alias)

    opt-3.8 -S -O3 -aa -basicaaa -tbaa -licm single.ll -o optimised.ll
  4. Générer l'assemblage (génère un optimised.sfichier)

    llc-3.8 optimised.ll
  5. Créer un exécutable (nommé a.out)

    clang-3.8 optimised.s
Kiko Fernandez
la source
Votre solution est tout à fait unique: vous avez utilisé "-S" au lieu de simplement le laisser en sortie binaire. Y a-t-il une différence entre avoir "-S" et ne pas avoir "-S"?
Peter Teoh
@PeterTeoh J'utilise l' -Soption (à l'étape 2), je précise que je souhaite produire la sortie en LLVM IR. Fondamentalement, mettez tous les fichiers * .ll en un seul. Je fais cela pour vérifier que les optimisations changent vraiment le code, c'est-à single.ll- dire et optimised.lldevraient maintenant avoir un aspect différent (au niveau du code) et vous pouvez également afficher le rapport pour voir s'il y a une différence.
Kiko Fernandez
-basicaaaest un mauvais drapeau, -basicaadoit être utilisé à la place.
anton_rh