[svn r44] Lots of bug fixes.

New array literal support
New array ~= operator support (for single element)
New with statement support
More...
This commit is contained in:
Tomas Lindquist Olsen
2007-10-19 07:43:21 +02:00
parent bc02cdd5cf
commit 10db08076c
37 changed files with 1331 additions and 535 deletions

View File

@@ -31,7 +31,8 @@ Declaration::Declaration(Identifier *id)
type = NULL;
storage_class = STCundefined;
protection = PROTundefined;
linkage = LINKdefault;
linkage = LINKdefault;
llvmTouched = false;
}
void Declaration::semantic(Scope *sc)

View File

@@ -125,7 +125,9 @@ struct Declaration : Dsymbol
Declaration *isDeclaration() { return this; }
virtual void toObjFile(); // compile to .obj file
virtual void toObjFile(); // compile to .obj file
bool llvmTouched;
};
/**************************************************************/

View File

@@ -46,6 +46,7 @@ struct Symbol; // back end symbol
namespace llvm
{
class Constant;
class ConstantInt;
}
@@ -147,6 +148,8 @@ struct Expression : Object
// Back end
virtual elem *toElem(IRState *irs);
virtual dt_t **toDt(dt_t **pdt);
// LLVMDC
virtual llvm::Constant *toConstElem(IRState *irs);
};
struct IntegerExp : Expression
@@ -172,6 +175,8 @@ struct IntegerExp : Expression
Expression *toLvalue(Scope *sc, Expression *e);
elem *toElem(IRState *irs);
dt_t **toDt(dt_t **pdt);
// LLVMDC
virtual llvm::Constant *toConstElem(IRState *irs);
};
struct RealExp : Expression
@@ -195,6 +200,8 @@ struct RealExp : Expression
void toMangleBuffer(OutBuffer *buf);
elem *toElem(IRState *irs);
dt_t **toDt(dt_t **pdt);
// LLVMDC
virtual llvm::Constant *toConstElem(IRState *irs);
};
struct ComplexExp : Expression
@@ -298,6 +305,8 @@ struct NullExp : Expression
Expression *interpret(InterState *istate);
elem *toElem(IRState *irs);
dt_t **toDt(dt_t **pdt);
// LLVMDC
virtual llvm::Constant *toConstElem(IRState *irs);
};
struct StringExp : Expression
@@ -326,6 +335,8 @@ struct StringExp : Expression
void toMangleBuffer(OutBuffer *buf);
elem *toElem(IRState *irs);
dt_t **toDt(dt_t **pdt);
// LLVMDC
virtual llvm::Constant *toConstElem(IRState *irs);
};
// Tuple
@@ -376,6 +387,8 @@ struct ArrayLiteralExp : Expression
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
// LLVMDC
virtual llvm::Constant *toConstElem(IRState *irs);
};
struct AssocArrayLiteralExp : Expression
@@ -401,6 +414,8 @@ struct AssocArrayLiteralExp : Expression
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
// LLVMDC
virtual llvm::Constant *toConstElem(IRState *irs);
};
struct StructLiteralExp : Expression
@@ -432,6 +447,8 @@ struct StructLiteralExp : Expression
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
// LLVMDC
virtual llvm::Constant *toConstElem(IRState *irs);
};
struct TypeDotIdExp : Expression
@@ -564,6 +581,8 @@ struct VarExp : Expression
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
//Expression *inlineScan(InlineScanState *iss);
// LLVMDC
virtual llvm::Constant *toConstElem(IRState *irs);
};
// Function/Delegate literal

View File

@@ -192,16 +192,16 @@ Usage:\n\
x86 x86-64 ppc32 ppc64\n\
-nofloat do not emit reference to floating point\n\
-noruntime do not allow code that generates implicit runtime calls\n\
-novalidate do not run the validation pass before writing bitcode\n\
-noverify do not run the validation pass before writing bitcode\n\
-O optimize, same as -O2\n\
-O<n> optimize at level <n> (0-5)\n\
-o- do not write object file\n\
-od<objdir> write object files to directory <objdir>\n\
-of<filename> name output file to <filename>\n\
-op do not strip paths from source file\n\
-profile profile runtime performance of generated code\n\
-profile profile runtime performance of generated code\n\
-quiet suppress unnecessary messages\n\
-release compile release version\n\
-release compile release version\n\
-run srcfile args... run resulting program, passing args\n\
-unittest compile in unit tests\n\
-v verbose\n\
@@ -382,7 +382,7 @@ int main(int argc, char *argv[])
global.params.forceBE = 1;
else if (strcmp(p + 1, "noruntime") == 0)
global.params.noruntime = 1;
else if (strcmp(p + 1, "novalidate") == 0)
else if (strcmp(p + 1, "noverify") == 0)
global.params.novalidate = 1;
else if (p[1] == 'o')
{

View File

@@ -1,8 +1,4 @@
#include "llvm/Constants.h"
#include "llvm/Type.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/CallingConv.h"
#include "gen/llvm.h"
#include "mtype.h"
#include "dsymbol.h"
@@ -218,16 +214,17 @@ void LLVM_DtoSetArray(llvm::Value* arr, llvm::Value* dim, llvm::Value* ptr)
}
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Constant* LLVM_DtoArrayInitializer(ArrayInitializer* arrinit)
llvm::Constant* LLVM_DtoConstArrayInitializer(ArrayInitializer* arrinit)
{
Logger::println("arr init begin");
assert(arrinit->type->ty == Tsarray);
TypeSArray* t = (TypeSArray*)arrinit->type;
Type* arrinittype = LLVM_DtoDType(arrinit->type);
assert(arrinittype->ty == Tsarray);
TypeSArray* t = (TypeSArray*)arrinittype;
integer_t tdim = t->dim->toInteger();
std::vector<llvm::Constant*> inits(tdim, 0);
const llvm::Type* elemty = LLVM_DtoType(arrinit->type->next);
const llvm::Type* elemty = LLVM_DtoType(arrinittype->next);
assert(arrinit->index.dim == arrinit->value.dim);
for (int i=0,j=0; i < tdim; ++i)
@@ -255,23 +252,19 @@ llvm::Constant* LLVM_DtoArrayInitializer(ArrayInitializer* arrinit)
if (!init)
{
elem* e = t->next->defaultInit()->toElem(gIR);
v = llvm::cast<llvm::Constant>(e->val);
delete e;
v = t->next->defaultInit()->toConstElem(gIR);
}
else if (ExpInitializer* ex = init->isExpInitializer())
{
elem* e = ex->exp->toElem(gIR);
v = llvm::cast<llvm::Constant>(e->val);
delete e;
v = ex->exp->toConstElem(gIR);
}
else if (StructInitializer* si = init->isStructInitializer())
{
v = LLVM_DtoStructInitializer(si);
v = LLVM_DtoConstStructInitializer(si);
}
else if (ArrayInitializer* ai = init->isArrayInitializer())
{
v = LLVM_DtoArrayInitializer(ai);
v = LLVM_DtoConstArrayInitializer(ai);
}
else if (init->isVoidInitializer())
{
@@ -415,3 +408,61 @@ void LLVM_DtoResizeDynArray(llvm::Value* arr, llvm::Value* sz)
new llvm::StoreInst(sz,len,gIR->scopebb());
}
//////////////////////////////////////////////////////////////////////////////////////////
void LLVM_DtoCatArrayElement(llvm::Value* arr, Expression* exp)
{
llvm::Value* ptr = LLVM_DtoGEPi(arr, 0, 0, "tmp", gIR->scopebb());
llvm::Value* idx = new llvm::LoadInst(ptr, "tmp", gIR->scopebb());
llvm::Value* one = llvm::ConstantInt::get(idx->getType(),1,false);
llvm::Value* len = llvm::BinaryOperator::createAdd(idx, one, "tmp", gIR->scopebb());
LLVM_DtoResizeDynArray(arr,len);
ptr = LLVM_DtoGEPi(arr, 0, 1, "tmp", gIR->scopebb());
ptr = new llvm::LoadInst(ptr, "tmp", gIR->scopebb());
ptr = new llvm::GetElementPtrInst(ptr, idx, "tmp", gIR->scopebb());
elem* e = exp->toElem(gIR);
Type* et = LLVM_DtoDType(exp->type);
if (et->ty == Tstruct) {
TypeStruct* ts = (TypeStruct*)et;
LLVM_DtoStructCopy(ts,ptr,e->getValue());
}
else {
llvm::Value* val = e->getValue();
Logger::cout() << "ptr = '" << *ptr << "' element = '" << *val << "'\n";
new llvm::StoreInst(val, ptr, gIR->scopebb());
}
}
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Value* LLVM_DtoStaticArrayCompare(TOK op, llvm::Value* l, llvm::Value* r)
{
const char* fname;
if (op == TOKequal)
fname = "_d_static_array_eq";
else if (op == TOKnotequal)
fname = "_d_static_array_neq";
else
assert(0);
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, fname);
assert(fn);
assert(l->getType() == r->getType());
assert(llvm::isa<llvm::PointerType>(l->getType()));
const llvm::Type* arrty = l->getType()->getContainedType(0);
assert(llvm::isa<llvm::ArrayType>(arrty));
llvm::Value* ll = new llvm::BitCastInst(l, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp", gIR->scopebb());
llvm::Value* rr = new llvm::BitCastInst(r, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp", gIR->scopebb());
llvm::Value* n = llvm::ConstantInt::get(LLVM_DtoSize_t(),gTargetData->getTypeSize(arrty),false);
std::vector<llvm::Value*> args;
args.push_back(ll);
args.push_back(rr);
args.push_back(n);
return new llvm::CallInst(fn, args.begin(), args.end(), "tmp", gIR->scopebb());
}
//////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -4,7 +4,7 @@
const llvm::StructType* LLVM_DtoArrayType(Type* t);
const llvm::ArrayType* LLVM_DtoStaticArrayType(Type* t);
llvm::Constant* LLVM_DtoArrayInitializer(ArrayInitializer* si);
llvm::Constant* LLVM_DtoConstArrayInitializer(ArrayInitializer* si);
llvm::Constant* LLVM_DtoConstantSlice(llvm::Constant* dim, llvm::Constant* ptr);
void LLVM_DtoArrayCopy(elem* dst, elem* src);
@@ -17,4 +17,8 @@ void LLVM_DtoNullArray(llvm::Value* v);
void LLVM_DtoNewDynArray(llvm::Value* dst, llvm::Value* dim, Type* dty, bool doinit=true);
void LLVM_DtoResizeDynArray(llvm::Value* arr, llvm::Value* sz);
void LLVM_DtoCatArrayElement(llvm::Value* arr, Expression* exp);
llvm::Value* LLVM_DtoStaticArrayCompare(TOK op, llvm::Value* l, llvm::Value* r);
#endif // LLVMC_GEN_ARRAYS_H

View File

@@ -1,6 +1,6 @@
#include <iostream>
#include "llvm/Instructions.h"
#include "gen/llvm.h"
#include "gen/elem.h"
#include "gen/irstate.h"
@@ -50,7 +50,7 @@ llvm::Value* elem::getValue()
return mem;
}
else {
return new llvm::LoadInst(mem, "tmp", gIR->scopebb());
return gIR->ir->CreateLoad(mem, "tmp");
}
}

