如何直接从 LLVM 源代码树使用新编译的 LLVM 工具?
How do I use a freshly compiled LLVM tool directly from LLVM source tree?
我正在编写一个针对 X86 体系结构的 MachineFunctionPass
,它会生成修改后的 llc
二进制文件。
为了测试我修改后的 llc
版本,我创建了一堆 .c
程序,它们的 MIR 将由我的 pass 处理。
为了简洁起见,我将包含源代码的目录直接添加到 LLVM 的源代码树中,特别是在 $llvm_src_dir/lib/Target/X86/$examples_dir
中:然后我通过附加 add_subdirectory()
将其插入 LLVM 构建系统指令 $llvm_src_dir/lib/Target/X86/CMakeLists.txt
.
通过这种方式,我将能够直接从 LLVM 的构建目录构建所有内容。
现在:我如何在 $examples_dir/CMakeLists.txt
中指定使用 LLVM 的 in-tree llc
?
源代码树结构
这是资源的目录结构。我省略了所有根目录的子目录,因为我只包含了 "interesting ones".
LLVM 在 tools/llc
中定义了 llc
目标,而我的源代码位于目录的更深处,如下面的树所示:
llvm_src_dir
├── bindings
├── cmake
├── docs
├── examples
├── include
├── lib
└── Target
└── X86
/*
* My git repo is here. LLVM's and
* my MachineFunctionPass' files
* live here
*/
├── .git
├── CMakeLists.txt // This is LLVM's X86 CMakeLists.txt
└── examples
└── CMakeLists.txt // My CMakeLists.txt
├── projects
├── resources
├── runtimes
├── test
├── tools
└── llc
└── CMakeLists.txt // this is where LLVM's llc target is defined
├── unittests
└── utils
lib/Target/X86/CMakeLists.txt
这就是我编辑目标架构 CMakeLists.txt
的方式:
set (CMAKE_CXX_STANDARD 14)
set(LLVM_TARGET_DEFINITIONS X86.td)
tablegen(LLVM X86GenAsmMatcher.inc -gen-asm-matcher)
tablegen(LLVM X86GenAsmWriter.inc -gen-asm-writer)
tablegen(LLVM X86GenAsmWriter1.inc -gen-asm-writer -asmwriternum=1)
tablegen(LLVM X86GenCallingConv.inc -gen-callingconv)
tablegen(LLVM X86GenDAGISel.inc -gen-dag-isel)
tablegen(LLVM X86GenDisassemblerTables.inc -gen-disassembler)
tablegen(LLVM X86GenEVEX2VEXTables.inc -gen-x86-EVEX2VEX-tables)
tablegen(LLVM X86GenFastISel.inc -gen-fast-isel)
tablegen(LLVM X86GenGlobalISel.inc -gen-global-isel)
tablegen(LLVM X86GenInstrInfo.inc -gen-instr-info)
tablegen(LLVM X86GenRegisterBank.inc -gen-register-bank)
tablegen(LLVM X86GenRegisterInfo.inc -gen-register-info)
tablegen(LLVM X86GenSubtargetInfo.inc -gen-subtarget)
if (X86_GEN_FOLD_TABLES)
tablegen(LLVM X86GenFoldTables.inc -gen-x86-fold-tables)
endif ()
add_public_tablegen_target(X86CommonTableGen)
set(MY_SOURCES
a.cpp
b.cpp
c.cpp
)
set(sources
ShadowCallStack.cpp
X86AsmPrinter.cpp
X86CallFrameOptimization.cpp
X86CallingConv.cpp
X86CallLowering.cpp
X86CmovConversion.cpp
X86DomainReassignment.cpp
X86ExpandPseudo.cpp
X86FastISel.cpp
X86FixupBWInsts.cpp
X86FixupLEAs.cpp
X86AvoidStoreForwardingBlocks.cpp
X86FixupSetCC.cpp
X86FlagsCopyLowering.cpp
X86FloatingPoint.cpp
X86FrameLowering.cpp
X86InstructionSelector.cpp
X86ISelDAGToDAG.cpp
X86ISelLowering.cpp
X86IndirectBranchTracking.cpp
X86InterleavedAccess.cpp
X86InstrFMA3Info.cpp
X86InstrFoldTables.cpp
X86InstrInfo.cpp
X86EvexToVex.cpp
X86LegalizerInfo.cpp
X86MCInstLower.cpp
X86MachineFunctionInfo.cpp
X86MacroFusion.cpp
X86OptimizeLEAs.cpp
X86PadShortFunction.cpp
X86RegisterBankInfo.cpp
X86RegisterInfo.cpp
X86RetpolineThunks.cpp
X86SelectionDAGInfo.cpp
X86ShuffleDecodeConstantPool.cpp
X86SpeculativeLoadHardening.cpp
X86Subtarget.cpp
X86TargetMachine.cpp
X86TargetObjectFile.cpp
X86TargetTransformInfo.cpp
X86VZeroUpper.cpp
X86WinAllocaExpander.cpp
X86WinEHState.cpp
${MY_SOURCES}
)
add_llvm_target(X86CodeGen ${sources})
add_subdirectory(AsmParser)
add_subdirectory(Disassembler)
add_subdirectory(InstPrinter)
add_subdirectory(MCTargetDesc)
add_subdirectory(TargetInfo)
add_subdirectory(Utils)
add_subdirectory(examples) // my examples directory
我已经尝试过的
我目前正在使用 find_path()
查找 llc
但这需要 llc
已经 编译,因此我的示例 CMakeLists.txt
如果我不事先编译 llc
,验证将失败。
假设路径存在,我最终使用 add_custom_command()
指令在我的 CMakeLists.txt
中使用 llc
,但在我看来这太老套了。
基本上,我需要添加 llc
目标作为我的目标的依赖项,然后使用 llc
's path to compile my examples' .bc
文件到 .s
中。
有什么想法吗?
非常感谢!
我看到了两种可能的解决方案,现在让我介绍一种更简单的解决方案。
project(nested-toolchain C CXX)
# Assume that `llc` target is created somewhere within project
# Even if it is created in later `add_subdirectory` calls,
# We can defer evaluation to its path using generator expression $<TARGET_FILE:llc>
# This is the magic.
# It tells cmake how to produce test1.s from test1.bc using llc binary
# Also will track test1.bc changes and set test1.s as dirty when needed
add_custom_command(OUTPUT test1.s COMMAND $<TARGET_FILE:llc> test1.bc DEPENDS test1.bc)
add_custom_command(OUTPUT test2.s COMMAND $<TARGET_FILE:llc> test2.bc DEPENDS test2.bc)
# Now merge custom commands into single target which can be called by make/ninja/...
# simply call `make tests` to run two commands listed above (and compile llc before that)
add_custom_target(tests SOURCES test1.s test2.s)
总结一下:首先我们知道我们的 CMake 项目可以从 llvm-sources 的某个地方生成 llc
二进制文件。此二进制文件可用于生成 test.s
指定魔术命令的文件。
它们依赖于相应的 .bc
文件。这些 .bc
个文件通过 add_custom_target
.
加入到单个目标 tests
我使用 add_custom_target
来保持示例最小化,它有一个缺陷:调用 make tests
将始终调用所有 llc
命令,因为自定义目标始终被视为 "out of date".
如果您想在 .s
个文件上使用其他工具,我建议您再按类推方式链接另一个 add_custom_command
,然后使用 add_custom_target
完成链接。
只要您测试单个二进制文件 (llc
),这种方法就应该有效。如果您想测试整个工具链,我会选择 try_compile
.
为了完整起见,对于给定的 llc.cpp
文件:
// Just print args
#include <iostream>
int main(int argc, char **argv) {
for (int i = 0; i < argc; i++) {
std::cout << argv[i] << ' ';
}
std::cout << "\n";
return 0;
}
ninja tests
结果:
$ ninja tests
[1/2] Generating test2.s
/home/Whosebug/nested-toolchain/build/llc test2.bc
[2/2] Generating test1.s
/home/Whosebug/nested-toolchain/build/llc test1.bc
我正在编写一个针对 X86 体系结构的 MachineFunctionPass
,它会生成修改后的 llc
二进制文件。
为了测试我修改后的 llc
版本,我创建了一堆 .c
程序,它们的 MIR 将由我的 pass 处理。
为了简洁起见,我将包含源代码的目录直接添加到 LLVM 的源代码树中,特别是在 $llvm_src_dir/lib/Target/X86/$examples_dir
中:然后我通过附加 add_subdirectory()
将其插入 LLVM 构建系统指令 $llvm_src_dir/lib/Target/X86/CMakeLists.txt
.
通过这种方式,我将能够直接从 LLVM 的构建目录构建所有内容。
现在:我如何在 $examples_dir/CMakeLists.txt
中指定使用 LLVM 的 in-tree llc
?
源代码树结构
这是资源的目录结构。我省略了所有根目录的子目录,因为我只包含了 "interesting ones".
LLVM 在 tools/llc
中定义了 llc
目标,而我的源代码位于目录的更深处,如下面的树所示:
llvm_src_dir
├── bindings
├── cmake
├── docs
├── examples
├── include
├── lib
└── Target
└── X86
/*
* My git repo is here. LLVM's and
* my MachineFunctionPass' files
* live here
*/
├── .git
├── CMakeLists.txt // This is LLVM's X86 CMakeLists.txt
└── examples
└── CMakeLists.txt // My CMakeLists.txt
├── projects
├── resources
├── runtimes
├── test
├── tools
└── llc
└── CMakeLists.txt // this is where LLVM's llc target is defined
├── unittests
└── utils
lib/Target/X86/CMakeLists.txt
这就是我编辑目标架构 CMakeLists.txt
的方式:
set (CMAKE_CXX_STANDARD 14)
set(LLVM_TARGET_DEFINITIONS X86.td)
tablegen(LLVM X86GenAsmMatcher.inc -gen-asm-matcher)
tablegen(LLVM X86GenAsmWriter.inc -gen-asm-writer)
tablegen(LLVM X86GenAsmWriter1.inc -gen-asm-writer -asmwriternum=1)
tablegen(LLVM X86GenCallingConv.inc -gen-callingconv)
tablegen(LLVM X86GenDAGISel.inc -gen-dag-isel)
tablegen(LLVM X86GenDisassemblerTables.inc -gen-disassembler)
tablegen(LLVM X86GenEVEX2VEXTables.inc -gen-x86-EVEX2VEX-tables)
tablegen(LLVM X86GenFastISel.inc -gen-fast-isel)
tablegen(LLVM X86GenGlobalISel.inc -gen-global-isel)
tablegen(LLVM X86GenInstrInfo.inc -gen-instr-info)
tablegen(LLVM X86GenRegisterBank.inc -gen-register-bank)
tablegen(LLVM X86GenRegisterInfo.inc -gen-register-info)
tablegen(LLVM X86GenSubtargetInfo.inc -gen-subtarget)
if (X86_GEN_FOLD_TABLES)
tablegen(LLVM X86GenFoldTables.inc -gen-x86-fold-tables)
endif ()
add_public_tablegen_target(X86CommonTableGen)
set(MY_SOURCES
a.cpp
b.cpp
c.cpp
)
set(sources
ShadowCallStack.cpp
X86AsmPrinter.cpp
X86CallFrameOptimization.cpp
X86CallingConv.cpp
X86CallLowering.cpp
X86CmovConversion.cpp
X86DomainReassignment.cpp
X86ExpandPseudo.cpp
X86FastISel.cpp
X86FixupBWInsts.cpp
X86FixupLEAs.cpp
X86AvoidStoreForwardingBlocks.cpp
X86FixupSetCC.cpp
X86FlagsCopyLowering.cpp
X86FloatingPoint.cpp
X86FrameLowering.cpp
X86InstructionSelector.cpp
X86ISelDAGToDAG.cpp
X86ISelLowering.cpp
X86IndirectBranchTracking.cpp
X86InterleavedAccess.cpp
X86InstrFMA3Info.cpp
X86InstrFoldTables.cpp
X86InstrInfo.cpp
X86EvexToVex.cpp
X86LegalizerInfo.cpp
X86MCInstLower.cpp
X86MachineFunctionInfo.cpp
X86MacroFusion.cpp
X86OptimizeLEAs.cpp
X86PadShortFunction.cpp
X86RegisterBankInfo.cpp
X86RegisterInfo.cpp
X86RetpolineThunks.cpp
X86SelectionDAGInfo.cpp
X86ShuffleDecodeConstantPool.cpp
X86SpeculativeLoadHardening.cpp
X86Subtarget.cpp
X86TargetMachine.cpp
X86TargetObjectFile.cpp
X86TargetTransformInfo.cpp
X86VZeroUpper.cpp
X86WinAllocaExpander.cpp
X86WinEHState.cpp
${MY_SOURCES}
)
add_llvm_target(X86CodeGen ${sources})
add_subdirectory(AsmParser)
add_subdirectory(Disassembler)
add_subdirectory(InstPrinter)
add_subdirectory(MCTargetDesc)
add_subdirectory(TargetInfo)
add_subdirectory(Utils)
add_subdirectory(examples) // my examples directory
我已经尝试过的
我目前正在使用 find_path()
查找 llc
但这需要 llc
已经 编译,因此我的示例 CMakeLists.txt
如果我不事先编译 llc
,验证将失败。
假设路径存在,我最终使用 add_custom_command()
指令在我的 CMakeLists.txt
中使用 llc
,但在我看来这太老套了。
基本上,我需要添加 llc
目标作为我的目标的依赖项,然后使用 llc
's path to compile my examples' .bc
文件到 .s
中。
有什么想法吗?
非常感谢!
我看到了两种可能的解决方案,现在让我介绍一种更简单的解决方案。
project(nested-toolchain C CXX)
# Assume that `llc` target is created somewhere within project
# Even if it is created in later `add_subdirectory` calls,
# We can defer evaluation to its path using generator expression $<TARGET_FILE:llc>
# This is the magic.
# It tells cmake how to produce test1.s from test1.bc using llc binary
# Also will track test1.bc changes and set test1.s as dirty when needed
add_custom_command(OUTPUT test1.s COMMAND $<TARGET_FILE:llc> test1.bc DEPENDS test1.bc)
add_custom_command(OUTPUT test2.s COMMAND $<TARGET_FILE:llc> test2.bc DEPENDS test2.bc)
# Now merge custom commands into single target which can be called by make/ninja/...
# simply call `make tests` to run two commands listed above (and compile llc before that)
add_custom_target(tests SOURCES test1.s test2.s)
总结一下:首先我们知道我们的 CMake 项目可以从 llvm-sources 的某个地方生成 llc
二进制文件。此二进制文件可用于生成 test.s
指定魔术命令的文件。
它们依赖于相应的 .bc
文件。这些 .bc
个文件通过 add_custom_target
.
tests
我使用 add_custom_target
来保持示例最小化,它有一个缺陷:调用 make tests
将始终调用所有 llc
命令,因为自定义目标始终被视为 "out of date".
如果您想在 .s
个文件上使用其他工具,我建议您再按类推方式链接另一个 add_custom_command
,然后使用 add_custom_target
完成链接。
只要您测试单个二进制文件 (llc
),这种方法就应该有效。如果您想测试整个工具链,我会选择 try_compile
.
为了完整起见,对于给定的 llc.cpp
文件:
// Just print args
#include <iostream>
int main(int argc, char **argv) {
for (int i = 0; i < argc; i++) {
std::cout << argv[i] << ' ';
}
std::cout << "\n";
return 0;
}
ninja tests
结果:
$ ninja tests
[1/2] Generating test2.s
/home/Whosebug/nested-toolchain/build/llc test2.bc
[2/2] Generating test1.s
/home/Whosebug/nested-toolchain/build/llc test1.bc