[svn r68] Added support for multi-dimensional static arrays.

Several bugfixes to array support.
This commit is contained in:
Tomas Lindquist Olsen
2007-10-25 12:09:13 +02:00
parent 1dcad1c62d
commit 498c442bc1
9 changed files with 140 additions and 25 deletions

View File

@@ -143,24 +143,53 @@ void LLVM_DtoArrayInit(llvm::Value* l, llvm::Value* r)
//////////////////////////////////////////////////////////////////////////////////////////
typedef const llvm::Type* constLLVMTypeP;
static size_t checkRectArrayInit(const llvm::Type* pt, constLLVMTypeP& finalty)
{
if (llvm::isa<llvm::ArrayType>(pt)) {
size_t n = checkRectArrayInit(pt->getContainedType(0), finalty);
size_t ne = llvm::cast<llvm::ArrayType>(pt)->getNumElements();
if (n) return n * ne;
return ne;
}
finalty = pt;
return 0;
}
void LLVM_DtoArrayInit(llvm::Value* ptr, llvm::Value* dim, llvm::Value* val)
{
const llvm::Type* t = ptr->getType()->getContainedType(0);
const llvm::Type* pt = ptr->getType()->getContainedType(0);
const llvm::Type* t = val->getType();
const llvm::Type* finalTy;
if (size_t arrsz = checkRectArrayInit(pt, finalTy)) {
assert(finalTy == t);
llvm::Constant* c = llvm::cast_or_null<llvm::Constant>(dim);
assert(c);
dim = llvm::ConstantExpr::getMul(c, LLVM_DtoConstSize_t(arrsz));
ptr = gIR->ir->CreateBitCast(ptr, llvm::PointerType::get(finalTy), "tmp");
}
else if (llvm::isa<llvm::StructType>(t)) {
assert(0);
}
else {
assert(t == pt);
}
std::vector<llvm::Value*> args;
args.push_back(ptr);
args.push_back(dim);
args.push_back(val);
const char* funcname = NULL;
if (llvm::isa<llvm::PointerType>(t)) {
funcname = "_d_array_init_pointer";
const llvm::Type* dstty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty));
if (args[0]->getType() != dstty)
args[0] = new llvm::BitCastInst(args[0],dstty,"tmp",gIR->scopebb());
const llvm::Type* valty = llvm::PointerType::get(llvm::Type::Int8Ty);
if (args[2]->getType() != valty)
args[2] = new llvm::BitCastInst(args[2],valty,"tmp",gIR->scopebb());
@@ -187,6 +216,7 @@ void LLVM_DtoArrayInit(llvm::Value* ptr, llvm::Value* dim, llvm::Value* val)
funcname = "_d_array_init_double";
}
else {
Logger::cout() << *ptr->getType() << " = " << *val->getType() << '\n';
assert(0);
}
@@ -607,3 +637,21 @@ llvm::Value* LLVM_DtoDynArrayIs(TOK op, llvm::Value* l, llvm::Value* r)
llvm::Value* b = gIR->ir->CreateAnd(b1,b2,"tmp");
return b;
}
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Constant* LLVM_DtoConstantStaticArray(const llvm::Type* t, llvm::Constant* c)
{
assert(llvm::isa<llvm::ArrayType>(t));
const llvm::ArrayType* at = llvm::cast<llvm::ArrayType>(t);
if (llvm::isa<llvm::ArrayType>(at->getElementType()))
{
c = LLVM_DtoConstantStaticArray(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);
}

View File

@@ -6,6 +6,7 @@ const llvm::ArrayType* LLVM_DtoStaticArrayType(Type* t);
llvm::Constant* LLVM_DtoConstArrayInitializer(ArrayInitializer* si);
llvm::Constant* LLVM_DtoConstantSlice(llvm::Constant* dim, llvm::Constant* ptr);
llvm::Constant* LLVM_DtoConstantStaticArray(const llvm::Type* t, llvm::Constant* c);
void LLVM_DtoArrayCopy(elem* dst, elem* src);
void LLVM_DtoArrayInit(llvm::Value* l, llvm::Value* r);

View File

@@ -1458,32 +1458,41 @@ elem* SymOffExp::toElem(IRState* p)
vdt->sym->offsetToIndex(t->next, offset, dst);
llvm::Value* ptr = llvalue;
assert(ptr);
e->mem = LLVM_DtoGEP(ptr,dst,"tmp",p->scopebb());
e->mem = LLVM_DtoGEP(ptr,dst,"tmp");
e->type = elem::VAL;
e->field = true;
}
else if (vdtype->ty == Tsarray) {
/*e = new elem;
llvm::Value* idx0 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
e->val = new llvm::GetElementPtrInst(vd->llvmValue,idx0,idx0,"tmp",p->scopebb());*/
e = new elem;
llvm::Value* idx0 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
//llvm::Value* idx1 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
e->mem = LLVM_DtoGEP(llvalue,idx0,idx0,"tmp",p->scopebb());
assert(llvalue);
e->arg = llvalue;
e->type = elem::VAL;
const llvm::Type* llt = LLVM_DtoType(t);
llvm::Value* off = 0;
if (offset != 0) {
Logger::println("offset = %d\n", offset);
}
if (llvalue->getType() != llt) {
e->mem = p->ir->CreateBitCast(llvalue, llt, "tmp");
if (offset != 0)
e->mem = LLVM_DtoGEPi(e->mem, offset, "tmp");
}
else {
assert(offset == 0);
e->mem = LLVM_DtoGEPi(llvalue,0,0,"tmp");
}
}
else if (offset == 0) {
e = new elem;
e->type = elem::VAL;
assert(llvalue);
e->mem = llvalue;
const llvm::Type* llt = LLVM_DtoType(t);
if (llvalue->getType() != llt) {
Logger::cout() << "llt is:" << *llt << '\n';
//const llvm::PointerType* vpty = llvm::PointerType::get(llvm::Type::Int8Ty);
e->mem = p->ir->CreateBitCast(e->mem, llt, "tmp");
}
e->type = elem::VAL;
}
else {
assert(0);
@@ -2009,6 +2018,7 @@ elem* EqualExp::toElem(IRState* p)
if (t->isintegral() || t->ty == Tpointer)
{
Logger::println("integral or pointer");
llvm::ICmpInst::Predicate cmpop;
switch(op)
{
@@ -2025,6 +2035,7 @@ elem* EqualExp::toElem(IRState* p)
}
else if (t->isfloating())
{
Logger::println("floating");
llvm::FCmpInst::Predicate cmpop;
switch(op)
{
@@ -2041,14 +2052,17 @@ elem* EqualExp::toElem(IRState* p)
}
else if (t->ty == Tsarray)
{
Logger::println("static array");
e->val = LLVM_DtoStaticArrayCompare(op,l->mem,r->mem);
}
else if (t->ty == Tarray)
{
Logger::println("dynamic array");
e->val = LLVM_DtoDynArrayCompare(op,l->mem,r->mem);
}
else if (t->ty == Tdelegate)
{
Logger::println("delegate");
e->val = LLVM_DtoCompareDelegate(op,l->mem,r->mem);
}
else

View File

@@ -35,6 +35,7 @@
#include "gen/elem.h"
#include "gen/logger.h"
#include "gen/tollvm.h"
#include "gen/arrays.h"
//////////////////////////////////////////////////////////////////////////////////////////
@@ -546,15 +547,7 @@ void VarDeclaration::toObjFile()
// array single value init
else if (llvm::isa<llvm::ArrayType>(_type))
{
const llvm::ArrayType* at = llvm::cast<llvm::ArrayType>(_type);
if (at->getElementType() == _init->getType()) {
std::vector<llvm::Constant*> initvals;
initvals.resize(at->getNumElements(), _init);
_init = llvm::ConstantArray::get(at, initvals);
}
else {
assert(0);
}
_init = LLVM_DtoConstantStaticArray(_type, _init);
}
else {
Logger::cout() << "Unexpected initializer type: " << *_type << '\n';
@@ -562,6 +555,7 @@ void VarDeclaration::toObjFile()
}
}
Logger::cout() << "final init = " << *_init << '\n';
gvar->setInitializer(_init);
}

View File

@@ -1,7 +1,16 @@
module internal.arrays;
private import llvm.intrinsic;
extern(C):
int memcmp(void*,void*,size_t);
version(LLVM64)
alias llvm_memcpy_i64 llvm_memcpy;
else
alias llvm_memcpy_i32 llvm_memcpy;
// per-element array init routines
void _d_array_init_i1(bool* a, size_t n, bool v)
@@ -68,8 +77,17 @@ void _d_array_init_pointer(void** a, size_t n, void* v)
*p++ = v;
}
void _d_array_init(void* a, size_t na, void* v, size_t nv)
{
auto p = a;
auto end = a + na*nv;
while (p !is end) {
llvm_memcpy(p,v,nv,0);
p += nv;
}
}
// array comparison routines
int memcmp(void*,void*,size_t);
bool _d_static_array_eq(void* lhs, void* rhs, size_t bytesize)
{

10
test/multiarr1.d Normal file
View File

@@ -0,0 +1,10 @@
module multiarr1;
void main()
{
int[16][16] a;
a[10][13] = 42;
assert(a[0][0] == 0);
assert(a[10][13] == 42);
{assert(*((cast(int*)a)+10*16+13) == 42);}
}

7
test/multiarr2.d Normal file
View File

@@ -0,0 +1,7 @@
module multiarr2;
void main()
{
static float[1][2][3] arr;
assert(arr[2][1][0] !<>= float.nan);
}

10
test/multiarr3.d Normal file
View File

@@ -0,0 +1,10 @@
module multiarr3;
void main()
{
static int[2][2] arr = [[1,2],[3,4]];
assert(arr[0][0] == 1);
assert(arr[0][1] == 2);
assert(arr[1][0] == 3);
assert(arr[1][1] == 4);
}

13
test/multiarr4.d Normal file
View File

@@ -0,0 +1,13 @@
module multiarr4;
void main()
{
char[][] a;
a.length = 2;
a[0] = "hello";
a[1] = "world";
foreach(v;a)
{
printf("%.*s\n", v.length, v.ptr);
}
}