我在C++中有一些示例代码:
struct RecordTest
{
int value1;
int value2;
};
void test()
{
RecordTest rt;
rt.value1 = 15;
rt.value2 = 75;
}
Run Code Online (Sandbox Code Playgroud)
和LLVM 3.4 IR:
%struct.RecordTest = type { i32, i32 }
; Function Attrs: nounwind
define void @_Z4testv() #0 {
entry:
%rt = alloca %struct.RecordTest, align 4
%value1 = getelementptr inbounds %struct.RecordTest* %rt, i32 0, i32 0
store i32 15, i32* %value1, align 4
%value2 = getelementptr inbounds %struct.RecordTest* %rt, i32 0, i32 1
store i32 75, i32* %value2, align …Run Code Online (Sandbox Code Playgroud) 下面的问题如何检测类型是否可以流式传输到std :: ostream?我写了一个trait类,说明某些类型是否可以流式传输到IO流.直到现在我发现了一个问题,这个特性似乎运作良好.
我在使用LLVM的项目中使用代码,我正在使用他们的StringRef类(它与提议的std :: string_view类似).这是该类的Doxygen doc的链接,如果需要,您可以从中找到它的声明头文件.由于LLVM不提供运算符<<将StringRef对象流式传输到std流(它们使用自定义轻量级流类),因此我写了一个.
但是,当我使用特征时,如果我的自定义运算符<< 在特征之后被声明(这是因为我在一个标题中具有特征而操作符在另一个标题中的函数),则它不起作用.我曾经认为模板实例化中的查找是从实例化点的角度来看的,所以我认为它应该可行.实际上,正如你在下面看到的那样,使用另一个类及其自定义运算符<<,在特征之后声明,一切都按预期工作(这就是为什么我现在才发现这个问题),所以我无法弄清楚StringRef的原因特别.
这是完整的例子:
#include <iostream>
#include "llvm/ADT/StringRef.h"
// Trait class exactly from the cited question's accepted answer
template<typename T>
class is_streamable
{
template<typename SS, typename TT>
static auto test(int)
-> decltype(std::declval<SS&>() << std::declval<TT>(),
std::true_type());
template<typename, typename>
static auto test(...) -> std::false_type;
public:
static const bool value = decltype(test<std::ostream,T>(0))::value;
};
// Custom stream operator for StringRef, declared after the trait
inline std::ostream &operator<<(std::ostream &s, llvm::StringRef const&str) {
return …Run Code Online (Sandbox Code Playgroud) 对于LLVM IR指令,%cmp7 = icmp eq i32 %6 %7我希望得到所有三个寄存器/符号名称(即%cmp %6 and %7)
现在我可以%cmp通过命令获取字符串,pi->getName()其中pi是指令指针.但是当我尝试获取操作名称时,我通过键入获得了空字符串pi->getOperand(0)->getName().
我试图isa<Instruction>(pi->getOperand(0))检查这是否是一个指令,它返回true但pi->getOperand(0)->hasName()返回false.事情让我感到奇怪的是,为什么这两个pi和pi->getOperand(0)的指示,但仅pi具有名?
有没有想法我可以使用API 获取操作数名称(字符串%6和 %7此处)?
我正在使用的LLVM版本是3.4.2
直截了当 - 我正在尝试将两个(或更多)llvm模块链接在一起,而我正面临来自LLVM的某个奇怪错误.
我不想发布太多代码,所以我会在这里使用一堆伪.
我有3个模块,比方说A,B和C. A是主要模块; 我llvm::Linker用它初始化.B和C是辅助模块; 我打电话linker.linkInModule(B and C).
除其他外,所有3个模块都定义了以下两种类型:
%String = type { i8*, i64 }
%Character = type { i8*, i64 }
Run Code Online (Sandbox Code Playgroud)
请注意,它们具有相同的成员类型.此外,函数foo定义为(在模块B中):
define i1 @_ZN9Character7hasDataEv(%Character*) { }
Run Code Online (Sandbox Code Playgroud)
这个函数在模块A和C中声明.现在,一切看起来都很好 - 从模块A和C调用此函数,并且IR看起来很正常,如下所示:
%21 = call i1 @_ZN9Character7hasDataEv(%Character* %4)
Run Code Online (Sandbox Code Playgroud)
问题出在这里:当所有3个模块链接在一起时,这些类型会发生一些事情:
%2(%String)和%3(%Character).奇怪的是,虽然这种转换发生在模块A和C中,但这种错误只发生在C中 - 注意A是所谓的"主"模块.
现在是链接文件的函数定义
define i1 @_ZN9Character7hasDataEv(%2*)
Run Code Online (Sandbox Code Playgroud)
注意如何%Character,或者%3,变成了%2.此外,在呼叫网站,可能是尝试取消合并类型,我得到了这个:
%10 = call i1 bitcast (i1 (%2*)* @_ZN9Character7hasDataEv to …Run Code Online (Sandbox Code Playgroud) 给定一个llvm::CallInst *,如何告诉内联者内联这个特定的调用.我可以将目标函数标记为AlwaysInline,这将内联调用,但它也会内联每个调用.也许有一些方法可以在我发出特定呼叫时调用内联器?内联基本块中的所有调用也会起作用.
我正在尝试用LLVM和C++编写一个玩具编译器.但每当我尝试使用多个索引创建一个GetElementPtrInst时,就会出现一个Segfault.关于这条指令的文档对我没有帮助(API-文档 语言 - 文档)
我的llvm版本是3.1,这是在Arch Linux上.刚刚在另一台Arch机器上测试它并得到了同样的错误.
难道我做错了什么?
这是一个小工作程序来说明我的问题.它可以编译为:
g++ -o segfault_example segfault_example.cpp -Wall -Wextra -pedantic \
`llvm-config --libs core jit native --cxxflags --ldflags`
Run Code Online (Sandbox Code Playgroud)
#include <llvm/Module.h>
#include <llvm/Constants.h>
#include <llvm/DerivedTypes.h>
#include <llvm/LLVMContext.h>
#include <llvm/Instructions.h>
#include <llvm/Analysis/Verifier.h>
#include <llvm/ADT/ArrayRef.h>
#include <string>
#include <iostream>
static llvm::LLVMContext& global = llvm::getGlobalContext();
static llvm::Type* int32ty = llvm::Type::getInt32Ty(global);
llvm::ConstantInt* getInt32(int n)
{
return llvm::ConstantInt::get(llvm::Type::getInt32Ty(global), n);
}
int main()
{
//setup everything for a minimal example
llvm::Module* mainModule = new llvm::Module("main", global);
llvm::FunctionType* ftype = llvm::FunctionType::get(int32ty, …Run Code Online (Sandbox Code Playgroud) 使用以下代码,我可以从模块生成LLVM 位代码文件:
llvm::Module * module;
// fill module with code
module = ...;
std::error_code ec;
llvm::raw_fd_ostream out("anonymous.bc", ec, llvm::sys::fs::F_None);
llvm::WriteBitcodeToFile(module, out);
Run Code Online (Sandbox Code Playgroud)
然后我可以使用该位码文件生成可执行机器代码文件,例如:
clang -o anonymous anonymous.bc
Run Code Online (Sandbox Code Playgroud)
或者:
llc anonymous.bc
gcc -o anonymous anonymous.s
Run Code Online (Sandbox Code Playgroud)
我现在的问题是:我可以使用 LLVM API 直接在 C++ 中生成机器代码,而不需要首先编写位码文件吗?
我正在寻找代码示例或至少 LLVM API 中的一些起点,例如要使用哪些类,将我推向正确的方向可能就足够了。
我正在 LLVM 中编写一个函数传递,需要调用方法 Module::getOrInsertFunction。我需要访问当前函数的模块。我如何得到它?
我有以下要生成C ++的IR代码:
@gArray = global [10 x i32] [i32 3, i32 4, i32 5, i32 6, i32 0, i32 0, i32 0, i32 0, i32 12, i32 0], align 16
Run Code Online (Sandbox Code Playgroud)
我知道我可以使用以下代码行将数组初始化为全零:
ConstantAggregateZero* const_array_2 = ConstantAggregateZero::get(ArrayTy_0);
GArray->setInitializer(const_array_2);
Run Code Online (Sandbox Code Playgroud)
如何将LLVM中的数组初始化为值列表?
我试图在过去的两天里将LLVM与My C++项目联系起来并且它最终正在工作,但问题是当我使用dump()方法时它会给出链接器错误我认为问题出在我正在链接的库中,所以我'我将可执行文件链接到所有LLVM库(模块)但没有成功.所以这是LLVM5.0代码库中的一个错误,或者我做错了什么以及我专门谈论LLVM5.0的原因,因为我已经在评论部分中读取了其他地方(LLVM-5.0 Makefile未定义引用失败)没有问题使用LLVM4.0编译相同的代码,当然我搜索了其他解决方案,但没有什么
llvm_test.cpp:
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
llvm::LLVMContext context;
int main(){
llvm::Module*module = new llvm::Module("llvm-module",context);
module->dump();
}
Run Code Online (Sandbox Code Playgroud)
命令:
clang++ -O3 -Wall -std=c++11 `llvm-config --cppflags --ldflags` `llvm-config --libs core --system-libs` toy.cpp
Run Code Online (Sandbox Code Playgroud)
而且我已经链接了所有模块:
clang++ -O3 -Wall -std=c++11 `llvm-config --cxxflags --ldflags` `llvm-config --libs all --system-libs` toy.cpp
Run Code Online (Sandbox Code Playgroud)
编译器: Apple Clang 8.0.0 x86_64
操作系统: mac OS 10.12.5
谢谢你提前帮助