mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-11 18:33:14 +01:00
[svn r68] Added support for multi-dimensional static arrays.
Several bugfixes to array support.
This commit is contained in:
58
gen/arrays.c
58
gen/arrays.c
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
34
gen/toir.c
34
gen/toir.c
@@ -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
|
||||
|
||||
12
gen/toobj.c
12
gen/toobj.c
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
10
test/multiarr1.d
Normal 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
7
test/multiarr2.d
Normal 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
10
test/multiarr3.d
Normal 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
13
test/multiarr4.d
Normal 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user