View File

@@ -1,8 +1,6 @@
#ifndef LLVMDC_GEN_ELEM_H
#define LLVMDC_GEN_ELEM_H
#include "llvm/Value.h"
#include "root.h"
#include "declaration.h"
#include "aggregate.h"

View File

@@ -4,8 +4,15 @@
* has been parsed. Substitute your own behaviors for these routimes.
*/
#include <cstdarg>
#include "gen/llvm.h"
#include "mtype.h"
#include "declaration.h"
#include "gen/irstate.h"
#include "tollvm.h"
IRState* gIR = 0;
llvm::TargetData* gTargetData = 0;
@@ -13,15 +20,14 @@ llvm::TargetData* gTargetData = 0;
//////////////////////////////////////////////////////////////////////////////////////////
IRScope::IRScope()
{
begin = end = 0;
returned = false;
begin = end = NULL;
}
IRScope::IRScope(llvm::BasicBlock* b, llvm::BasicBlock* e)
{
begin = b;
end = e;
returned = false;
builder.SetInsertPoint(b);
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -32,24 +38,31 @@ IRState::IRState()
inLvalue = false;
emitMain = false;
mainFunc = 0;
ir.state = this;
}
IRFunction& IRState::func()
{
assert(!functions.empty() && "Function stack is empty!");
return functions.back();
}
llvm::Function* IRState::topfunc()
{
assert(!funcs.empty() && "Function stack is empty!");
return funcs.top();
assert(!functions.empty() && "Function stack is empty!");
return functions.back().func;
}
TypeFunction* IRState::topfunctype()
{
assert(!functypes.empty() && "TypeFunction stack is empty!");
return functypes.top();
assert(!functions.empty() && "Function stack is empty!");
return functions.back().type;
}
llvm::Instruction* IRState::topallocapoint()
{
assert(!functypes.empty() && "AllocaPoint stack is empty!");
return functypes.top()->llvmAllocaPoint;
assert(!functions.empty() && "AllocaPoint stack is empty!");
return functions.back().allocapoint;
}
IRStruct& IRState::topstruct()
@@ -108,6 +121,35 @@ IRStruct::IRStruct(Type* t)
queueFuncs = true;
}
IRStruct::~IRStruct()
//////////////////////////////////////////////////////////////////////////////////////////
IRFinally::IRFinally()
: bb(NULL), ret(false), retval(NULL)
{
}
IRFinally::IRFinally(llvm::BasicBlock* b)
: bb(b), ret(false), retval(NULL)
{
}
//////////////////////////////////////////////////////////////////////////////////////////
LLVMBuilder* IRBuilderHelper::operator->()
{
LLVMBuilder& b = state->scope().builder;
assert(b.GetInsertBlock() != NULL);
return &b;
}
//////////////////////////////////////////////////////////////////////////////////////////
IRFunction::IRFunction(FuncDeclaration* fd)
{
decl = fd;
Type* t = LLVM_DtoDType(fd->type);
assert(t->ty == Tfunction);
type = (TypeFunction*)t;
func = NULL;
allocapoint = NULL;
}

View File

