我正在写一个针对X86体系结构的MachineFunctionPass
,它产生了经过修改的llc
二进制文件。
为了测试修改后的llc
版本,我创建了一堆.c
程序,其MIR将由我的通行证处理。
为了简洁起见,我已将包含源的目录直接添加到LLVM的源树中,特别是在$llvm_src_dir/lib/Target/X86/$examples_dir
中:然后,通过将add_subdirectory()
指令附加到LLVM构建系统,将其插入到LLVM构建系统中。 $llvm_src_dir/lib/Target/X86/CMakeLists.txt
。
这样,我将能够直接从LLVM的构建目录构建所有内容。
现在:如何在$examples_dir/CMakeLists.txt
中指定使用LLVM的树内llc
?
这是来源的目录结构。因为只包含了“有趣的目录”,所以我省略了所有根目录的子目录。
LLVM在llc
中定义了tools/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()
中使用llc
指令在CMakeLists.txt
中使用llc
,但是我认为这太过分了。
基本上,我需要添加llc
目标作为目标的依赖项,然后使用.bc
的路径将示例的.s
文件编译为mongoimport --db myApp --collection tempCollection --drop --file list.json --jsonArray
有什么想法吗?
非常感谢您!
答案 0 :(得分:1)
I see two possible solutions and for now let me present simpler one.
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)
To sum up: first we know that our CMake project can produce llc
binary somewhere from llvm-sources. This binary can be used to produce test.s
files with magic command specified.
They depend on corresponding .bc
files. These .bc
files are joined into single target tests
via add_custom_target
.
I've used add_custom_target
to keep example minimal and it has one flaw: calling make tests
will always call all llc
commands, as custom targets are always considered "out of date".
If you want to use another tool over .s
files, I recommend to chain yet another add_custom_command
analogically and use add_custom_target
to finish the chain.
This approach should work as long as you are testing single binary (llc
). If you wanted to test whole toolchain, I'd go for try_compile
.
For completeness, for llc.cpp
file as given:
// 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
result in:
$ ninja tests
[1/2] Generating test2.s
/home/stackoverflow/nested-toolchain/build/llc test2.bc
[2/2] Generating test1.s
/home/stackoverflow/nested-toolchain/build/llc test1.bc