我正在尝试使用LLVM来为我的代码添加即时编译,但发现很难找到关于如何在LLVM中执行我想要的事情的参考,尽管已经通过Kaleidoscope教程检查了语言参考手册,程序员手册和doxygen文档.是否有更多对LLVM的C++ API的引用?
现在提出具体问题.我已经分配了一个带有两个元素的数组对象(我假设它对应double[2]于C++):
const llvm::Type* double_t = llvm::Type::getDoubleTy(llvm::getGlobalContext());
const llvm::Type* array_t = llvm::ArrayType::get(double_t,2)
Run Code Online (Sandbox Code Playgroud)
稍后在代码中,我创建了一个函数,其中此数组是参数之一.然后,在我的函数中,我提取数组中的第一个元素并将其返回给用户:
llvm::Function::arg_iterator AI = jit_function_->arg_begin();
llvm::Value *x = AI;
llvm::Value *x0 = Builder.CreateExtractValue(x,0);
Builder.CreateRet(x0);
Run Code Online (Sandbox Code Playgroud)
代码很好,但是当我尝试运行它时,它不起作用.例如:
typedef double (*GenType)(double[2]);
GenType FP = GenType(intptr_t(TheExecutionEngine->getPointerToFunction(jit_function_)));
double y[2] = {10,20};
double r = FP(y);
printf("r = %g\n", r);
Run Code Online (Sandbox Code Playgroud)
返回值只是废话,我看不出我做错了什么.如果我将数组(10和20)中的值作为函数的标量参数传递,它可以正常工作.
在我的研究小组中,我们有不同的人在不同的符号工具中进行代数建模,例如Matlab中的Symbolic Toolbox和Python中的Sympy.然后,这些模型通常导出为C代码并复制粘贴到我们自己的基于符号C++的工具中,以进一步进行符号操作.
在寻找这种难以维护的方法的替代方案时,我发现了两种看起来或多或少标准化的格式:OpenMath和"Content MathML".请注意,我们只对语义感兴趣,没有漂亮的打印.
这两种格式之间有什么关系?两者都可以用来存储和交换工具之间的数学表达式吗?
是否还有其他或多或少标准化的数学表达式交换格式?
我有一个C++项目,其核心基本上是自包含的,但有很多用户可能想要或可能不想编译的第三方代码接口.我们使用CMake构建代码,现在我正在尝试更好地组织代码.
我想出的解决方案是在顶部CMakeLists.txt文件中添加一组选项,用于确定是否应该定位依赖包.
option(WITH_FOO "Compile the interface to Foo, if found" ON)
option(REQUIRE_FOO "Require that the Foo interface to be compiled" OFF)
option(WITH_BAR "Compile the interface to Bar, if found" ON)
option(REQUIRE_BAR "Require that the Bar interface to be compiled" OFF)
...
if(WITH_FOO)
if(REQUIRE_FOO)
find_package(Foo REQUIRED)
else(REQUIRE_FOO)
find_package(Foo)
endif(REQUIRE_FOO)
else(WITH_FOO)
set(FOO_FOUND FALSE)
endif(WITH_FOO)
if(WITH_BAR)
if(REQUIRE_BAR)
find_package(Bar REQUIRED)
else(REQUIRE_BAR)
find_package(Bar)
endif(REQUIRE_BAR)
else(WITH_BAR)
set(BAR_FOUND FALSE)
endif(WITH_BAR)
Run Code Online (Sandbox Code Playgroud)
然后在子目录中的CMakeLists.txt文件中,将出现如下语句:
if(BAR_FOUND)
add_subdirectory(bar_interface)
endif(BAR_FOUND)
Run Code Online (Sandbox Code Playgroud)
我并不特别喜欢这个解决方案,部分原因是因为它非常冗长,部分是因为我觉得应该有一些更标准化的方法来做到这一点.有人知道更好,更易维护的解决方案吗?
我正在研究对应于大数学表达式(数百万个节点)的表达式图实现公共子表达式消除(CSE).
什么算法适合执行此操作?我在互联网上搜索一个易于实现的算法,但我找不到任何东西.如果可能,算法应该具有完整表达图的节点数的线性复杂度.
我试图使用llvm作为我的软件的代码生成后端,并且意识到llvm是在不支持C++异常处理的情况下编译的(为了提高效率).但是,在我的软件中,我广泛使用异常处理.
如果我将所有回调函数包装在try-catch-blocks中(这样就不需要通过llvm代码传播任何异常),那么我可以安全地从我的链接器标志中删除"-fno-exceptions"(对于GCC) ?(当与llvm链接时,通常需要此标志,因为它在执行时会出现llvm-config --cxxflags).
如果不是,如果用包含"throws()"声明的函数包装llvm函数,情况是否会改变?可以使用-fno-exceptions编译这些函数的实现.
我有一个带有SWIG生成的Python前端的C++项目,我使用CMake构建.我现在正在尝试找到一种方便的方法来调试我的混合Python/C++代码.我能够使用gdb获得堆栈跟踪错误,但我希望有一些更奇特的功能,例如单步执行代码和设置断点的功能,例如使用Eclipse.
使用Eclipse生成器进行CMake我能够生成一个能够导入Eclipse的项目.这很好用,我也可以单步执行纯C++可执行文件.但问题就此开始了.
首先,我无法从Eclipse内部构建Python前端.从命令行我只做"make python",但Eclipse项目中没有目标"python".
其次,一旦我编译了Python前端,我就不知道如何逐步完成包含对我的包装C++类的调用的Python脚本.Eclipse已经为Python和C++进行了调试,但是它们可以组合在一起吗?
我有一组由整数类型Index和类类型模板化的函数,T我以下列方式"部分地专门化":
// Integer type
enum Index{One,Two,Three,Four};
// Default implementation
template<int I>
struct Foo{
template<typename T> static void bar(const T& x){ std::cout <<"default" << endl; }
};
// Template specializations
template<>
struct Foo<One>{
template<typename T> static void bar(const T& x){ std::cout << "one" << endl; }
};
Run Code Online (Sandbox Code Playgroud)
这用于在程序的运行时使用switch语句选择一个特定的索引(这应该会产生一个高效的查找表).该开关独立于T:
template<typename T>
void barSwitch(int k, const T& x){
switch(k){
case ONE: Foo<ONE>::bar(x); break;
case TWO: Foo<TWO>::bar(x); break;
case THREE: Foo<THREE>::bar(x); break;
}
}
Run Code Online (Sandbox Code Playgroud)
当然,这很好用,但是这个类Foo并不是我想要应用这个开关的唯一类.事实上,我有很多类都是由相同的整数类型模板化的.所以我想barSwitch …
据我了解, astd::stringstream在内部表示不是作为一个std::string而是作为一组std::string实例。(如果我错了,请纠正我)。
我有表示为 an 的数据std::stringstream,我想将它传递给一个 C 函数(clCreateProgramWithSource来自 OpenCL),该函数期望数据作为字符数组的数组。( const char**).
是否有某种方法可以在不首先创建一个包含 stringstream 的全部内容的字符串的情况下执行此操作,例如通过以下方式:
std::string tmp1 = my_stringstream.str();
const char* tmp2 = tmp1.c_str();
const char** tmp3 = &tmp2;
Run Code Online (Sandbox Code Playgroud)
编辑
后续问题:
如果这是没有可能的,是有一些替代方案std::stringstream,继承std::ostream,允许这种低级别的访问权限?
我有一个用C++编写的程序,它为数学计算生成C源代码.我注意到常量在生成的代码中占用了很多空间,我正在寻找更紧凑的表示.
要生成常量,我现在使用:
double v = ...
cfile << std::scientific << std::setprecision(std::numeric_limits<double>::digits10 + 1) << v;
Run Code Online (Sandbox Code Playgroud)
我很确定这是一种无损代表,但它也非常臃肿.例如,零和一个将表示为0.0000000000000000e + 00和1.0000000000000000e + 00.并且"0" 或"1." 携带同样多的信息.
有没有办法以更紧凑但仍然无损的方式打印常量?它并不需要好看的人类读者,只是编译当存在于普通的C代码(如C99,我宁愿当它也是有效的C++).十六进制可以是可移植的.
编辑:已删除std::fixed代码段.
我有一个能够生成C语言代码的软件,希望在即时编译环境中使用。据我了解,LLVM / Clang是可行的方法,为了项目的可维护性,我想使用llvm和Clang的C API(libclang)。
我开始使用创建一个libclang上下文,clang_createIndex并使用一个翻译单元创建一个createTranslationUnitFromSourceFile(很高兴能够避免通过文件系统,而是将源代码作为字符串传递)。但是我几乎被困在那里。如何从libclang转换单元转到LLVM“执行引擎”,这似乎是JIT所需要的?还是使用C API甚至无法做到这一点?
我试图在使用参数依赖查找(ADL)的函数中使用std :: initializer_list作为参数.但是我没有让它工作,我不明白为什么.以下是最小的失败示例:
#include <initializer_list>
#include <iostream>
class Foo {
public:
inline friend void bar(std::initializer_list<Foo> v) {
std::cout << "size = " << v.size() << std::endl;
}
};
void baz(std::initializer_list<Foo> v) {
std::cout << "size = " << v.size() << std::endl;
}
int main(){
Foo a;
//bar({a,a}); // error: use of undeclared identifier 'bar'
baz({a,a}); // works
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如上所示,等效的全局函数可以正常工作.为什么以上不起作用?
我在OS X 10.10上使用了clang.
我有一个C++框架,其中一些计算被委托(有时自动生成)C函数或C++函数与外部"C"链接.这些是低级例程,必须以非常快的速度进行评估并且开销最小,并且它们通常驻留在单独的共享对象/ DLL中.他们目前的签名是这样的:
int my_generated_function(const double* input, double* output, double* work);
Run Code Online (Sandbox Code Playgroud)
它将驻留在使用dlopenPOSIX或LoadLibraryWindows 加载的共享库中.使用dlsym(handle, "my_generated_function")POSIX或GetProcAddress(handle, TEXT("my_generated_function"))Windows 提取相应的函数指针.
使用FILE对象指针增强签名是否安全且可移植?
int my_generated_function(const double* input, double* output, double* work,
FILE* logfile);
Run Code Online (Sandbox Code Playgroud)
请注意,包含的共享对象my_generated_function可能已使用与加载共享对象的代码不同(但二进制兼容)的编译器进行编译.
我在基类中定义了一个昂贵的函数,它依赖于派生类的低级信息:
class BaseClass{
...
// Defined in derived class
virtual int low_level(int)=0;
// Expensive function depending on the pure virtual function
void myExpensiveFunction(){
for(...){
for(...){
for(...){
... = low_level(...);
...
}
}
}
}
};
class DerivedClass : public BaseClass{
// A very cheap operation that can be inlined:
inline virtual int low_level(int i){
return a[i];
}
// Calling the base class function
void test(){
myExpensiveFunction();
}
};
Run Code Online (Sandbox Code Playgroud)
如果我理解正确,那么低级函数是虚拟的这一事实可以防止它在上面的代码中被内联.现在,我正在考虑一种解决此问题的方法并考虑以下解决方案,其中我将指向派生类成员函数的指针作为模板参数传递:
class BaseClass{
...
// The function is now templated by the …Run Code Online (Sandbox Code Playgroud)