mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-02-26 08:33:14 +01:00
[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:
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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')
|
||||
{
|
||||
|
||||
85
gen/arrays.c
85
gen/arrays.c
@@ -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());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
18
gen/llvm.h
Normal 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
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
152
gen/statements.c
152
gen/statements.c
@@ -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);
|
||||
|
||||
823
gen/toir.c
823
gen/toir.c
File diff suppressed because it is too large
Load Diff
221
gen/tollvm.c
221
gen/tollvm.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
110
gen/toobj.c
110
gen/toobj.c
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
6
test/arrays6.d
Normal file
@@ -0,0 +1,6 @@
|
||||
module arrays6;
|
||||
|
||||
void main()
|
||||
{
|
||||
int[4] a = [1,2,3,4];
|
||||
}
|
||||
19
test/arrays7.d
Normal file
19
test/arrays7.d
Normal 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
23
test/bug10.d
Normal 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
12
test/bug11.d
Normal 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
6
test/bug12.d
Normal file
@@ -0,0 +1,6 @@
|
||||
module bug12;
|
||||
|
||||
void main()
|
||||
{
|
||||
const string name="y";
|
||||
}
|
||||
18
test/bug13.d
Normal file
18
test/bug13.d
Normal 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
7
test/bug14.d
Normal file
@@ -0,0 +1,7 @@
|
||||
module bug14;
|
||||
|
||||
void main()
|
||||
{
|
||||
int[] arr = new int[12];
|
||||
int i = arr[0];
|
||||
}
|
||||
17
test/bug15.d
Normal file
17
test/bug15.d
Normal 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));
|
||||
}
|
||||
@@ -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
21
test/bug8.d
Normal 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
32
test/bug9.d
Normal 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
8
test/cond1.d
Normal 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
8
test/scope2.d
Normal 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
10
test/scope3.d
Normal 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
13
test/scope4.d
Normal file
@@ -0,0 +1,13 @@
|
||||
module scope4;
|
||||
int main()
|
||||
{
|
||||
int i;
|
||||
try
|
||||
{
|
||||
return i;
|
||||
}
|
||||
finally
|
||||
{
|
||||
//i = 1;
|
||||
}
|
||||
}
|
||||
@@ -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
15
test/with1.d
Normal file
@@ -0,0 +1,15 @@
|
||||
module with1;
|
||||
struct S
|
||||
{
|
||||
int i;
|
||||
float f;
|
||||
}
|
||||
void main()
|
||||
{
|
||||
S s;
|
||||
with(s)
|
||||
{
|
||||
i = 0;
|
||||
f = 3.4;
|
||||
}
|
||||
}
|
||||
12
tester.sh
12
tester.sh
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user