@@ -5,12 +5,6 @@
#include <vector>
#include <deque>
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Function.h"
#include "llvm/BasicBlock.h"
#include "llvm/Target/TargetData.h"
#include "root.h"
// global ir state for current module
@@ -25,19 +19,26 @@ struct FuncDeclaration;
struct Module;
struct TypeStruct;
/*
struct LLVMValue
{
std::vector<llvm::Value*> vals;
};
*/
// represents a scope
struct IRScope
{
llvm::BasicBlock* begin;
llvm::BasicBlock* end;
bool returned;
LLVMBuilder builder;
IRScope();
IRScope(llvm::BasicBlock* b, llvm::BasicBlock* e);
};
// represents a struct or class
struct IRStruct : Object
struct IRStruct
{
typedef std::vector<const llvm::Type*> TypeVector;
typedef std::vector<llvm::Constant*> ConstantVector;
@@ -46,7 +47,6 @@ struct IRStruct : Object
public:
IRStruct();
IRStruct(Type*);
virtual ~IRStruct();
Type* type;
TypeVector fields;
@@ -56,8 +56,40 @@ public:
bool queueFuncs;
};
// represents a finally block
struct IRFinally
{
llvm::BasicBlock* bb;
bool ret;
llvm::Value* retval;
IRFinally();
IRFinally(llvm::BasicBlock* b);
};
// represents a function
struct IRFunction
{
llvm::Function* func;
llvm::Instruction* allocapoint;
FuncDeclaration* decl;
TypeFunction* type;
// finally blocks
typedef std::vector<IRFinally> FinallyVec;
FinallyVec finallys;
IRFunction(FuncDeclaration*);
};
struct IRBuilderHelper
{
IRState* state;
LLVMBuilder* operator->();
};
// represents the module
struct IRState : Object
struct IRState
{
IRState();
@@ -66,9 +98,11 @@ struct IRState : Object
llvm::Module* module;
// functions
std::stack<llvm::Function*> funcs;
typedef std::vector<IRFunction> FunctionVector;
FunctionVector functions;
IRFunction& func();
llvm::Function* topfunc();
std::stack<TypeFunction*> functypes;
TypeFunction* topfunctype();
llvm::Instruction* topallocapoint();
@@ -109,9 +143,8 @@ struct IRState : Object
// array pointer from this :(
LvalVec arrays;
// keeping track of the declaration for the current function body
typedef std::vector<FuncDeclaration*> FuncDeclVec;
FuncDeclVec funcdecls;
// builder helper
IRBuilderHelper ir;
};
#endif // LLVMDC_GEN_IRSTATE_H

18
gen/llvm.h Normal file
View File

@@ -0,0 +1,18 @@
#ifndef GEN_LLVM_H
#define GEN_LLVM_H
#include "llvm/Type.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Constants.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/CallingConv.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Function.h"
#include "llvm/Module.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Support/LLVMBuilder.h"
using llvm::LLVMBuilder;
#endif // GEN_LLVM_H

View File

@@ -70,9 +70,13 @@ llvm::Function* LLVM_D_GetRuntimeFunction(llvm::Module* target, const char* name
}
llvm::Function* fn = M->getFunction(name);
if (!fn)
return NULL;
if (!fn) {
error("Runtime function '%s' was not found", name);
fatal();
//return NULL;
}
const llvm::FunctionType* fnty = fn->getFunctionType();
return llvm::cast<llvm::Function>(target->getOrInsertFunction(name, fnty));
}

View File

