如果我有一个声明了
我该如何确保C++代码中的
此外,在C++中我有一个
问题在于LLVM在
我正在尝试使用。对于我的机器[Mac OS X 10.9.5,g++ Apple LLVM版本6.0(基于LLVM 3.5svn的clang-600.0.57)],如果我打印数据布局字符串,我会得到:
如果我强制设置数据布局为:
struct
的C++程序,例如:struct S {
short s;
union U {
bool b;
void *v;
};
U u;
};
我使用LLVM C ++ API生成一些LLVM IR,以反映C ++声明:
vector<Type*> members;
members.push_back( IntegerType::get( ctx, sizeof( short ) * 8 ) );
// since LLVM doesn't support unions, just use an ArrayType that's the same size
members.push_back( ArrayType::get( IntegerType::get( ctx, 8 ), sizeof( S::U ) ) );
StructType *const llvm_S = StructType::create( ctx, "S" );
llvm_S->setBody( members );
我该如何确保C++代码中的
sizeof(S)
与LLVM IR代码中的StructType
大小相同?对于各个成员的偏移量,例如u.b
,也是同样的情况。此外,在C++中我有一个
S
数组已经分配好了空间:S *s_array = new S[10];
我将s_array
传递给LLVM IR代码,其中我访问数组的各个元素。为了使其正常工作,sizeof(S)
在C++和LLVM IR中必须相同,因此如下所示:
%elt = getelementptr %S* %ptr_to_start, i64 1
将正确访问s_array[1]
。
当我编译并运行下面的程序时,它输出:
sizeof(S) = 16
allocSize(S) = 10
问题在于LLVM在
S::s
和S::u
之间缺少6个字节的填充。C++编译器使union
从8字节对齐边界开始,而LLVM则没有这样做。我正在尝试使用。对于我的机器[Mac OS X 10.9.5,g++ Apple LLVM版本6.0(基于LLVM 3.5svn的clang-600.0.57)],如果我打印数据布局字符串,我会得到:
e-m:o-i64:64-f80:128-n8:16:32:64-S128
如果我强制设置数据布局为:
e-m:o-i64:64-f80:128-n8:16:32:64-S128-a:64
如果加上a:64
,表示聚合类型的对象将对齐在64位边界上,那么我得到的大小是相同的。那么为什么默认数据布局不正确呢?
下面是完整的工作程序
// LLVM
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/MCJIT.h>
#include <llvm/IR/DerivedTypes.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/Type.h>
#include <llvm/Support/TargetSelect.h>
// standard
#include <iostream>
#include <memory>
#include <string>
using namespace std;
using namespace llvm;
struct S {
short s;
union U {
bool b;
void *v;
};
U u;
};
ExecutionEngine* createEngine( Module *module ) {
InitializeNativeTarget();
InitializeNativeTargetAsmPrinter();
unique_ptr<Module> u( module );
EngineBuilder eb( move( u ) );
string errStr;
eb.setErrorStr( &errStr );
eb.setEngineKind( EngineKind::JIT );
ExecutionEngine *const exec = eb.create();
if ( !exec ) {
cerr << "Could not create ExecutionEngine: " << errStr << endl;
exit( 1 );
}
return exec;
}
int main() {
LLVMContext ctx;
vector<Type*> members;
members.push_back( IntegerType::get( ctx, sizeof( short ) * 8 ) );
members.push_back( ArrayType::get( IntegerType::get( ctx, 8 ), sizeof( S::U ) ) );
StructType *const llvm_S = StructType::create( ctx, "S" );
llvm_S->setBody( members );
Module *const module = new Module( "size_test", ctx );
ExecutionEngine *const exec = createEngine( module );
DataLayout const *const layout = exec->getDataLayout();
module->setDataLayout( layout );
cout << "sizeof(S) = " << sizeof( S ) << endl;
cout << "allocSize(S) = " << layout->getTypeAllocSize( llvm_S ) << endl;
delete exec;
return 0;
}