mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-04-30 23:20:40 +03:00

Fixed: Implemented volatile statements. Uses the LLVM memory barrier intrinsic, closes #21 .
1095 lines
36 KiB
C++
1095 lines
36 KiB
C++
#include "gen/llvm.h"
|
|
|
|
#include "mtype.h"
|
|
#include "dsymbol.h"
|
|
#include "aggregate.h"
|
|
#include "declaration.h"
|
|
#include "init.h"
|
|
|
|
#include "gen/irstate.h"
|
|
#include "gen/tollvm.h"
|
|
#include "gen/arrays.h"
|
|
#include "gen/runtime.h"
|
|
#include "gen/logger.h"
|
|
#include "gen/dvalue.h"
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
const llvm::StructType* DtoArrayType(Type* t)
|
|
{
|
|
assert(t->next);
|
|
const llvm::Type* at = DtoType(t->next);
|
|
const llvm::Type* arrty;
|
|
|
|
if (at == llvm::Type::VoidTy) {
|
|
at = llvm::Type::Int8Ty;
|
|
}
|
|
arrty = getPtrToType(at);
|
|
|
|
std::vector<const llvm::Type*> members;
|
|
if (global.params.is64bit)
|
|
members.push_back(llvm::Type::Int64Ty);
|
|
else
|
|
members.push_back(llvm::Type::Int32Ty);
|
|
|
|
members.push_back(arrty);
|
|
|
|
return llvm::StructType::get(members);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
const llvm::ArrayType* DtoStaticArrayType(Type* t)
|
|
{
|
|
if (t->ir.type)
|
|
return isaArray(t->ir.type->get());
|
|
|
|
assert(t->ty == Tsarray);
|
|
assert(t->next);
|
|
|
|
const llvm::Type* at = DtoType(t->next);
|
|
|
|
TypeSArray* tsa = (TypeSArray*)t;
|
|
assert(tsa->dim->type->isintegral());
|
|
const llvm::ArrayType* arrty = llvm::ArrayType::get(at,tsa->dim->toUInteger());
|
|
|
|
assert(!tsa->ir.type);
|
|
tsa->ir.type = new llvm::PATypeHolder(arrty);
|
|
return arrty;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void DtoSetArrayToNull(llvm::Value* v)
|
|
{
|
|
Logger::println("DtoSetArrayToNull");
|
|
LOG_SCOPE;
|
|
|
|
llvm::Value* len = DtoGEPi(v,0,0,"tmp",gIR->scopebb());
|
|
llvm::Value* zerolen = llvm::ConstantInt::get(len->getType()->getContainedType(0), 0, false);
|
|
new llvm::StoreInst(zerolen, len, gIR->scopebb());
|
|
|
|
llvm::Value* ptr = DtoGEPi(v,0,1,"tmp",gIR->scopebb());
|
|
const llvm::PointerType* pty = isaPointer(ptr->getType()->getContainedType(0));
|
|
llvm::Value* nullptr = llvm::ConstantPointerNull::get(pty);
|
|
new llvm::StoreInst(nullptr, ptr, gIR->scopebb());
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void DtoArrayAssign(llvm::Value* dst, llvm::Value* src)
|
|
{
|
|
Logger::println("DtoArrayAssign");
|
|
LOG_SCOPE;
|
|
|
|
assert(gIR);
|
|
if (dst->getType() == src->getType())
|
|
{
|
|
llvm::Value* ptr = DtoGEPi(src,0,0,"tmp",gIR->scopebb());
|
|
llvm::Value* val = new llvm::LoadInst(ptr,"tmp",gIR->scopebb());
|
|
ptr = DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
|
|
new llvm::StoreInst(val, ptr, gIR->scopebb());
|
|
|
|
ptr = DtoGEPi(src,0,1,"tmp",gIR->scopebb());
|
|
val = new llvm::LoadInst(ptr,"tmp",gIR->scopebb());
|
|
ptr = DtoGEPi(dst,0,1,"tmp",gIR->scopebb());
|
|
new llvm::StoreInst(val, ptr, gIR->scopebb());
|
|
}
|
|
else
|
|
{
|
|
Logger::cout() << "array assignment type dont match: " << *dst->getType() << "\n\n" << *src->getType() << '\n';
|
|
const llvm::ArrayType* arrty = isaArray(src->getType()->getContainedType(0));
|
|
if (!arrty)
|
|
{
|
|
Logger::cout() << "invalid: " << *src << '\n';
|
|
assert(0);
|
|
}
|
|
const llvm::Type* dstty = getPtrToType(arrty->getElementType());
|
|
|
|
llvm::Value* dstlen = DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
|
|
llvm::Value* srclen = DtoConstSize_t(arrty->getNumElements());
|
|
new llvm::StoreInst(srclen, dstlen, gIR->scopebb());
|
|
|
|
llvm::Value* dstptr = DtoGEPi(dst,0,1,"tmp",gIR->scopebb());
|
|
llvm::Value* srcptr = new llvm::BitCastInst(src,dstty,"tmp",gIR->scopebb());
|
|
new llvm::StoreInst(srcptr, dstptr, gIR->scopebb());
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void DtoArrayInit(llvm::Value* l, llvm::Value* r)
|
|
{
|
|
Logger::println("DtoArrayInit");
|
|
LOG_SCOPE;
|
|
|
|
const llvm::PointerType* ptrty = isaPointer(l->getType());
|
|
const llvm::Type* t = ptrty->getContainedType(0);
|
|
const llvm::ArrayType* arrty = isaArray(t);
|
|
if (arrty)
|
|
{
|
|
llvm::Value* ptr = DtoGEPi(l,0,0,"tmp",gIR->scopebb());
|
|
llvm::Value* dim = llvm::ConstantInt::get(DtoSize_t(), arrty->getNumElements(), false);
|
|
DtoArrayInit(ptr, dim, r);
|
|
}
|
|
else if (isaStruct(t))
|
|
{
|
|
llvm::Value* dim = DtoLoad(DtoGEPi(l, 0,0, "tmp"));
|
|
llvm::Value* ptr = DtoLoad(DtoGEPi(l, 0,1, "tmp"));
|
|
DtoArrayInit(ptr, dim, r);
|
|
}
|
|
else
|
|
assert(0);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
typedef const llvm::Type* constLLVMTypeP;
|
|
|
|
static size_t checkRectArrayInit(const llvm::Type* pt, constLLVMTypeP& finalty)
|
|
{
|
|
if (const llvm::ArrayType* arrty = isaArray(pt)) {
|
|
size_t n = checkRectArrayInit(arrty->getElementType(), finalty);
|
|
size_t ne = arrty->getNumElements();
|
|
if (n) return n * ne;
|
|
return ne;
|
|
}
|
|
finalty = pt;
|
|
return 0;
|
|
}
|
|
|
|
void DtoArrayInit(llvm::Value* ptr, llvm::Value* dim, llvm::Value* val)
|
|
{
|
|
Logger::println("DtoArrayInit");
|
|
LOG_SCOPE;
|
|
|
|
Logger::cout() << "array: " << *ptr << " dim: " << *dim << " val: " << *val << '\n';
|
|
const llvm::Type* pt = ptr->getType()->getContainedType(0);
|
|
const llvm::Type* t = val->getType();
|
|
const llvm::Type* finalTy;
|
|
size_t aggrsz = 0;
|
|
if (size_t arrsz = checkRectArrayInit(pt, finalTy)) {
|
|
assert(finalTy == t);
|
|
llvm::Constant* c = isaConstant(dim);
|
|
assert(c);
|
|
dim = llvm::ConstantExpr::getMul(c, DtoConstSize_t(arrsz));
|
|
ptr = gIR->ir->CreateBitCast(ptr, getPtrToType(finalTy), "tmp");
|
|
}
|
|
else if (isaStruct(t)) {
|
|
aggrsz = getABITypeSize(t);
|
|
llvm::Constant* c = isaConstant(val);
|
|
if (c && c->isNullValue()) {
|
|
llvm::Value* nbytes;
|
|
if (aggrsz == 1)
|
|
nbytes = dim;
|
|
else
|
|
nbytes = gIR->ir->CreateMul(dim, DtoConstSize_t(aggrsz), "tmp");
|
|
DtoMemSetZero(ptr,nbytes);
|
|
return;
|
|
}
|
|
else {
|
|
ptr = gIR->ir->CreateBitCast(ptr, getPtrToType(llvm::Type::Int8Ty), "tmp");
|
|
}
|
|
}
|
|
else {
|
|
assert(t == pt);
|
|
}
|
|
|
|
Logger::cout() << "array: " << *ptr << " dim: " << *dim << " val: " << *val << '\n';
|
|
|
|
std::vector<llvm::Value*> args;
|
|
args.push_back(ptr);
|
|
args.push_back(dim);
|
|
args.push_back(val);
|
|
|
|
const char* funcname = NULL;
|
|
|
|
if (aggrsz) {
|
|
funcname = "_d_array_init_mem";
|
|
args.push_back(DtoConstSize_t(aggrsz));
|
|
}
|
|
else if (isaPointer(t)) {
|
|
funcname = "_d_array_init_pointer";
|
|
|
|
const llvm::Type* dstty = getPtrToType(getPtrToType(llvm::Type::Int8Ty));
|
|
if (args[0]->getType() != dstty)
|
|
args[0] = new llvm::BitCastInst(args[0],dstty,"tmp",gIR->scopebb());
|
|
|
|
const llvm::Type* valty = getPtrToType(llvm::Type::Int8Ty);
|
|
if (args[2]->getType() != valty)
|
|
args[2] = new llvm::BitCastInst(args[2],valty,"tmp",gIR->scopebb());
|
|
}
|
|
else if (t == llvm::Type::Int1Ty) {
|
|
funcname = "_d_array_init_i1";
|
|
}
|
|
else if (t == llvm::Type::Int8Ty) {
|
|
funcname = "_d_array_init_i8";
|
|
}
|
|
else if (t == llvm::Type::Int16Ty) {
|
|
funcname = "_d_array_init_i16";
|
|
}
|
|
else if (t == llvm::Type::Int32Ty) {
|
|
funcname = "_d_array_init_i32";
|
|
}
|
|
else if (t == llvm::Type::Int64Ty) {
|
|
funcname = "_d_array_init_i64";
|
|
}
|
|
else if (t == llvm::Type::FloatTy) {
|
|
funcname = "_d_array_init_float";
|
|
}
|
|
else if (t == llvm::Type::DoubleTy) {
|
|
funcname = "_d_array_init_double";
|
|
}
|
|
else {
|
|
Logger::cout() << *ptr->getType() << " = " << *val->getType() << '\n';
|
|
assert(0);
|
|
}
|
|
|
|
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, funcname);
|
|
assert(fn);
|
|
Logger::cout() << "calling array init function: " << *fn <<'\n';
|
|
llvm::CallInst* call = llvm::CallInst::Create(fn, args.begin(), args.end(), "", gIR->scopebb());
|
|
call->setCallingConv(llvm::CallingConv::C);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void DtoSetArray(llvm::Value* arr, llvm::Value* dim, llvm::Value* ptr)
|
|
{
|
|
Logger::println("DtoSetArray");
|
|
LOG_SCOPE;
|
|
|
|
Logger::cout() << "arr = " << *arr << '\n';
|
|
Logger::cout() << "dim = " << *dim << '\n';
|
|
Logger::cout() << "ptr = " << *ptr << '\n';
|
|
|
|
const llvm::StructType* st = isaStruct(arr->getType()->getContainedType(0));
|
|
|
|
llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
|
|
llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
|
|
|
|
llvm::Value* arrdim = DtoGEP(arr,zero,zero,"tmp",gIR->scopebb());
|
|
Logger::cout() << "arrdim = " << *arrdim << '\n';
|
|
new llvm::StoreInst(dim, arrdim, gIR->scopebb());
|
|
|
|
llvm::Value* arrptr = DtoGEP(arr,zero,one,"tmp",gIR->scopebb());
|
|
Logger::cout() << "arrptr = " << *arrptr << '\n';
|
|
new llvm::StoreInst(ptr, arrptr, gIR->scopebb());
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
llvm::Constant* DtoConstArrayInitializer(ArrayInitializer* arrinit)
|
|
{
|
|
Logger::println("DtoConstArrayInitializer: %s | %s", arrinit->toChars(), arrinit->type->toChars());
|
|
LOG_SCOPE;
|
|
|
|
Type* arrinittype = DtoDType(arrinit->type);
|
|
|
|
Type* t;
|
|
integer_t tdim;
|
|
if (arrinittype->ty == Tsarray) {
|
|
Logger::println("static array");
|
|
TypeSArray* tsa = (TypeSArray*)arrinittype;
|
|
tdim = tsa->dim->toInteger();
|
|
t = tsa;
|
|
}
|
|
else if (arrinittype->ty == Tarray) {
|
|
Logger::println("dynamic array");
|
|
t = arrinittype;
|
|
tdim = arrinit->dim;
|
|
}
|
|
else
|
|
assert(0);
|
|
|
|
Logger::println("dim = %u", tdim);
|
|
|
|
std::vector<llvm::Constant*> inits(tdim, NULL);
|
|
|
|
Type* arrnext = arrinittype->next;
|
|
const llvm::Type* elemty = DtoType(arrinittype->next);
|
|
|
|
assert(arrinit->index.dim == arrinit->value.dim);
|
|
for (unsigned i=0,j=0; i < tdim; ++i)
|
|
{
|
|
Initializer* init = 0;
|
|
Expression* idx;
|
|
|
|
if (j < arrinit->index.dim)
|
|
idx = (Expression*)arrinit->index.data[j];
|
|
else
|
|
idx = NULL;
|
|
|
|
llvm::Constant* v = NULL;
|
|
|
|
if (idx)
|
|
{
|
|
Logger::println("%d has idx", i);
|
|
// this is pretty weird :/ idx->type turned out NULL for the initializer:
|
|
// const in6_addr IN6ADDR_ANY = { s6_addr8: [0] };
|
|
// in std.c.linux.socket
|
|
if (idx->type) {
|
|
Logger::println("has idx->type", i);
|
|
//integer_t k = idx->toInteger();
|
|
//Logger::println("getting value for exp: %s | %s", idx->toChars(), arrnext->toChars());
|
|
llvm::Constant* cc = idx->toConstElem(gIR);
|
|
Logger::println("value gotten");
|
|
assert(cc != NULL);
|
|
llvm::ConstantInt* ci = llvm::dyn_cast<llvm::ConstantInt>(cc);
|
|
assert(ci != NULL);
|
|
uint64_t k = ci->getZExtValue();
|
|
if (i == k)
|
|
{
|
|
init = (Initializer*)arrinit->value.data[j];
|
|
assert(init);
|
|
++j;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (j < arrinit->value.dim) {
|
|
init = (Initializer*)arrinit->value.data[j];
|
|
++j;
|
|
}
|
|
else
|
|
v = arrnext->defaultInit()->toConstElem(gIR);
|
|
}
|
|
|
|
if (!v)
|
|
v = DtoConstInitializer(t->next, init);
|
|
assert(v);
|
|
|
|
inits[i] = v;
|
|
Logger::cout() << "llval: " << *v << '\n';
|
|
}
|
|
|
|
Logger::println("building constant array");
|
|
const llvm::ArrayType* arrty = llvm::ArrayType::get(elemty,tdim);
|
|
llvm::Constant* constarr = llvm::ConstantArray::get(arrty, inits);
|
|
|
|
if (arrinittype->ty == Tsarray)
|
|
return constarr;
|
|
else
|
|
assert(arrinittype->ty == Tarray);
|
|
|
|
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(arrty,true,llvm::GlobalValue::InternalLinkage,constarr,"constarray",gIR->module);
|
|
llvm::Constant* idxs[2] = { DtoConstUint(0), DtoConstUint(0) };
|
|
llvm::Constant* gep = llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2);
|
|
return DtoConstSlice(DtoConstSize_t(tdim),gep);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
static llvm::Value* get_slice_ptr(DSliceValue* e, llvm::Value*& sz)
|
|
{
|
|
const llvm::Type* t = e->ptr->getType()->getContainedType(0);
|
|
llvm::Value* ret = 0;
|
|
if (e->len != 0) {
|
|
// this means it's a real slice
|
|
ret = e->ptr;
|
|
|
|
size_t elembsz = getABITypeSize(ret->getType());
|
|
llvm::ConstantInt* elemsz = llvm::ConstantInt::get(DtoSize_t(), elembsz, false);
|
|
|
|
if (isaConstantInt(e->len)) {
|
|
sz = llvm::ConstantExpr::getMul(elemsz, isaConstant(e->len));
|
|
}
|
|
else {
|
|
sz = llvm::BinaryOperator::createMul(elemsz,e->len,"tmp",gIR->scopebb());
|
|
}
|
|
}
|
|
else if (isaArray(t)) {
|
|
ret = DtoGEPi(e->ptr, 0, 0, "tmp", gIR->scopebb());
|
|
|
|
size_t elembsz = getABITypeSize(ret->getType()->getContainedType(0));
|
|
llvm::ConstantInt* elemsz = llvm::ConstantInt::get(DtoSize_t(), elembsz, false);
|
|
|
|
size_t numelements = isaArray(t)->getNumElements();
|
|
llvm::ConstantInt* nelems = llvm::ConstantInt::get(DtoSize_t(), numelements, false);
|
|
|
|
sz = llvm::ConstantExpr::getMul(elemsz, nelems);
|
|
}
|
|
else if (isaStruct(t)) {
|
|
ret = DtoGEPi(e->ptr, 0, 1, "tmp", gIR->scopebb());
|
|
ret = new llvm::LoadInst(ret, "tmp", gIR->scopebb());
|
|
|
|
size_t elembsz = getABITypeSize(ret->getType()->getContainedType(0));
|
|
llvm::ConstantInt* elemsz = llvm::ConstantInt::get(DtoSize_t(), elembsz, false);
|
|
|
|
llvm::Value* len = DtoGEPi(e->ptr, 0, 0, "tmp", gIR->scopebb());
|
|
len = new llvm::LoadInst(len, "tmp", gIR->scopebb());
|
|
sz = llvm::BinaryOperator::createMul(len,elemsz,"tmp",gIR->scopebb());
|
|
}
|
|
else {
|
|
assert(0);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void DtoArrayCopySlices(DSliceValue* dst, DSliceValue* src)
|
|
{
|
|
Logger::println("ArrayCopySlices");
|
|
const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty);
|
|
|
|
llvm::Value* sz1;
|
|
llvm::Value* dstarr = new llvm::BitCastInst(get_slice_ptr(dst,sz1),arrty,"tmp",gIR->scopebb());
|
|
|
|
llvm::Value* sz2;
|
|
llvm::Value* srcarr = new llvm::BitCastInst(get_slice_ptr(src,sz2),arrty,"tmp",gIR->scopebb());
|
|
|
|
llvm::Function* fn = (global.params.is64bit) ? LLVM_DeclareMemCpy64() : LLVM_DeclareMemCpy32();
|
|
std::vector<llvm::Value*> llargs;
|
|
llargs.resize(4);
|
|
llargs[0] = dstarr;
|
|
llargs[1] = srcarr;
|
|
llargs[2] = sz1;
|
|
llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
|
|
|
|
llvm::CallInst::Create(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
|
|
}
|
|
|
|
void DtoArrayCopyToSlice(DSliceValue* dst, DValue* src)
|
|
{
|
|
Logger::println("ArrayCopyToSlice");
|
|
const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty);
|
|
|
|
llvm::Value* sz1;
|
|
llvm::Value* dstarr = new llvm::BitCastInst(get_slice_ptr(dst,sz1),arrty,"tmp",gIR->scopebb());
|
|
llvm::Value* srcarr = new llvm::BitCastInst(DtoArrayPtr(src),arrty,"tmp",gIR->scopebb());
|
|
|
|
llvm::Function* fn = (global.params.is64bit) ? LLVM_DeclareMemCpy64() : LLVM_DeclareMemCpy32();
|
|
std::vector<llvm::Value*> llargs;
|
|
llargs.resize(4);
|
|
llargs[0] = dstarr;
|
|
llargs[1] = srcarr;
|
|
llargs[2] = sz1;
|
|
llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
|
|
|
|
llvm::CallInst::Create(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
void DtoStaticArrayCopy(llvm::Value* dst, llvm::Value* src)
|
|
{
|
|
Logger::cout() << "static array copy: " << *dst << " from " << *src << '\n';
|
|
assert(dst->getType() == src->getType());
|
|
size_t arrsz = getABITypeSize(dst->getType()->getContainedType(0));
|
|
llvm::Value* n = llvm::ConstantInt::get(DtoSize_t(), arrsz, false);
|
|
|
|
const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty);
|
|
llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb());
|
|
llvm::Value* srcarr = new llvm::BitCastInst(src,arrty,"tmp",gIR->scopebb());
|
|
|
|
llvm::Function* fn = (global.params.is64bit) ? LLVM_DeclareMemCpy64() : LLVM_DeclareMemCpy32();
|
|
std::vector<llvm::Value*> llargs;
|
|
llargs.resize(4);
|
|
llargs[0] = dstarr;
|
|
llargs[1] = srcarr;
|
|
llargs[2] = n;
|
|
llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
|
|
|
|
llvm::CallInst::Create(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
llvm::Constant* DtoConstSlice(llvm::Constant* dim, llvm::Constant* ptr)
|
|
{
|
|
std::vector<const llvm::Type*> types;
|
|
types.push_back(dim->getType());
|
|
types.push_back(ptr->getType());
|
|
const llvm::StructType* type = llvm::StructType::get(types);
|
|
std::vector<llvm::Constant*> values;
|
|
values.push_back(dim);
|
|
values.push_back(ptr);
|
|
return llvm::ConstantStruct::get(type,values);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
DSliceValue* DtoNewDynArray(Type* arrayType, DValue* dim, bool defaultInit)
|
|
{
|
|
Logger::println("DtoNewDynArray : %s", arrayType->toChars());
|
|
LOG_SCOPE;
|
|
|
|
bool zeroInit = arrayType->toBasetype()->nextOf()->isZeroInit();
|
|
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, zeroInit ? "_d_newarrayT" : "_d_newarrayiT" );
|
|
|
|
llvm::SmallVector<llvm::Value*,2> args;
|
|
args.push_back(DtoTypeInfoOf(arrayType));
|
|
assert(DtoType(dim->getType()) == DtoSize_t());
|
|
args.push_back(dim->getRVal());
|
|
|
|
llvm::Value* newptr = gIR->ir->CreateCall(fn, args.begin(), args.end(), ".gc_mem");
|
|
const llvm::Type* dstType = DtoType(arrayType)->getContainedType(1);
|
|
if (newptr->getType() != dstType)
|
|
newptr = DtoBitCast(newptr, dstType, ".gc_mem");
|
|
|
|
Logger::cout() << "final ptr = " << *newptr << '\n';
|
|
|
|
#if 0
|
|
if (defaultInit) {
|
|
DValue* e = dty->defaultInit()->toElem(gIR);
|
|
DtoArrayInit(newptr,dim,e->getRVal());
|
|
}
|
|
#endif
|
|
|
|
return new DSliceValue(arrayType, args[1], newptr);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
DSliceValue* DtoResizeDynArray(Type* arrayType, DValue* array, DValue* newdim)
|
|
{
|
|
Logger::println("DtoResizeDynArray : %s", arrayType->toChars());
|
|
LOG_SCOPE;
|
|
|
|
assert(array);
|
|
assert(newdim);
|
|
assert(arrayType);
|
|
assert(arrayType->toBasetype()->ty == Tarray);
|
|
|
|
bool zeroInit = arrayType->toBasetype()->nextOf()->isZeroInit();
|
|
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, zeroInit ? "_d_arraysetlengthT" : "_d_arraysetlengthiT" );
|
|
|
|
llvm::SmallVector<llvm::Value*,4> args;
|
|
args.push_back(DtoTypeInfoOf(arrayType));
|
|
args.push_back(newdim->getRVal());
|
|
args.push_back(DtoArrayLen(array));
|
|
llvm::Value* arrPtr = DtoArrayPtr(array);
|
|
Logger::cout() << "arrPtr = " << *arrPtr << '\n';
|
|
args.push_back(DtoBitCast(arrPtr, fn->getFunctionType()->getParamType(3), "tmp"));
|
|
|
|
llvm::Value* newptr = gIR->ir->CreateCall(fn, args.begin(), args.end(), ".gc_mem");
|
|
if (newptr->getType() != arrPtr->getType())
|
|
newptr = DtoBitCast(newptr, arrPtr->getType(), ".gc_mem");
|
|
|
|
return new DSliceValue(arrayType, newdim->getRVal(), newptr);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
DSliceValue* DtoCatAssignElement(DValue* array, Expression* exp)
|
|
{
|
|
Logger::println("DtoCatAssignElement");
|
|
LOG_SCOPE;
|
|
|
|
assert(array);
|
|
|
|
llvm::Value* idx = DtoArrayLen(array);
|
|
llvm::Value* one = DtoConstSize_t(1);
|
|
llvm::Value* len = gIR->ir->CreateAdd(idx,one,"tmp");
|
|
|
|
DValue* newdim = new DImValue(Type::tsize_t, len);
|
|
DSliceValue* slice = DtoResizeDynArray(array->getType(), array, newdim);
|
|
|
|
llvm::Value* ptr = slice->ptr;
|
|
ptr = llvm::GetElementPtrInst::Create(ptr, idx, "tmp", gIR->scopebb());
|
|
|
|
DValue* dptr = new DVarValue(exp->type, ptr, true);
|
|
|
|
gIR->exps.push_back(IRExp(0,exp,dptr));
|
|
DValue* e = exp->toElem(gIR);
|
|
gIR->exps.pop_back();
|
|
|
|
if (!e->inPlace())
|
|
DtoAssign(dptr, e);
|
|
|
|
return slice;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
DSliceValue* DtoCatAssignArray(DValue* arr, Expression* exp)
|
|
{
|
|
Logger::println("DtoCatAssignArray");
|
|
LOG_SCOPE;
|
|
|
|
DValue* e = exp->toElem(gIR);
|
|
|
|
llvm::Value *len1, *len2, *src1, *src2, *res;
|
|
|
|
len1 = DtoArrayLen(arr);
|
|
len2 = DtoArrayLen(e);
|
|
res = gIR->ir->CreateAdd(len1,len2,"tmp");
|
|
|
|
DValue* newdim = new DImValue(Type::tsize_t, res);
|
|
DSliceValue* slice = DtoResizeDynArray(arr->getType(), arr, newdim);
|
|
|
|
src1 = slice->ptr;
|
|
src2 = DtoArrayPtr(e);
|
|
|
|
// advance ptr
|
|
src1 = gIR->ir->CreateGEP(src1,len1,"tmp");
|
|
|
|
// memcpy
|
|
llvm::Value* elemSize = DtoConstSize_t(getABITypeSize(src2->getType()->getContainedType(0)));
|
|
llvm::Value* bytelen = gIR->ir->CreateMul(len2, elemSize, "tmp");
|
|
DtoMemCpy(src1,src2,bytelen);
|
|
|
|
return slice;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
DSliceValue* DtoCatArrays(Type* type, Expression* exp1, Expression* exp2)
|
|
{
|
|
Logger::println("DtoCatArrays");
|
|
LOG_SCOPE;
|
|
|
|
Type* t1 = DtoDType(exp1->type);
|
|
Type* t2 = DtoDType(exp2->type);
|
|
|
|
assert(t1->ty == Tarray);
|
|
assert(t1->ty == t2->ty);
|
|
|
|
DValue* e1 = exp1->toElem(gIR);
|
|
DValue* e2 = exp2->toElem(gIR);
|
|
|
|
llvm::Value *len1, *len2, *src1, *src2, *res;
|
|
|
|
len1 = DtoArrayLen(e1);
|
|
len2 = DtoArrayLen(e2);
|
|
res = gIR->ir->CreateAdd(len1,len2,"tmp");
|
|
|
|
DValue* lenval = new DImValue(Type::tsize_t, res);
|
|
DSliceValue* slice = DtoNewDynArray(type, lenval, false);
|
|
llvm::Value* mem = slice->ptr;
|
|
|
|
src1 = DtoArrayPtr(e1);
|
|
src2 = DtoArrayPtr(e2);
|
|
|
|
// first memcpy
|
|
llvm::Value* elemSize = DtoConstSize_t(getABITypeSize(src1->getType()->getContainedType(0)));
|
|
llvm::Value* bytelen = gIR->ir->CreateMul(len1, elemSize, "tmp");
|
|
DtoMemCpy(mem,src1,bytelen);
|
|
|
|
// second memcpy
|
|
mem = gIR->ir->CreateGEP(mem,len1,"tmp");
|
|
bytelen = gIR->ir->CreateMul(len2, elemSize, "tmp");
|
|
DtoMemCpy(mem,src2,bytelen);
|
|
|
|
return slice;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
DSliceValue* DtoCatArrayElement(Type* type, Expression* exp1, Expression* exp2)
|
|
{
|
|
Logger::println("DtoCatArrayElement");
|
|
LOG_SCOPE;
|
|
|
|
Type* t1 = DtoDType(exp1->type);
|
|
Type* t2 = DtoDType(exp2->type);
|
|
|
|
DValue* e1 = exp1->toElem(gIR);
|
|
DValue* e2 = exp2->toElem(gIR);
|
|
|
|
llvm::Value *len1, *src1, *res;
|
|
|
|
// handle prefix case, eg. int~int[]
|
|
if (t2->next && t1 == DtoDType(t2->next))
|
|
{
|
|
len1 = DtoArrayLen(e2);
|
|
res = gIR->ir->CreateAdd(len1,DtoConstSize_t(1),"tmp");
|
|
|
|
DValue* lenval = new DImValue(Type::tsize_t, res);
|
|
DSliceValue* slice = DtoNewDynArray(type, lenval, false);
|
|
llvm::Value* mem = slice->ptr;
|
|
|
|
DVarValue* memval = new DVarValue(e1->getType(), mem, true);
|
|
DtoAssign(memval, e1);
|
|
|
|
src1 = DtoArrayPtr(e2);
|
|
|
|
mem = gIR->ir->CreateGEP(mem,DtoConstSize_t(1),"tmp");
|
|
|
|
llvm::Value* elemSize = DtoConstSize_t(getABITypeSize(src1->getType()->getContainedType(0)));
|
|
llvm::Value* bytelen = gIR->ir->CreateMul(len1, elemSize, "tmp");
|
|
DtoMemCpy(mem,src1,bytelen);
|
|
|
|
|
|
return slice;
|
|
}
|
|
// handle suffix case, eg. int[]~int
|
|
else
|
|
{
|
|
len1 = DtoArrayLen(e1);
|
|
res = gIR->ir->CreateAdd(len1,DtoConstSize_t(1),"tmp");
|
|
|
|
DValue* lenval = new DImValue(Type::tsize_t, res);
|
|
DSliceValue* slice = DtoNewDynArray(type, lenval, false);
|
|
llvm::Value* mem = slice->ptr;
|
|
|
|
src1 = DtoArrayPtr(e1);
|
|
|
|
llvm::Value* elemSize = DtoConstSize_t(getABITypeSize(src1->getType()->getContainedType(0)));
|
|
llvm::Value* bytelen = gIR->ir->CreateMul(len1, elemSize, "tmp");
|
|
DtoMemCpy(mem,src1,bytelen);
|
|
|
|
mem = gIR->ir->CreateGEP(mem,len1,"tmp");
|
|
DVarValue* memval = new DVarValue(e2->getType(), mem, true);
|
|
DtoAssign(memval, e2);
|
|
|
|
return slice;
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
// helper for eq and cmp
|
|
static llvm::Value* DtoArrayEqCmp_impl(const char* func, DValue* l, DValue* r, bool useti)
|
|
{
|
|
Logger::println("comparing arrays");
|
|
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, func);
|
|
assert(fn);
|
|
|
|
llvm::Value* lmem;
|
|
llvm::Value* rmem;
|
|
|
|
// cast static arrays to dynamic ones, this turns them into DSliceValues
|
|
Logger::println("casting to dynamic arrays");
|
|
Type* l_ty = DtoDType(l->getType());
|
|
Type* r_ty = DtoDType(r->getType());
|
|
assert(l_ty->next == r_ty->next);
|
|
if ((l_ty->ty == Tsarray) || (r_ty->ty == Tsarray)) {
|
|
Type* a_ty = new Type(Tarray, l_ty->next);
|
|
if (l_ty->ty == Tsarray)
|
|
l = DtoCastArray(l, a_ty);
|
|
if (r_ty->ty == Tsarray)
|
|
r = DtoCastArray(r, a_ty);
|
|
}
|
|
|
|
Logger::println("giving storage");
|
|
|
|
// we need to give slices storage
|
|
if (l->isSlice()) {
|
|
lmem = new llvm::AllocaInst(DtoType(l->getType()), "tmpparam", gIR->topallocapoint());
|
|
DtoSetArray(lmem, DtoArrayLen(l), DtoArrayPtr(l));
|
|
}
|
|
// also null
|
|
else if (l->isNull())
|
|
{
|
|
lmem = new llvm::AllocaInst(DtoType(l->getType()), "tmpparam", gIR->topallocapoint());
|
|
DtoSetArray(lmem, llvm::Constant::getNullValue(DtoSize_t()), llvm::Constant::getNullValue(DtoType(l->getType()->next->pointerTo())));
|
|
}
|
|
else
|
|
lmem = l->getRVal();
|
|
|
|
// and for the rvalue ...
|
|
// we need to give slices storage
|
|
if (r->isSlice()) {
|
|
rmem = new llvm::AllocaInst(DtoType(r->getType()), "tmpparam", gIR->topallocapoint());
|
|
DtoSetArray(rmem, DtoArrayLen(r), DtoArrayPtr(r));
|
|
}
|
|
// also null
|
|
else if (r->isNull())
|
|
{
|
|
rmem = new llvm::AllocaInst(DtoType(r->getType()), "tmpparam", gIR->topallocapoint());
|
|
DtoSetArray(rmem, llvm::Constant::getNullValue(DtoSize_t()), llvm::Constant::getNullValue(DtoType(r->getType()->next->pointerTo())));
|
|
}
|
|
else
|
|
rmem = r->getRVal();
|
|
|
|
const llvm::Type* pt = fn->getFunctionType()->getParamType(0);
|
|
|
|
std::vector<llvm::Value*> args;
|
|
Logger::cout() << "bitcasting to " << *pt << '\n';
|
|
Logger::cout() << *lmem << '\n';
|
|
Logger::cout() << *rmem << '\n';
|
|
args.push_back(DtoBitCast(lmem,pt));
|
|
args.push_back(DtoBitCast(rmem,pt));
|
|
|
|
// pass element typeinfo ?
|
|
if (useti) {
|
|
TypeInfoDeclaration* ti = DtoDType(l->getType())->next->getTypeInfoDeclaration();
|
|
DtoForceConstInitDsymbol(ti);
|
|
Logger::cout() << "typeinfo decl: " << *ti->ir.getIrValue() << '\n';
|
|
|
|
pt = fn->getFunctionType()->getParamType(2);
|
|
args.push_back(DtoBitCast(ti->ir.getIrValue(), pt));
|
|
}
|
|
|
|
return gIR->ir->CreateCall(fn, args.begin(), args.end(), "tmp");
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
llvm::Value* DtoArrayEquals(TOK op, DValue* l, DValue* r)
|
|
{
|
|
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_adEq");
|
|
assert(fn);
|
|
|
|
llvm::Value* res = DtoArrayEqCmp_impl("_adEq", l, r, true);
|
|
if (op == TOKnotequal)
|
|
res = gIR->ir->CreateNot(res, "tmp");
|
|
|
|
return res;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
llvm::Value* DtoArrayCompare(TOK op, DValue* l, DValue* r)
|
|
{
|
|
llvm::Value* res = 0;
|
|
|
|
llvm::ICmpInst::Predicate cmpop;
|
|
bool skip = false;
|
|
|
|
switch(op)
|
|
{
|
|
case TOKlt:
|
|
case TOKul:
|
|
cmpop = llvm::ICmpInst::ICMP_SLT;
|
|
break;
|
|
case TOKle:
|
|
case TOKule:
|
|
cmpop = llvm::ICmpInst::ICMP_SLE;
|
|
break;
|
|
case TOKgt:
|
|
case TOKug:
|
|
cmpop = llvm::ICmpInst::ICMP_SGT;
|
|
break;
|
|
case TOKge:
|
|
case TOKuge:
|
|
cmpop = llvm::ICmpInst::ICMP_SGE;
|
|
break;
|
|
case TOKue:
|
|
cmpop = llvm::ICmpInst::ICMP_EQ;
|
|
break;
|
|
case TOKlg:
|
|
cmpop = llvm::ICmpInst::ICMP_NE;
|
|
break;
|
|
case TOKleg:
|
|
skip = true;
|
|
res = llvm::ConstantInt::getTrue();
|
|
break;
|
|
case TOKunord:
|
|
skip = true;
|
|
res = llvm::ConstantInt::getFalse();
|
|
break;
|
|
|
|
default:
|
|
assert(0);
|
|
}
|
|
|
|
if (!skip)
|
|
{
|
|
Type* t = DtoDType(DtoDType(l->getType())->next);
|
|
if (t->ty == Tchar)
|
|
res = DtoArrayEqCmp_impl("_adCmpChar", l, r, false);
|
|
else
|
|
res = DtoArrayEqCmp_impl("_adCmp", l, r, true);
|
|
res = new llvm::ICmpInst(cmpop, res, DtoConstInt(0), "tmp", gIR->scopebb());
|
|
}
|
|
|
|
assert(res);
|
|
return res;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
llvm::Value* DtoArrayCastLength(llvm::Value* len, const llvm::Type* elemty, const llvm::Type* newelemty)
|
|
{
|
|
Logger::println("DtoArrayCastLength");
|
|
LOG_SCOPE;
|
|
|
|
assert(len);
|
|
assert(elemty);
|
|
assert(newelemty);
|
|
|
|
size_t esz = getABITypeSize(elemty);
|
|
size_t nsz = getABITypeSize(newelemty);
|
|
if (esz == nsz)
|
|
return len;
|
|
|
|
std::vector<llvm::Value*> args;
|
|
args.push_back(len);
|
|
args.push_back(llvm::ConstantInt::get(DtoSize_t(), esz, false));
|
|
args.push_back(llvm::ConstantInt::get(DtoSize_t(), nsz, false));
|
|
|
|
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_array_cast_len");
|
|
return llvm::CallInst::Create(fn, args.begin(), args.end(), "tmp", gIR->scopebb());
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
llvm::Value* DtoDynArrayIs(TOK op, llvm::Value* l, llvm::Value* r)
|
|
{
|
|
llvm::ICmpInst::Predicate pred = (op == TOKidentity) ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE;
|
|
|
|
if (r == NULL) {
|
|
llvm::Value* ll = gIR->ir->CreateLoad(DtoGEPi(l, 0,0, "tmp"),"tmp");
|
|
llvm::Value* rl = llvm::Constant::getNullValue(ll->getType());//DtoConstSize_t(0);
|
|
llvm::Value* b1 = gIR->ir->CreateICmp(pred,ll,rl,"tmp");
|
|
|
|
llvm::Value* lp = gIR->ir->CreateLoad(DtoGEPi(l, 0,1, "tmp"),"tmp");
|
|
const llvm::PointerType* pty = isaPointer(lp->getType());
|
|
llvm::Value* rp = llvm::ConstantPointerNull::get(pty);
|
|
llvm::Value* b2 = gIR->ir->CreateICmp(pred,lp,rp,"tmp");
|
|
|
|
llvm::Value* b = gIR->ir->CreateAnd(b1,b2,"tmp");
|
|
return b;
|
|
}
|
|
else {
|
|
assert(l->getType() == r->getType());
|
|
|
|
llvm::Value* ll = gIR->ir->CreateLoad(DtoGEPi(l, 0,0, "tmp"),"tmp");
|
|
llvm::Value* rl = gIR->ir->CreateLoad(DtoGEPi(r, 0,0, "tmp"),"tmp");
|
|
llvm::Value* b1 = gIR->ir->CreateICmp(pred,ll,rl,"tmp");
|
|
|
|
llvm::Value* lp = gIR->ir->CreateLoad(DtoGEPi(l, 0,1, "tmp"),"tmp");
|
|
llvm::Value* rp = gIR->ir->CreateLoad(DtoGEPi(r, 0,1, "tmp"),"tmp");
|
|
llvm::Value* b2 = gIR->ir->CreateICmp(pred,lp,rp,"tmp");
|
|
|
|
llvm::Value* b = gIR->ir->CreateAnd(b1,b2,"tmp");
|
|
return b;
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
llvm::Constant* DtoConstStaticArray(const llvm::Type* t, llvm::Constant* c)
|
|
{
|
|
const llvm::ArrayType* at = isaArray(t);
|
|
assert(at);
|
|
|
|
if (isaArray(at->getElementType()))
|
|
{
|
|
c = DtoConstStaticArray(at->getElementType(), c);
|
|
}
|
|
else {
|
|
assert(at->getElementType() == c->getType());
|
|
}
|
|
std::vector<llvm::Constant*> initvals;
|
|
initvals.resize(at->getNumElements(), c);
|
|
return llvm::ConstantArray::get(at, initvals);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
llvm::Value* DtoArrayLen(DValue* v)
|
|
{
|
|
Logger::println("DtoArrayLen");
|
|
LOG_SCOPE;
|
|
|
|
Type* t = DtoDType(v->getType());
|
|
if (t->ty == Tarray) {
|
|
if (DSliceValue* s = v->isSlice()) {
|
|
if (s->len) {
|
|
return s->len;
|
|
}
|
|
const llvm::ArrayType* arrTy = isaArray(s->ptr->getType()->getContainedType(0));
|
|
if (arrTy)
|
|
return DtoConstSize_t(arrTy->getNumElements());
|
|
else
|
|
return DtoLoad(DtoGEPi(s->ptr, 0,0, "tmp"));
|
|
}
|
|
return DtoLoad(DtoGEPi(v->getRVal(), 0,0, "tmp"));
|
|
}
|
|
else if (t->ty == Tsarray) {
|
|
assert(!v->isSlice());
|
|
llvm::Value* rv = v->getRVal();
|
|
Logger::cout() << "casting: " << *rv << '\n';
|
|
const llvm::ArrayType* t = isaArray(rv->getType()->getContainedType(0));
|
|
return DtoConstSize_t(t->getNumElements());
|
|
}
|
|
assert(0);
|
|
return 0;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
llvm::Value* DtoArrayPtr(DValue* v)
|
|
{
|
|
Logger::println("DtoArrayPtr");
|
|
LOG_SCOPE;
|
|
|
|
Type* t = DtoDType(v->getType());
|
|
if (t->ty == Tarray) {
|
|
if (DSliceValue* s = v->isSlice()) {
|
|
if (s->len) return s->ptr;
|
|
const llvm::Type* t = s->ptr->getType()->getContainedType(0);
|
|
Logger::cout() << "ptr of full slice: " << *s->ptr << '\n';
|
|
const llvm::ArrayType* arrTy = isaArray(s->ptr->getType()->getContainedType(0));
|
|
if (arrTy)
|
|
return DtoGEPi(s->ptr, 0,0, "tmp");
|
|
else
|
|
return DtoLoad(DtoGEPi(s->ptr, 0,1, "tmp"));
|
|
}
|
|
return DtoLoad(DtoGEPi(v->getRVal(), 0,1, "tmp"));
|
|
}
|
|
else if (t->ty == Tsarray) {
|
|
return DtoGEPi(v->getRVal(), 0,0, "tmp");
|
|
}
|
|
assert(0);
|
|
return 0;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
DValue* DtoCastArray(DValue* u, Type* to)
|
|
{
|
|
Logger::println("DtoCastArray");
|
|
LOG_SCOPE;
|
|
|
|
const llvm::Type* tolltype = DtoType(to);
|
|
|
|
Type* totype = DtoDType(to);
|
|
Type* fromtype = DtoDType(u->getType());
|
|
assert(fromtype->ty == Tarray || fromtype->ty == Tsarray);
|
|
|
|
llvm::Value* rval;
|
|
llvm::Value* rval2;
|
|
bool isslice = false;
|
|
|
|
Logger::cout() << "from array or sarray" << '\n';
|
|
if (totype->ty == Tpointer) {
|
|
Logger::cout() << "to pointer" << '\n';
|
|
rval = DtoArrayPtr(u);
|
|
if (rval->getType() != tolltype)
|
|
rval = gIR->ir->CreateBitCast(rval, tolltype, "tmp");
|
|
}
|
|
else if (totype->ty == Tarray) {
|
|
Logger::cout() << "to array" << '\n';
|
|
const llvm::Type* ptrty = DtoType(totype->next);
|
|
if (ptrty == llvm::Type::VoidTy)
|
|
ptrty = llvm::Type::Int8Ty;
|
|
ptrty = getPtrToType(ptrty);
|
|
|
|
const llvm::Type* ety = DtoType(fromtype->next);
|
|
if (ety == llvm::Type::VoidTy)
|
|
ety = llvm::Type::Int8Ty;
|
|
|
|
if (DSliceValue* usl = u->isSlice()) {
|
|
Logger::println("from slice");
|
|
Logger::cout() << "from: " << *usl->ptr << " to: " << *ptrty << '\n';
|
|
rval = new llvm::BitCastInst(usl->ptr, ptrty, "tmp", gIR->scopebb());
|
|
if (fromtype->next->size() == totype->next->size())
|
|
rval2 = DtoArrayLen(usl);
|
|
else
|
|
rval2 = DtoArrayCastLength(DtoArrayLen(usl), ety, ptrty->getContainedType(0));
|
|
}
|
|
else {
|
|
llvm::Value* uval = u->getRVal();
|
|
if (fromtype->ty == Tsarray) {
|
|
Logger::cout() << "uvalTy = " << *uval->getType() << '\n';
|
|
assert(isaPointer(uval->getType()));
|
|
const llvm::ArrayType* arrty = isaArray(uval->getType()->getContainedType(0));
|
|
rval2 = llvm::ConstantInt::get(DtoSize_t(), arrty->getNumElements(), false);
|
|
rval2 = DtoArrayCastLength(rval2, ety, ptrty->getContainedType(0));
|
|
rval = new llvm::BitCastInst(uval, ptrty, "tmp", gIR->scopebb());
|
|
}
|
|
else {
|
|
llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
|
|
llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
|
|
rval2 = DtoGEP(uval,zero,zero,"tmp",gIR->scopebb());
|
|
rval2 = new llvm::LoadInst(rval2, "tmp", gIR->scopebb());
|
|
rval2 = DtoArrayCastLength(rval2, ety, ptrty->getContainedType(0));
|
|
|
|
rval = DtoGEP(uval,zero,one,"tmp",gIR->scopebb());
|
|
rval = new llvm::LoadInst(rval, "tmp", gIR->scopebb());
|
|
//Logger::cout() << *e->mem->getType() << '|' << *ptrty << '\n';
|
|
rval = new llvm::BitCastInst(rval, ptrty, "tmp", gIR->scopebb());
|
|
}
|
|
}
|
|
isslice = true;
|
|
}
|
|
else if (totype->ty == Tsarray) {
|
|
Logger::cout() << "to sarray" << '\n';
|
|
assert(0);
|
|
}
|
|
else {
|
|
assert(0);
|
|
}
|
|
|
|
if (isslice) {
|
|
Logger::println("isslice");
|
|
return new DSliceValue(to, rval2, rval);
|
|
}
|
|
|
|
return new DImValue(to, rval);
|
|
}
|