@@ -6,12 +6,7 @@
#include <fstream>
#include <iostream>
#include "llvm/Type.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Constants.h"
#include "llvm/Instructions.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/CallingConv.h"
#include "gen/llvm.h"
#include "total.h"
#include "init.h"
@@ -41,8 +36,8 @@ void CompoundStatement::toIR(IRState* p)
if (s)
s->toIR(p);
else {
Logger::println("NULL statement found in CompoundStatement !! :S");
assert(0);
Logger::println("*** ATTENTION: null statement found in CompoundStatement");
//assert(0);
}
}
@@ -56,11 +51,14 @@ void ReturnStatement::toIR(IRState* p)
Logger::println("ReturnStatement::toIR(%d): %s", rsi++, toChars());
LOG_SCOPE;
IRFunction::FinallyVec& fin = p->func().finallys;
if (exp)
{
TY expty = exp->type->ty;
Type* exptype = LLVM_DtoDType(exp->type);
TY expty = exptype->ty;
if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) {
assert(expty == Tstruct || expty == Tdelegate || expty == Tarray);
assert(LLVM_DtoIsPassedByRef(exptype));
TypeFunction* f = p->topfunctype();
assert(f->llvmRetInPtr && f->llvmRetArg);
@@ -69,17 +67,14 @@ void ReturnStatement::toIR(IRState* p)
elem* e = exp->toElem(p);
p->lvals.pop_back();
// structliterals do this themselves
// also they dont produce any value
if (expty == Tstruct) {
if (!e->inplace) {
TypeStruct* ts = (TypeStruct*)exp->type;
TypeStruct* ts = (TypeStruct*)exptype;
assert(e->mem);
LLVM_DtoStructCopy(ts,f->llvmRetArg,e->mem);
}
}
else if (expty == Tdelegate) {
// do nothing, handled by the DelegateExp
LLVM_DtoDelegateCopy(f->llvmRetArg,e->mem);
}
else if (expty == Tarray) {
@@ -91,26 +86,47 @@ void ReturnStatement::toIR(IRState* p)
else
assert(0);
new llvm::ReturnInst(p->scopebb());
if (fin.empty())
new llvm::ReturnInst(p->scopebb());
else {
new llvm::BranchInst(fin.back().bb);
fin.back().ret = true;
}
delete e;
}
else {
elem* e = exp->toElem(p);
llvm::Value* v = e->getValue();
Logger::cout() << *v << '\n';
new llvm::ReturnInst(v, p->scopebb());
delete e;
Logger::cout() << "return value is '" <<*v << "'\n";
if (fin.empty()) {
new llvm::ReturnInst(v, p->scopebb());
}
else {
llvm::Value* rettmp = new llvm::AllocaInst(v->getType(),"tmpreturn",p->topallocapoint());
new llvm::StoreInst(v,rettmp,p->scopebb());
new llvm::BranchInst(fin.back().bb, p->scopebb());
fin.back().ret = true;
fin.back().retval = rettmp;
}
}
}
else
{
if (p->topfunc()->getReturnType() == llvm::Type::VoidTy)
new llvm::ReturnInst(p->scopebb());
else
if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) {
if (fin.empty()) {
new llvm::ReturnInst(p->scopebb());
}
else {
new llvm::BranchInst(fin.back().bb);
fin.back().ret = true;
}
}
else {
assert(0); // why should this ever happen?
new llvm::UnreachableInst(p->scopebb());
}
}
p->scope().returned = true;
}
//////////////////////////////////////////////////////////////////////////////
@@ -196,33 +212,26 @@ void ScopeStatement::toIR(IRState* p)
llvm::BasicBlock* oldend = p->scopeend();
IRScope irs;
llvm::BasicBlock* beginbb = 0;
// remove useless branches by clearing and reusing the current basicblock
llvm::BasicBlock* bb = p->scopebegin();
if (bb->empty()) {
irs.begin = bb;
beginbb = bb;
}
else {
irs.begin = new llvm::BasicBlock("scope", p->topfunc(), oldend);
new llvm::BranchInst(irs.begin, p->scopebegin());
assert(!p->scopereturned());
beginbb = new llvm::BasicBlock("scope", p->topfunc(), oldend);
new llvm::BranchInst(beginbb, p->scopebegin());
}
irs.end = new llvm::BasicBlock("endscope", p->topfunc(), oldend);
llvm::BasicBlock* endbb = new llvm::BasicBlock("endscope", p->topfunc(), oldend);
gIR->scope() = irs;
gIR->scope() = IRScope(beginbb, endbb);
statement->toIR(p);
p->scope() = IRScope(p->scopebb(),oldend);
irs.end->eraseFromParent();
/*
if (!gIR->scopereturned()) {
new llvm::BranchInst(irs.end, gIR->scopebegin());
}
// rewrite the scope
gIR->scope() = IRScope(irs.end,oldend);
*/
endbb->eraseFromParent();
}
//////////////////////////////////////////////////////////////////////////////
@@ -239,7 +248,8 @@ void WhileStatement::toIR(IRState* p)
llvm::BasicBlock* endbb = new llvm::BasicBlock("endwhile", gIR->topfunc(), oldend);
// move into the while block
new llvm::BranchInst(whilebb, gIR->scopebegin());
p->ir->CreateBr(whilebb);
//new llvm::BranchInst(whilebb, gIR->scopebegin());
// replace current scope
gIR->scope() = IRScope(whilebb,endbb);
@@ -324,10 +334,7 @@ void ForStatement::toIR(IRState* p)
// move into the for condition block, ie. start the loop
new llvm::BranchInst(forbb, gIR->scopebegin());
IRScope loop;
loop.begin = forincbb;
loop.end = endbb;
p->loopbbs.push_back(loop);
p->loopbbs.push_back(IRScope(forincbb,endbb));
// replace current scope
gIR->scope() = IRScope(forbb,forbodybb);
@@ -419,30 +426,46 @@ void TryFinallyStatement::toIR(IRState* p)
Logger::println("TryFinallyStatement::toIR(%d): %s", wsi++, toChars());
LOG_SCOPE;
llvm::BasicBlock* oldend = gIR->scopeend();
llvm::BasicBlock* oldend = p->scopeend();
llvm::BasicBlock* trybb = new llvm::BasicBlock("try", gIR->topfunc(), oldend);
llvm::BasicBlock* finallybb = new llvm::BasicBlock("finally", gIR->topfunc(), oldend);
llvm::BasicBlock* endbb = new llvm::BasicBlock("endtryfinally", gIR->topfunc(), oldend);
llvm::BasicBlock* trybb = new llvm::BasicBlock("try", p->topfunc(), oldend);
llvm::BasicBlock* finallybb = new llvm::BasicBlock("finally", p->topfunc(), oldend);
llvm::BasicBlock* endbb = new llvm::BasicBlock("endtryfinally", p->topfunc(), oldend);
// pass the previous BB into this
new llvm::BranchInst(trybb, gIR->scopebegin());
new llvm::BranchInst(trybb, p->scopebb());
gIR->scope() = IRScope(trybb,finallybb);
p->scope() = IRScope(trybb,finallybb);
assert(body);
gIR->func().finallys.push_back(IRFinally(finallybb));
body->toIR(p);
new llvm::BranchInst(finallybb, gIR->scopebegin());
if (!gIR->scopereturned())
new llvm::BranchInst(finallybb, p->scopebb());
// rewrite the scope
gIR->scope() = IRScope(finallybb,endbb);
p->scope() = IRScope(finallybb,endbb);
assert(finalbody);
finalbody->toIR(p);
new llvm::BranchInst(endbb, gIR->scopebegin());
if (gIR->func().finallys.back().ret) {
llvm::Value* retval = p->func().finallys.back().retval;
if (retval) {
retval = new llvm::LoadInst(retval,"tmp",p->scopebb());
new llvm::ReturnInst(retval, p->scopebb());
}
else {
new llvm::ReturnInst(p->scopebb());
}
}
else if (!gIR->scopereturned()) {
new llvm::BranchInst(endbb, p->scopebb());
}
p->func().finallys.pop_back();
// rewrite the scope
gIR->scope() = IRScope(endbb,oldend);
p->scope() = IRScope(endbb,oldend);
}
//////////////////////////////////////////////////////////////////////////////
@@ -628,7 +651,7 @@ void ForeachStatement::toIR(IRState* p)
const llvm::Type* valtype = LLVM_DtoType(value->type);
llvm::Value* valvar = new llvm::AllocaInst(keytype, "foreachval", p->topallocapoint());
if (aggr->type->ty == Tsarray)
if (LLVM_DtoDType(aggr->type)->ty == Tsarray)
{
assert(llvm::isa<llvm::PointerType>(val->getType()));
assert(llvm::isa<llvm::ArrayType>(val->getType()->getContainedType(0)));
@@ -686,7 +709,7 @@ void ForeachStatement::toIR(IRState* p)
body->toIR(p);
p->loopbbs.pop_back();
if (!p->scope().returned)
if (!p->scopereturned())
new llvm::BranchInst(nexbb, p->scopebb());
// end
@@ -734,12 +757,29 @@ void GotoStatement::toIR(IRState* p)
//////////////////////////////////////////////////////////////////////////////
void WithStatement::toIR(IRState* p)
{
Logger::println("WithStatement::toIR(): %s", toChars());
LOG_SCOPE;
assert(exp);
assert(body);
elem* e = exp->toElem(p);
wthis->llvmValue = e->getValue();
delete e;
body->toIR(p);
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
#define STUBST(x) void x::toIR(IRState * p) {error("Statement type "#x" not implemented: %s", toChars());fatal();}
//STUBST(BreakStatement);
//STUBST(ForStatement);
STUBST(WithStatement);
//STUBST(WithStatement);
STUBST(SynchronizedStatement);
//STUBST(ReturnStatement);
//STUBST(ContinueStatement);

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,6 @@
#include <iostream>
#include "llvm/Constants.h"
#include "llvm/Type.h"
#include "llvm/DerivedTypes.h"
#include "llvm/GlobalValue.h"
#include "llvm/Instructions.h"
#include "llvm/CallingConv.h"
#include "gen/llvm.h"
#include "mtype.h"
#include "dsymbol.h"
@@ -20,6 +15,29 @@
#include "gen/elem.h"
#include "gen/arrays.h"
bool LLVM_DtoIsPassedByRef(Type* type)
{
TY t = type->ty;
if (t == Tstruct || t == Tarray || t == Tdelegate)
return true;
else if (t == Ttypedef) {
Type* bt = type->toBasetype();
assert(bt);
return LLVM_DtoIsPassedByRef(bt);
}
return false;
}
Type* LLVM_DtoDType(Type* t)
{
if (t->ty == Ttypedef) {
Type* bt = t->toBasetype();
assert(bt);
return LLVM_DtoDType(bt);
}
return t;
}
const llvm::Type* LLVM_DtoType(Type* t)
{
assert(t);
@@ -167,9 +185,7 @@ const llvm::FunctionType* LLVM_DtoFunctionType(Type* t, const llvm::Type* thispa
const llvm::Type* rettype;
std::vector<const llvm::Type*> paramvec;
TY retty = f->next->ty;
if (retty == Tstruct || retty == Tdelegate || retty == Tarray) {
if (LLVM_DtoIsPassedByRef(f->next)) {
rettype = llvm::PointerType::get(LLVM_DtoType(f->next));
paramvec.push_back(rettype);
rettype = llvm::Type::VoidTy;
@@ -225,7 +241,7 @@ const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl)
actualRettype = rettype;
}
else if (rt) {
if (rt->ty == Tstruct || rt->ty == Tdelegate || rt->ty == Tarray) {
if (LLVM_DtoIsPassedByRef(rt)) {
rettype = llvm::PointerType::get(LLVM_DtoType(rt));
actualRettype = llvm::Type::VoidTy;
f->llvmRetInPtr = retinptr = true;
@@ -265,7 +281,7 @@ const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl)
for (int i=0; i < n; ++i) {
Argument* arg = Argument::getNth(f->parameters, i);
// ensure scalar
Type* argT = arg->type;
Type* argT = LLVM_DtoDType(arg->type);
assert(argT);
if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) {
@@ -286,6 +302,16 @@ const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl)
//paramvec.push_back(llvm::PointerType::get(at->getContainedType(0)));
paramvec.push_back(llvm::PointerType::get(at));
}
else if (llvm::isa<llvm::OpaqueType>(at)) {
Logger::println("opaque param");
if (argT->ty == Tstruct || argT->ty == Tclass)
paramvec.push_back(llvm::PointerType::get(at));
else
assert(0);
}
/*if (llvm::isa<llvm::StructType>(at) || argT->ty == Tstruct || argT->ty == Tsarray) {
paramvec.push_back(llvm::PointerType::get(at));
}*/
else {
if (!arg->llvmCopy) {
Logger::println("ref param");
@@ -453,7 +479,7 @@ llvm::Value* LLVM_DtoStructCopy(TypeStruct* t, llvm::Value* dst, llvm::Value* sr
}
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Constant* LLVM_DtoStructInitializer(StructInitializer* si)
llvm::Constant* LLVM_DtoConstStructInitializer(StructInitializer* si)
{
llvm::StructType* structtype = llvm::cast<llvm::StructType>(si->ad->llvmType);
size_t n = structtype->getNumElements();
@@ -468,11 +494,12 @@ llvm::Constant* LLVM_DtoStructInitializer(StructInitializer* si)
assert(ini);
VarDeclaration* vd = (VarDeclaration*)si->vars.data[i];
Type* vdtype = LLVM_DtoDType(vd->type);
assert(vd);
Logger::println("vars[%d] = %s", i, vd->toChars());
std::vector<unsigned> idxs;
si->ad->offsetToIndex(vd->type, vd->offset, idxs);
si->ad->offsetToIndex(vdtype, vd->offset, idxs);
assert(idxs.size() == 1);
unsigned idx = idxs[0];
@@ -480,17 +507,15 @@ llvm::Constant* LLVM_DtoStructInitializer(StructInitializer* si)
if (ExpInitializer* ex = ini->isExpInitializer())
{
elem* e = ex->exp->toElem(gIR);
v = llvm::cast<llvm::Constant>(e->val);
delete e;
v = ex->exp->toConstElem(gIR);
}
else if (StructInitializer* si = ini->isStructInitializer())
{
v = LLVM_DtoStructInitializer(si);
v = LLVM_DtoConstStructInitializer(si);
}
else if (ArrayInitializer* ai = ini->isArrayInitializer())
{
v = LLVM_DtoArrayInitializer(ai);
v = LLVM_DtoConstArrayInitializer(ai);
}
else if (ini->isVoidInitializer())
{
@@ -731,20 +756,6 @@ void LLVM_DtoMain()
// return
new llvm::ReturnInst(call,bb);
/*
// return value type
const llvm::Type* rettype;
Type* rt = f->next;
if (rt) {
rettype = LLVM_DtoType(rt);
}
else {
assert(0);
}
llvm::FunctionType* functype = llvm::FunctionType::get(rettype, paramvec, false);
*/
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -802,51 +813,58 @@ void LLVM_DtoInitClass(TypeClass* tc, llvm::Value* dst)
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Constant* LLVM_DtoInitializer(Type* type, Initializer* init)
llvm::Constant* LLVM_DtoConstInitializer(Type* type, Initializer* init)
{
llvm::Constant* _init = 0; // may return zero
if (!init)
{
Logger::println("default initializer");
elem* e = type->defaultInit()->toElem(gIR);
if (!e->inplace && !e->isNull()) {
_init = llvm::cast<llvm::Constant>(e->getValue());
}
delete e;
Logger::println("const default initializer for %s", type->toChars());
_init = type->defaultInit()->toConstElem(gIR);
}
else if (ExpInitializer* ex = init->isExpInitializer())
{
Logger::println("expression initializer");
elem* e = ex->exp->toElem(gIR);
if (!e->inplace && !e->isNull()) {
_init = llvm::cast<llvm::Constant>(e->getValue());
}
delete e;
Logger::println("const expression initializer");
_init = ex->exp->toConstElem(gIR);
}
else if (StructInitializer* si = init->isStructInitializer())
{
Logger::println("struct initializer");
_init = LLVM_DtoStructInitializer(si);
Logger::println("const struct initializer");
_init = LLVM_DtoConstStructInitializer(si);
}
else if (ArrayInitializer* ai = init->isArrayInitializer())
{
Logger::println("array initializer");
_init = LLVM_DtoArrayInitializer(ai);
Logger::println("const array initializer");
_init = LLVM_DtoConstArrayInitializer(ai);
}
else if (init->isVoidInitializer())
{
Logger::println("void initializer");
Logger::println("const void initializer");
const llvm::Type* ty = LLVM_DtoType(type);
_init = llvm::Constant::getNullValue(ty);
}
else {
Logger::println("unsupported initializer: %s", init->toChars());
Logger::println("unsupported const initializer: %s", init->toChars());
}
return _init;
}
//////////////////////////////////////////////////////////////////////////////////////////
void LLVM_DtoInitializer(Initializer* init)
{
if (ExpInitializer* ex = init->isExpInitializer())
{
Logger::println("expression initializer");
elem* e = ex->exp->toElem(gIR);
delete e;
}
else {
Logger::println("unsupported initializer: %s", init->toChars());
}
}
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Value* LLVM_DtoGEP(llvm::Value* ptr, llvm::Value* i0, llvm::Value* i1, const std::string& var, llvm::BasicBlock* bb)
{
std::vector<llvm::Value*> v(2);
@@ -862,13 +880,14 @@ llvm::Value* LLVM_DtoGEP(llvm::Value* ptr, const std::vector<unsigned>& src, con
{
size_t n = src.size();
std::vector<llvm::Value*> dst(n);
Logger::cout() << "indices:";
std::ostream& ostr = Logger::cout();
ostr << "indices for '" << *ptr << "':";
for (size_t i=0; i<n; ++i)
{
Logger::cout() << ' ' << i;
ostr << ' ' << i;
dst[i] = llvm::ConstantInt::get(llvm::Type::Int32Ty, src[i], false);
}
Logger::cout() << '\n';
ostr << '\n';
return new llvm::GetElementPtrInst(ptr, dst.begin(), dst.end(), var, bb);
}
@@ -912,7 +931,7 @@ llvm::Function* LLVM_DtoDeclareFunction(FuncDeclaration* fdecl)
}
// regular function
TypeFunction* f = (TypeFunction*)fdecl->type;
TypeFunction* f = (TypeFunction*)LLVM_DtoDType(fdecl->type);
assert(f != 0);
if (fdecl->llvmValue != 0) {
@@ -1054,9 +1073,93 @@ void LLVM_DtoAssert(llvm::Value* cond, llvm::Value* loc, llvm::Value* msg)
call->setCallingConv(llvm::CallingConv::C);
}
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Value* LLVM_DtoArgument(const llvm::Type* paramtype, Argument* fnarg, Expression* argexp)
{
llvm::Value* retval = 0;
bool haslvals = !gIR->lvals.empty();
if (haslvals)
gIR->lvals.push_back(NULL);
elem* arg = argexp->toElem(gIR);
if (haslvals)
gIR->lvals.pop_back();
if (arg->inplace) {
assert(arg->mem != 0);
retval = arg->mem;
delete arg;
return retval;
}
Type* realtype = LLVM_DtoDType(argexp->type);
TY argty = realtype->ty;
if (LLVM_DtoIsPassedByRef(realtype)) {
if (!fnarg || !fnarg->llvmCopy) {
retval = arg->getValue();
assert(retval != 0);
}
else {
llvm::Value* allocaInst = 0;
llvm::BasicBlock* entryblock = &gIR->topfunc()->front();
//const llvm::PointerType* pty = llvm::cast<llvm::PointerType>(arg->mem->getType());
const llvm::PointerType* pty = llvm::PointerType::get(LLVM_DtoType(argexp->type));
if (argty == Tstruct) {
allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint());
TypeStruct* ts = (TypeStruct*)LLVM_DtoDType(argexp->type);
LLVM_DtoStructCopy(ts,allocaInst,arg->mem);
}
else if (argty == Tdelegate) {
allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint());
LLVM_DtoDelegateCopy(allocaInst,arg->mem);
}
else if (argty == Tarray) {
if (arg->type == elem::SLICE) {
allocaInst = new llvm::AllocaInst(LLVM_DtoType(argexp->type), "tmpparam", gIR->topallocapoint());
LLVM_DtoSetArray(allocaInst, arg->arg, arg->mem);
}
else {
allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint());
LLVM_DtoArrayAssign(allocaInst,arg->mem);
}
}
else
assert(0);
assert(allocaInst != 0);
retval = allocaInst;
}
}
else if (!fnarg || fnarg->llvmCopy) {
Logger::println("regular arg");
assert(arg->type != elem::SLICE);
if (arg->mem) Logger::cout() << "mem = " << *arg->mem << '\n';
if (arg->val) Logger::cout() << "val = " << *arg->val << '\n';
if (arg->arg) Logger::cout() << "arg = " << *arg->arg << '\n';
retval = arg->arg ? arg->arg : arg->field ? arg->mem : arg->getValue();
}
else {
Logger::println("as ptr arg");
retval = arg->mem ? arg->mem : arg->val;
if (retval->getType() != paramtype)
{
assert(retval->getType() == paramtype->getContainedType(0));
LLVM_DtoGiveArgumentStorage(arg);
new llvm::StoreInst(retval, arg->mem, gIR->scopebb());
retval = arg->mem;
}
}
delete arg;
if (fnarg && retval->getType() != paramtype) {
Logger::cout() << "got '" << *retval->getType() << "' expected '" << *paramtype << "'\n";
assert(0 && "parameter type that was actually passed is invalid");
}
return retval;
}

View File

@@ -3,11 +3,13 @@
struct StructInitializer;
const llvm::Type* LLVM_DtoType(Type* t);
bool LLVM_DtoIsPassedByRef(Type* type);
Type* LLVM_DtoDType(Type* t);
const llvm::Type* LLVM_DtoStructType(Type* t);
llvm::Value* LLVM_DtoStructZeroInit(TypeStruct* t, llvm::Value* v);
llvm::Value* LLVM_DtoStructCopy(TypeStruct* t, llvm::Value* dst, llvm::Value* src);
llvm::Constant* LLVM_DtoStructInitializer(StructInitializer* si);
llvm::Constant* LLVM_DtoConstStructInitializer(StructInitializer* si);
const llvm::FunctionType* LLVM_DtoFunctionType(Type* t, const llvm::Type* thisparam = 0);
const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl);
@@ -30,7 +32,8 @@ void LLVM_DtoMain();
void LLVM_DtoCallClassDtors(TypeClass* tc, llvm::Value* instance);
void LLVM_DtoInitClass(TypeClass* tc, llvm::Value* dst);
llvm::Constant* LLVM_DtoInitializer(Type* type, Initializer* init);
llvm::Constant* LLVM_DtoConstInitializer(Type* type, Initializer* init);
void LLVM_DtoInitializer(Initializer* init);
llvm::Function* LLVM_DeclareMemSet32();
llvm::Function* LLVM_DeclareMemSet64();
@@ -49,4 +52,6 @@ llvm::Value* LLVM_DtoRealloc(llvm::Value* ptr, llvm::Value* len);
void LLVM_DtoAssert(llvm::Value* cond, llvm::Value* loc, llvm::Value* msg);
llvm::Value* LLVM_DtoArgument(const llvm::Type* paramtype, Argument* fnarg, Expression* argexp);
#include "enums.h"

View File

@@ -11,14 +11,9 @@
#include <iostream>
#include <fstream>
#include "llvm/Type.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "gen/llvm.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetMachineRegistry.h"
@@ -152,13 +147,14 @@ void AggregateDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsig
LOG_SCOPE;
for (unsigned i=0; i<fields.dim; ++i) {
VarDeclaration* vd = (VarDeclaration*)fields.data[i];
Logger::println("found %u type %s", vd->offset, vd->type->toChars());
if (os == vd->offset && vd->type == t) {
Type* vdtype = LLVM_DtoDType(vd->type);
Logger::println("found %u type %s", vd->offset, vdtype->toChars());
if (os == vd->offset && vdtype == t) {
result.push_back(i);
return;
}
else if (vd->type->ty == Tstruct && (vd->offset + vd->type->size()) > os) {
TypeStruct* ts = (TypeStruct*)vd->type;
else if (vdtype->ty == Tstruct && (vd->offset + vdtype->size()) > os) {
TypeStruct* ts = (TypeStruct*)vdtype;
StructDeclaration* sd = ts->sym;
result.push_back(i);
sd->offsetToIndex(t, os - vd->offset, result);
@@ -212,7 +208,7 @@ void InterfaceDeclaration::toObjFile()
void StructDeclaration::toObjFile()
{
TypeStruct* ts = (TypeStruct*)type;
TypeStruct* ts = (TypeStruct*)LLVM_DtoDType(type);
if (llvmType != 0)
return;
@@ -288,7 +284,7 @@ void StructDeclaration::toObjFile()
// generate member function definitions
gIR->topstruct().queueFuncs = false;
IRState::FuncDeclVec& mfs = gIR->topstruct().funcs;
IRStruct::FuncDeclVec& mfs = gIR->topstruct().funcs;
size_t n = mfs.size();
for (size_t i=0; i<n; ++i) {
mfs[i]->toObjFile();
@@ -311,6 +307,9 @@ static void LLVM_AddBaseClassData(BaseClasses* bcs)
{
BaseClass* bc = (BaseClass*)(bcs->data[j]);
assert(bc);
Logger::println("Adding base class members of %s", bc->base->toChars());
LOG_SCOPE;
LLVM_AddBaseClassData(&bc->base->baseclasses);
for (int k=0; k < bc->base->members->dim; k++) {
Dsymbol* dsym = (Dsymbol*)(bc->base->members->data[k]);
@@ -324,7 +323,7 @@ static void LLVM_AddBaseClassData(BaseClasses* bcs)
void ClassDeclaration::toObjFile()
{
TypeClass* ts = (TypeClass*)type;
TypeClass* ts = (TypeClass*)LLVM_DtoDType(type);
if (ts->llvmType != 0 || llvmInProgress)
return;
@@ -453,7 +452,7 @@ void ClassDeclaration::toObjFile()
// generate member function definitions
gIR->topstruct().queueFuncs = false;
IRState::FuncDeclVec& mfs = gIR->topstruct().funcs;
IRStruct::FuncDeclVec& mfs = gIR->topstruct().funcs;
size_t n = mfs.size();
for (size_t i=0; i<n; ++i) {
mfs[i]->toObjFile();
@@ -479,8 +478,7 @@ unsigned ClassDeclaration::baseVtblOffset(BaseClass *bc)
void VarDeclaration::toObjFile()
{
static int vdi = 0;
Logger::print("VarDeclaration::toObjFile(%d): %s | %s\n", vdi++, toChars(), type->toChars());
Logger::print("VarDeclaration::toObjFile(): %s | %s\n", toChars(), type->toChars());
LOG_SCOPE;
llvm::Module* M = gIR->module;
@@ -493,8 +491,11 @@ void VarDeclaration::toObjFile()
}
// global variable or magic
if (isDataseg())
if (isDataseg() || parent->isModule())
{
if (llvmTouched) return;
else llvmTouched = true;
bool _isconst = isConst();
llvm::GlobalValue::LinkageTypes _linkage;
@@ -503,7 +504,9 @@ void VarDeclaration::toObjFile()
else
_linkage = LLVM_DtoLinkage(protection, storage_class);
const llvm::Type* _type = LLVM_DtoType(type);
Type* t = LLVM_DtoDType(type);
const llvm::Type* _type = LLVM_DtoType(t);
assert(_type);
llvm::Constant* _init = 0;
@@ -513,10 +516,10 @@ void VarDeclaration::toObjFile()
std::string _name(mangle());
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_type,_isconst,_linkage,0,_name,M);
llvmValue = gvar;
gIR->lvals.push_back(gvar);
_init = LLVM_DtoInitializer(type, init);
assert(_init);
gIR->lvals.push_back(gvar);
_init = LLVM_DtoConstInitializer(t, init);
gIR->lvals.pop_back();
//Logger::cout() << "initializer: " << *_init << '\n';
if (_type != _init->getType()) {
@@ -529,8 +532,8 @@ void VarDeclaration::toObjFile()
{
assert(_init->getType()->getContainedType(0) == _type);
llvm::GlobalVariable* gv = llvm::cast<llvm::GlobalVariable>(_init);
assert(type->ty == Tstruct);
TypeStruct* ts = (TypeStruct*)type;
assert(t->ty == Tstruct);
TypeStruct* ts = (TypeStruct*)t;
assert(ts->sym->llvmInitZ);
_init = ts->sym->llvmInitZ;
}
@@ -549,9 +552,9 @@ void VarDeclaration::toObjFile()
}
}
gIR->lvals.pop_back();
gvar->setInitializer(_init);
llvmDModule = gIR->dmodule;
//if (storage_class & STCprivate)
// gvar->setVisibility(llvm::GlobalValue::ProtectedVisibility);
@@ -562,36 +565,37 @@ void VarDeclaration::toObjFile()
{
Logger::println("Aggregate var declaration: '%s' offset=%d", toChars(), offset);
const llvm::Type* _type = LLVM_DtoType(type);
Type* t = LLVM_DtoDType(type);
const llvm::Type* _type = LLVM_DtoType(t);
gIR->topstruct().fields.push_back(_type);
llvm::Constant*_init = LLVM_DtoInitializer(type, init);
llvm::Constant*_init = LLVM_DtoConstInitializer(t, init);
assert(_init);
Logger::cout() << "field init is: " << *_init << " type should be " << *_type << '\n';
if (!_init || _type != _init->getType())
if (_type != _init->getType())
{
if (type->ty == Tsarray)
if (t->ty == Tsarray)
{
const llvm::ArrayType* arrty = llvm::cast<llvm::ArrayType>(_type);
uint64_t n = arrty->getNumElements();
std::vector<llvm::Constant*> vals(n,_init);
_init = llvm::ConstantArray::get(arrty, vals);
}
else if (type->ty == Tarray)
else if (t->ty == Tarray)
{
assert(llvm::isa<llvm::StructType>(_type));
_init = llvm::ConstantAggregateZero::get(_type);
}
else if (type->ty == Tstruct)
else if (t->ty == Tstruct)
{
const llvm::StructType* structty = llvm::cast<llvm::StructType>(_type);
TypeStruct* ts = (TypeStruct*)type;
TypeStruct* ts = (TypeStruct*)t;
assert(ts);
assert(ts->sym);
assert(ts->sym->llvmInitZ);
_init = ts->sym->llvmInitZ;
}
else if (type->ty == Tclass)
else if (t->ty == Tclass)
{
_init = llvm::Constant::getNullValue(_type);
}
@@ -644,7 +648,8 @@ void FuncDeclaration::toObjFile()
return; // we wait with the definition as they might invoke a virtual method and the vtable is not yet complete
}
TypeFunction* f = (TypeFunction*)type;
Type* t = LLVM_DtoDType(type);
TypeFunction* f = (TypeFunction*)t;
assert(f->llvmType);
const llvm::FunctionType* functype = llvm::cast<llvm::FunctionType>(llvmValue->getType()->getContainedType(0));
@@ -684,7 +689,8 @@ void FuncDeclaration::toObjFile()
// function definition
if (allow_fbody && fbody != 0)
{
gIR->funcdecls.push_back(this);
gIR->functions.push_back(IRFunction(this));
gIR->func().func = func;
// first make absolutely sure the type is up to date
f->llvmType = llvmValue->getType()->getContainedType(0);
@@ -703,39 +709,38 @@ void FuncDeclaration::toObjFile()
if (isMain())
gIR->emitMain = true;
gIR->funcs.push(func);
gIR->functypes.push(f);
IRScope irs;
irs.begin = new llvm::BasicBlock("entry",func);
irs.end = new llvm::BasicBlock("endentry",func);
llvm::BasicBlock* beginbb = new llvm::BasicBlock("entry",func);
llvm::BasicBlock* endbb = new llvm::BasicBlock("endentry",func);
//assert(gIR->scopes.empty());
gIR->scopes.push_back(irs);
gIR->scopes.push_back(IRScope(beginbb, endbb));
// create alloca point
f->llvmAllocaPoint = new llvm::BitCastInst(llvm::ConstantInt::get(llvm::Type::Int32Ty,0,false),llvm::Type::Int32Ty,"alloca point",gIR->scopebb());
gIR->func().allocapoint = f->llvmAllocaPoint;
// output function body
fbody->toIR(gIR);
// llvm requires all basic blocks to end with a TerminatorInst but DMD does not put a return statement
// in automatically, so we do it here.
if (!isMain() && (gIR->scopebb()->empty() || !llvm::isa<llvm::TerminatorInst>(gIR->scopebb()->back()))) {
// pass the previous block into this block
//new llvm::BranchInst(irs.end, irs.begin);
new llvm::ReturnInst(gIR->scopebb());
if (!isMain()) {
if (gIR->scopebb()->empty() || !llvm::isa<llvm::TerminatorInst>(gIR->scopebb()->back())) {
// pass the previous block into this block
//new llvm::BranchInst(irs.end, irs.begin);
if (func->getReturnType() == llvm::Type::VoidTy) {
new llvm::ReturnInst(gIR->scopebb());
}
}
}
// erase alloca point
f->llvmAllocaPoint->eraseFromParent();
f->llvmAllocaPoint = 0;
gIR->func().allocapoint = 0;
gIR->scopes.pop_back();
//assert(gIR->scopes.empty());
gIR->functypes.pop();
gIR->funcs.pop();
// get rid of the endentry block, it's never used
assert(!func->getBasicBlockList().empty());
@@ -745,11 +750,10 @@ void FuncDeclaration::toObjFile()
// would be nice to figure out how to assert that this is correct
llvm::BasicBlock* lastbb = &func->getBasicBlockList().back();
if (lastbb->empty()) {
// possibly assert(lastbb->getNumPredecessors() == 0); ??? try it out sometime ...
new llvm::UnreachableInst(lastbb);
lastbb->eraseFromParent();
}
gIR->funcdecls.pop_back();
gIR->functions.pop_back();
}
// template instances should have weak linkage

View File

@@ -2,6 +2,8 @@ module internal.arrays;
extern(C):
// per-element array init routines
void _d_array_init_i1(bool* a, size_t n, bool v)
{
auto p = a;
@@ -65,3 +67,21 @@ void _d_array_init_pointer(void** a, size_t n, void* v)
while (p !is end)
*p++ = v;
}
// array comparison routines
int memcmp(void*,void*,size_t);
bool _d_static_array_eq(void* lhs, void* rhs, size_t bytesize)
{
if (lhs is rhs)
return true;
return memcmp(lhs,rhs,bytesize) == 0;
}
bool _d_static_array_neq(void* lhs, void* rhs, size_t bytesize)
{
if (lhs is rhs)
return false;
return memcmp(lhs,rhs,bytesize) != 0;
}

View File

@@ -1,9 +1,14 @@
module arrays4;
import std.stdio;
void main()
{
auto arr = new int[4];
auto arrcat = arr ~ arr;
assert(arrcat.length == arr.length * 2);
int[] arr;
arr ~= 3;
assert(arr.length == 1);
assert(arr[0] == 3);
arr ~= 5;
assert(arr.length == 2);
assert(arr[0] == 3);
assert(arr[1] == 5);
writefln(arr);
}

6
test/arrays6.d Normal file
View File

@@ -0,0 +1,6 @@
module arrays6;
void main()
{
int[4] a = [1,2,3,4];
}

19
test/arrays7.d Normal file
View File

@@ -0,0 +1,19 @@
module arrays7;
struct S
{
int i;
float f;
long l;
}
void main()
{
S[] arr;
S s;
arr ~= s;
arr ~= S(1,2.64,0xFFFF_FFFF_FFFF);
assert(arr[1].i == 1);
assert(arr[1].f > 2.63 && arr[1].f < 2.65);
assert(arr[1].l == 0xFFFF_FFFF_FFFF);
}

23
test/bug10.d Normal file
View File

@@ -0,0 +1,23 @@
module bug10;
import std.stdio;
class C
{
char[] msg;
this()
{
}
this(char[] msg)
{
this.msg = msg;
}
}
void main()
{
auto c = new C();
c.msg = "world";
auto b = new C("hello");
printf("%.*s\n", b.msg.length, b.msg.ptr);
printf("%.*s\n", c.msg.length, c.msg.ptr);
}

12
test/bug11.d Normal file
View File

@@ -0,0 +1,12 @@
module bug11;
struct S
{
int[4] arr;
}
S s=S([1,2,3,4]);
void main()
{
}

6
test/bug12.d Normal file
View File

@@ -0,0 +1,6 @@
module bug12;
void main()
{
const string name="y";
}

18
test/bug13.d Normal file
View File

@@ -0,0 +1,18 @@
module bug13;
void func1(ubyte[4]* arr)
{
ubyte* b = &(*arr)[0];
func2(&(*arr)[1]);
}
void func2(ubyte* ptr)
{
assert(*ptr == 2);
}
void main()
{
ubyte[4] arr = [cast(ubyte)1,2,3,4];
func1(&arr);
}

7
test/bug14.d Normal file
View File

@@ -0,0 +1,7 @@
module bug14;
void main()
{
int[] arr = new int[12];
int i = arr[0];
}

17
test/bug15.d Normal file
View File

@@ -0,0 +1,17 @@
module bug15;
bool bool1(bool b) {
if (b) return true;
else return false;
}
bool bool2(bool b) {
if (b) {return true;}
else {return false;}
}
void main()
{
assert(bool1(true));
assert(!bool2(false));
}

View File

@@ -17,6 +17,8 @@ void main()
S s;
s.arr = new int[5];
s.arr[1] = 32;
assert(s.arr[0] == 0);
assert(s.arr[1] == 32);
int i;
i = s.arr[0];
//assert(s.arr[0] == 0);
//assert(s.arr[1] == 32);
}

21
test/bug8.d Normal file
View File

@@ -0,0 +1,21 @@
module bug8;
void main()
{
s = newS();
}
S* s;
struct S
{
int i;
}
S* newS()
{
auto tmp = new S;
tmp.i = 4;
return tmp;
}

32
test/bug9.d Normal file
View File

@@ -0,0 +1,32 @@
module bug9;
struct rgb
{
ubyte[3] values;
rgb average(rgb other)
{
rgb res;
foreach (id, ref v; res.values) v=(values[id]+other.values[id])/2;
return res;
}
void print()
{
printf("[%d,%d,%d]\n", values[0], values[1], values[2]);
}
}
void main()
{
rgb a,b;
a.values[0] = 10;
a.values[1] = 20;
a.values[2] = 30;
b.values[0] = 30;
b.values[1] = 20;
b.values[2] = 10;
rgb avg = a.average(b);
avg.print();
assert(avg.values[0] == 20);
assert(avg.values[1] == 20);
assert(avg.values[2] == 20);
}

8
test/cond1.d Normal file
View File

@@ -0,0 +1,8 @@
module cond1;
void main()
{
double a = 2;
double b = 4;
double c = (a > 0) ? a : b;
}

8
test/scope2.d Normal file
View File

@@ -0,0 +1,8 @@
module scope2;
void main()
{
scope(exit) printf("exit\n");
scope(failure) printf("failure\n");
scope(success) printf("success\n");
}

10
test/scope3.d Normal file
View File

@@ -0,0 +1,10 @@
module scope3;
void main()
{
int i;
while (i < 10) {
scope(success) i++;
}
printf("%d\n", i);
}

13
test/scope4.d Normal file
View File

@@ -0,0 +1,13 @@
module scope4;
int main()
{
int i;
try
{
return i;
}
finally
{
//i = 1;
}
}

View File

@@ -12,4 +12,5 @@ void main()
{
C c = new C;
auto s = c.toString();
printf("%.*s\n", s.length, s.ptr);
}

15
test/with1.d Normal file
View File

@@ -0,0 +1,15 @@
module with1;
struct S
{
int i;
float f;
}
void main()
{
S s;
with(s)
{
i = 0;
f = 3.4;
}
}

View File

@@ -6,28 +6,28 @@ if [ -z $1 ]; then
fi
if [ "$2" = "ll" ]; then
llvmdc $1 -Itest -odtest -c &&
llvmdc $1 -Itest -odtest -c -vv &&
llvm-dis -f $1.bc &&
cat $1.ll
exit $?
elif [ "$2" = "llopt" ]; then
llvmdc $1 -Itest -odtest -c &&
llvmdc $1 -Itest -odtest -c -vv &&
opt -f -o=$1.bc -std-compile-opts $1.bc &&
llvm-dis -f $1.bc &&
cat $1.ll
exit $?
elif [ "$2" = "run" ]; then
llvmdc $1 lib/lphobos.bc -Itest -odtest -of$1 &&
llvmdc $1 lib/lphobos.bc -Itest -odtest -of$1 -vv &&
$1
exit $?
elif [ "$2" = "c" ]; then
llvmdc $1 -Itest -odtest -c
llvmdc $1 -Itest -odtest -c -vv
exit $?
elif [ "$2" = "gdb" ]; then
gdb --args llvmdc $1 -Itest -odtest -c
gdb --args llvmdc $1 -Itest -odtest -c -vv
exit $?
elif [ "$2" = "gdbrun" ]; then
llvmdc $1 -Itest -odtest -c &&
llvmdc $1 -Itest -odtest -c -vv &&
gdb $1
exit $?
else