Exemplo n.º 1
0
// build ModuleReference and register function, to register the module info in the global linked list
static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo)
{
    // build ctor type
    LLFunctionType* fty = LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector<LLType*>(), false);

    // build ctor name
    std::string fname = "_D";
    fname += gIR->dmodule->mangle();
    fname += "16__moduleinfoCtorZ";

    // build a function that registers the moduleinfo in the global moduleinfo linked list
    LLFunction* ctor = LLFunction::Create(fty, LLGlobalValue::InternalLinkage, fname, gIR->module);

    // provide the default initializer
    LLStructType* modulerefTy = DtoModuleReferenceType();
    LLConstant* mrefvalues[] = {
        LLConstant::getNullValue(modulerefTy->getContainedType(0)),
        llvm::ConstantExpr::getBitCast(moduleinfo, modulerefTy->getContainedType(1))
    };
    LLConstant* thismrefinit = LLConstantStruct::get(modulerefTy, llvm::ArrayRef<LLConstant*>(mrefvalues));

    // create the ModuleReference node for this module
    std::string thismrefname = "_D";
    thismrefname += gIR->dmodule->mangle();
    thismrefname += "11__moduleRefZ";
    Loc loc;
    LLGlobalVariable* thismref = getOrCreateGlobal(loc, *gIR->module,
        modulerefTy, false, LLGlobalValue::InternalLinkage, thismrefinit,
        thismrefname);
    // make sure _Dmodule_ref is declared
    LLConstant* mref = gIR->module->getNamedGlobal("_Dmodule_ref");
    LLType *modulerefPtrTy = getPtrToType(modulerefTy);
    if (!mref)
        mref = new LLGlobalVariable(*gIR->module, modulerefPtrTy, false, LLGlobalValue::ExternalLinkage, NULL, "_Dmodule_ref");
    mref = DtoBitCast(mref, getPtrToType(modulerefPtrTy));

    // make the function insert this moduleinfo as the beginning of the _Dmodule_ref linked list
    llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "moduleinfoCtorEntry", ctor);
    IRBuilder<> builder(bb);

    // debug info
    gIR->DBuilder.EmitSubProgramInternal(fname.c_str(), fname.c_str());

    // get current beginning
    LLValue* curbeg = builder.CreateLoad(mref, "current");

    // put current beginning as the next of this one
    LLValue* gep = builder.CreateStructGEP(thismref, 0, "next");
    builder.CreateStore(curbeg, gep);

    // replace beginning
    builder.CreateStore(thismref, mref);

    // return
    builder.CreateRetVoid();

    return ctor;
}
Exemplo n.º 2
0
static LLConstant* build_offti_array(ClassDeclaration* cd, LLType* arrayT)
{
    IrStruct* irstruct = cd->ir.irStruct;

    size_t nvars = irstruct->varDecls.size();
    std::vector<LLConstant*> arrayInits(nvars);

    for (size_t i=0; i<nvars; i++)
    {
        arrayInits[i] = build_offti_entry(cd, irstruct->varDecls[i]);
    }

    LLConstant* size = DtoConstSize_t(nvars);
    LLConstant* ptr;

    if (nvars == 0)
        return LLConstant::getNullValue( arrayT );

    // array type
    LLArrayType* arrTy = llvm::ArrayType::get(arrayInits[0]->getType(), nvars);
    LLConstant* arrInit = LLConstantArray::get(arrTy, arrayInits);

    // mangle
    std::string name(cd->type->vtinfo->toChars());
    name.append("__OffsetTypeInfos");

    // create symbol
    llvm::GlobalVariable* gvar = new llvm::GlobalVariable(arrTy,true,DtoInternalLinkage(cd),arrInit,name,gIR->module);
    ptr = DtoBitCast(gvar, getPtrToType(arrTy->getElementType()));

    return DtoConstSlice(size, ptr);
}
Exemplo n.º 3
0
IRLandingPadInfo::IRLandingPadInfo(Catch* catchstmt, llvm::BasicBlock* end)
: finallyBody(NULL)
{
    target = llvm::BasicBlock::Create(gIR->context(), "catch", gIR->topfunc(), end);
    gIR->scope() = IRScope(target,end);
    DtoDwarfBlockStart(catchstmt->loc);

    // assign storage to catch var
    if(catchstmt->var) {
        // use the same storage for all exceptions that are not accessed in
        // nested functions
    #if DMDV2
        if(!catchstmt->var->nestedrefs.dim) {
    #else
        if(!catchstmt->var->nestedref) {
    #endif
            assert(!catchstmt->var->ir.irLocal);
            catchstmt->var->ir.irLocal = new IrLocal(catchstmt->var);
            LLValue* catch_var = gIR->func()->gen->landingPadInfo.getExceptionStorage();
            catchstmt->var->ir.irLocal->value = gIR->ir->CreateBitCast(catch_var, getPtrToType(DtoType(catchstmt->var->type)));
        }

        // this will alloca if we haven't already and take care of nested refs
        DtoDeclarationExp(catchstmt->var);

        // the exception will only be stored in catch_var. copy it over if necessary
        if(catchstmt->var->ir.irLocal->value != gIR->func()->gen->landingPadInfo.getExceptionStorage()) {
            LLValue* exc = gIR->ir->CreateBitCast(DtoLoad(gIR->func()->gen->landingPadInfo.getExceptionStorage()), DtoType(catchstmt->var->type));
            DtoStore(exc, catchstmt->var->ir.irLocal->value);
        }
    }

    // emit handler, if there is one
    // handler is zero for instance for 'catch { debug foo(); }'
    if(catchstmt->handler)
        catchstmt->handler->toIR(gIR);

    if (!gIR->scopereturned())
        gIR->ir->CreateBr(end);

    assert(catchstmt->type);
    catchType = catchstmt->type->toBasetype()->isClassHandle();
    assert(catchType);
    catchType->codegen(Type::sir);
    DtoDwarfBlockEnd();
}

IRLandingPadInfo::IRLandingPadInfo(Statement* finallystmt)
: target(NULL), finallyBody(finallystmt), catchType(NULL)
{

}


void IRLandingPad::addCatch(Catch* catchstmt, llvm::BasicBlock* end)
{
    unpushed_infos.push_front(IRLandingPadInfo(catchstmt, end));
}
Exemplo n.º 4
0
 void vaCopy(LLValue* pDest, LLValue* src) {
     // Analog to va_start, we need to allocate a new __va_list struct on the stack,
     // fill it with a bitcopy of the source struct...
     src = DtoLoad(DtoBitCast(src, getValistType()->getPointerTo())); // *(__va_list*)src
     LLValue* valistmem = DtoAllocaDump(src, 0, "__va_list_mem");
     // ... and finally set the passed 'dest' char* pointer to the new struct's address.
     DtoStore(DtoBitCast(valistmem, getVoidPtrType()),
         DtoBitCast(pDest, getPtrToType(getVoidPtrType())));
 }
Exemplo n.º 5
0
 LLValue *prepareVaStart(DLValue *ap) override {
   // Since the user only created a char* pointer (ap) on the stack before
   // invoking va_start, we first need to allocate the actual __va_list struct
   // and set `ap` to its address.
   LLValue *valistmem = DtoRawAlloca(getValistType(), 0, "__va_list_mem");
   DtoStore(valistmem,
            DtoBitCast(DtoLVal(ap), getPtrToType(valistmem->getType())));
   // Pass a i8* pointer to the actual struct to LLVM's va_start intrinsic.
   return DtoBitCast(valistmem, getVoidPtrType());
 }
Exemplo n.º 6
0
 void vaCopy(DLValue *dest, DValue *src) override {
   // Analog to va_start, we first need to allocate a new __va_list struct on
   // the stack and set `dest` to its address.
   LLValue *valistmem = DtoRawAlloca(getValistType(), 0, "__va_list_mem");
   DtoStore(valistmem,
            DtoBitCast(DtoLVal(dest), getPtrToType(valistmem->getType())));
   // Then fill the new struct with a bitcopy of the source struct.
   // `src` is a char* pointer to the source struct.
   DtoMemCpy(valistmem, DtoRVal(src));
 }
Exemplo n.º 7
0
static LLConstant* build_class_dtor(ClassDeclaration* cd)
{
    FuncDeclaration* dtor = cd->dtor;

    // if no destructor emit a null
    if (!dtor)
        return getNullPtr(getVoidPtrType());

    dtor->codegen(Type::sir);
    return llvm::ConstantExpr::getBitCast(dtor->ir.irFunc->func, getPtrToType(LLType::getInt8Ty(gIR->context())));
}
Exemplo n.º 8
0
std::vector<llvm::Type *>
IrTypeClass::buildVtblType(Type *first, FuncDeclarations *vtbl_array) {
  IF_LOG Logger::println("Building vtbl type for class %s",
                         cd->toPrettyChars());
  LOG_SCOPE;

  std::vector<llvm::Type *> types;
  types.reserve(vtbl_array->dim);

  auto I = vtbl_array->begin();
  // first comes the classinfo for D interfaces
  if (first) {
    types.push_back(DtoType(first));
    ++I;
  }

  // then come the functions
  for (auto E = vtbl_array->end(); I != E; ++I) {
    FuncDeclaration *fd = *I;
    if (fd == nullptr) {
      // FIXME: This stems from the ancient D1 days – can it still happen?
      types.push_back(getVoidPtrType());
      continue;
    }

    IF_LOG Logger::println("Adding type of %s", fd->toPrettyChars());

    // If inferring return type and semantic3 has not been run, do it now.
    // This pops up in some other places in the frontend as well, however
    // it is probably a bug that it still occurs that late.
    if (!fd->type->nextOf() && fd->inferRetType) {
      Logger::println("Running late semantic3 to infer return type.");
      TemplateInstance *spec = fd->isSpeculative();
      unsigned int olderrs = global.errors;
      fd->semantic3(fd->_scope);
      if (spec && global.errors != olderrs) {
        spec->errors = global.errors - olderrs;
      }
    }

    if (!fd->type->nextOf()) {
      // Return type of the function has not been inferred. This seems to
      // happen with virtual functions and is probably a frontend bug.
      IF_LOG Logger::println("Broken function type, semanticRun: %d",
                             fd->semanticRun);
      types.push_back(getVoidPtrType());
      continue;
    }

    types.push_back(getPtrToType(DtoFunctionType(fd)));
  }

  return types;
}
Exemplo n.º 9
0
LLValue* DtoIndexStruct(LLValue* src, StructDeclaration* sd, VarDeclaration* vd)
{
    Logger::println("indexing struct field %s:", vd->toPrettyChars());
    LOG_SCOPE;

    DtoResolveStruct(sd);

    // vd must be a field
    IrField* field = vd->ir.irField;
    assert(field);

    // get the start pointer
    LLType* st = getPtrToType(DtoType(sd->type));

    // cast to the formal struct type
    src = DtoBitCast(src, st);

    // gep to the index
    LLValue* val = DtoGEPi(src, 0, field->index);

    // do we need to offset further? (union area)
    if (field->unionOffset)
    {
        // cast to void*
        val = DtoBitCast(val, getVoidPtrType());
        // offset
        val = DtoGEPi1(val, field->unionOffset);
    }

    // cast it to the right type
    val = DtoBitCast(val, getPtrToType(i1ToI8(DtoType(vd->type))));

    if (Logger::enabled())
        Logger::cout() << "value: " << *val << '\n';

    return val;
}
Exemplo n.º 10
0
 // Get struct from ABI-mangled representation
 LLValue* get(Type* dty, DValue* v)
 {
     LLValue* lval;
     if (v->isLVal()) {
         lval = v->getLVal();
     } else {
         // No memory location, create one.
         LLValue* rval = v->getRVal();
         lval = DtoRawAlloca(rval->getType(), 0);
         DtoStore(rval, lval);
     }
     
     LLType* pTy = getPtrToType(DtoType(dty));
     return DtoLoad(DtoBitCast(lval, pTy), "get-result");
 }
Exemplo n.º 11
0
LLStructType* DtoInterfaceInfoType()
{
    if (gIR->interfaceInfoType)
        return gIR->interfaceInfoType;

    // build interface info type
    LLSmallVector<LLType*, 3> types;
    // ClassInfo classinfo
    ClassDeclaration* cd2 = ClassDeclaration::classinfo;
    DtoResolveClass(cd2);
    types.push_back(DtoType(cd2->type));
    // void*[] vtbl
    LLSmallVector<LLType*, 2> vtbltypes;
    vtbltypes.push_back(DtoSize_t());
    LLType* byteptrptrty = getPtrToType(getPtrToType(LLType::getInt8Ty(gIR->context())));
    vtbltypes.push_back(byteptrptrty);
    types.push_back(LLStructType::get(gIR->context(), vtbltypes));
    // int offset
    types.push_back(LLType::getInt32Ty(gIR->context()));
    // create type
    gIR->interfaceInfoType = LLStructType::get(gIR->context(), types);

    return gIR->interfaceInfoType;
}
Exemplo n.º 12
0
LLValue* DtoIndexClass(LLValue* src, ClassDeclaration* cd, VarDeclaration* vd)
{
    Logger::println("indexing class field %s:", vd->toPrettyChars());
    LOG_SCOPE;

    if (Logger::enabled())
        Logger::cout() << "src: " << *src << '\n';

    // make sure class is resolved
    DtoResolveClass(cd);

    // vd must be a field
    IrField* field = vd->ir.irField;
    assert(field);

    // get the start pointer
    LLType* st = DtoType(cd->type);
    // cast to the struct type
    src = DtoBitCast(src, st);

    // gep to the index
#if 0
    if (Logger::enabled())
    {
        Logger::cout() << "src2: " << *src << '\n';
        Logger::cout() << "index: " << field->index << '\n';
        Logger::cout() << "srctype: " << *src->getType() << '\n';
    }
#endif
    LLValue* val = DtoGEPi(src, 0, field->index);

    // do we need to offset further? (union area)
    if (field->unionOffset)
    {
        // cast to void*
        val = DtoBitCast(val, getVoidPtrType());
        // offset
        val = DtoGEPi1(val, field->unionOffset);
    }

    // cast it to the right type
    val = DtoBitCast(val, getPtrToType(DtoType(vd->type)));

    if (Logger::enabled())
        Logger::cout() << "value: " << *val << '\n';

    return val;
}
Exemplo n.º 13
0
 // Turn a struct into an ABI-mangled representation
 LLValue* put(Type* dty, DValue* v)
 {
     LLValue* lval;
     if (v->isLVal()) {
         lval = v->getLVal();
     } else {
         // No memory location, create one.
         LLValue* rval = v->getRVal();
         lval = DtoRawAlloca(rval->getType(), 0);
         DtoStore(rval, lval);
     }
     
     LLType* abiTy = getAbiType(dty);
     assert(abiTy && "Why are we rewriting a non-rewritten type?");
     
     LLType* pTy = getPtrToType(abiTy);
     return DtoLoad(DtoBitCast(lval, pTy), "put-result");
 }
Exemplo n.º 14
0
// routines for constructing the llvm types for MS RTTI structs.
llvm::StructType *getTypeDescriptorType(IRState &irs,
                                        llvm::Constant *classInfoPtr,
                                        llvm::StringRef TypeInfoString) {
  llvm::SmallString<256> TDTypeName("rtti.TypeDescriptor");
  TDTypeName += llvm::utostr(TypeInfoString.size());
  llvm::StructType *&TypeDescriptorType =
      irs.TypeDescriptorTypeMap[TypeInfoString.size()];
  if (TypeDescriptorType)
    return TypeDescriptorType;
  auto int8Ty = LLType::getInt8Ty(gIR->context());
  llvm::Type *FieldTypes[] = {
      classInfoPtr->getType(), // CGM.Int8PtrPtrTy,
      getPtrToType(int8Ty),    // CGM.Int8PtrTy,
      llvm::ArrayType::get(int8Ty, TypeInfoString.size() + 1)};
  TypeDescriptorType =
      llvm::StructType::create(gIR->context(), FieldTypes, TDTypeName);
  return TypeDescriptorType;
}
Exemplo n.º 15
0
LLStructType *DtoModuleReferenceType() {
  if (gIR->moduleRefType) {
    return gIR->moduleRefType;
  }

  // this is a recursive type so start out with a struct without body
  LLStructType *st = LLStructType::create(gIR->context(), "ModuleReference");

  // add members
  LLType *types[] = {getPtrToType(st),
                     DtoType(Module::moduleinfo->type->pointerTo())};

  // resolve type
  st->setBody(types);

  // done
  gIR->moduleRefType = st;
  return st;
}
Exemplo n.º 16
0
static void build_module_ref(std::string moduleMangle, llvm::Constant* thisModuleInfo)
{
    // Build the ModuleInfo reference and bracketing symbols.
    llvm::Type* const moduleInfoPtrTy =
        getPtrToType(DtoType(Module::moduleinfo->type));

    std::string thismrefname = "_D";
    thismrefname += moduleMangle;
    thismrefname += "11__moduleRefZ";
    llvm::GlobalVariable* thismref = new llvm::GlobalVariable(
        gIR->module,
        moduleInfoPtrTy,
        false, // FIXME: mRelocModel != llvm::Reloc::PIC_
        llvm::GlobalValue::LinkOnceODRLinkage,
        DtoBitCast(thisModuleInfo, moduleInfoPtrTy),
        thismrefname
    );
    thismref->setSection(".minfo");
    gIR->usedArray.push_back(thismref);
}
Exemplo n.º 17
0
// helper function that returns the static default initializer of a variable
LLConstant* get_default_initializer(VarDeclaration* vd, Initializer* init)
{
    if (init)
    {
        return DtoConstInitializer(init->loc, vd->type, init);
    }

    if (vd->init)
    {
        return DtoConstInitializer(vd->init->loc, vd->type, vd->init);
    }

    if (vd->type->size(vd->loc) == 0)
    {
        // We need to be able to handle void[0] struct members even if void has
        // no default initializer.
        return llvm::ConstantPointerNull::get(getPtrToType(DtoType(vd->type)));
    }
    return DtoConstExpInit(vd->loc, vd->type, vd->type->defaultInit(vd->loc));
}
Exemplo n.º 18
0
IrTypeDelegate* IrTypeDelegate::get(Type* t)
{
    assert(!t->irtype);
    assert(t->ty == Tdelegate);
    assert(t->nextOf()->ty == Tfunction);

    TypeDelegate *dt = (TypeDelegate*)t;

    if (!dt->irtype)
    {
        TypeFunction* tf = static_cast<TypeFunction*>(dt->nextOf());
        llvm::Type* ltf = DtoFunctionType(tf, dt->irFty, NULL, Type::tvoid->pointerTo());

        llvm::Type *types[] = { getVoidPtrType(), 
                                getPtrToType(ltf) };
        LLStructType* lt = LLStructType::get(gIR->context(), types, false);
        dt->irtype = new IrTypeDelegate(dt, lt);
    }

    return dt->irtype->isDelegate();
}
Exemplo n.º 19
0
void IRLandingPadInfo::toIR()
{
    if (!catchstmt)
        return;

    gIR->scope() = IRScope(target, target);
    DtoDwarfBlockStart(catchstmt->loc);

    // assign storage to catch var
    if(catchstmt->var) {
        // use the same storage for all exceptions that are not accessed in
        // nested functions
        if(!catchstmt->var->nestedrefs.dim) {
            assert(!catchstmt->var->ir.irLocal);
            catchstmt->var->ir.irLocal = new IrLocal(catchstmt->var);
            LLValue* catch_var = gIR->func()->gen->landingPadInfo.getExceptionStorage();
            catchstmt->var->ir.irLocal->value = gIR->ir->CreateBitCast(catch_var, getPtrToType(DtoType(catchstmt->var->type)));
        }

        // this will alloca if we haven't already and take care of nested refs
        DtoDeclarationExp(catchstmt->var);

        // the exception will only be stored in catch_var. copy it over if necessary
        if(catchstmt->var->ir.irLocal->value != gIR->func()->gen->landingPadInfo.getExceptionStorage()) {
            LLValue* exc = gIR->ir->CreateBitCast(DtoLoad(gIR->func()->gen->landingPadInfo.getExceptionStorage()), DtoType(catchstmt->var->type));
            DtoStore(exc, catchstmt->var->ir.irLocal->value);
        }
    }

    // emit handler, if there is one
    // handler is zero for instance for 'catch { debug foo(); }'
    if(catchstmt->handler)
        catchstmt->handler->toIR(gIR);

    if (!gIR->scopereturned())
        gIR->ir->CreateBr(end);

    DtoDwarfBlockEnd();
}
Exemplo n.º 20
0
LLValue* DtoVirtualFunctionPointer(DValue* inst, FuncDeclaration* fdecl, char* name)
{
    // sanity checks
    assert(fdecl->isVirtual());
    assert(!fdecl->isFinal());
    assert(fdecl->vtblIndex > 0); // 0 is always ClassInfo/Interface*
    assert(inst->getType()->toBasetype()->ty == Tclass);

    // get instance
    LLValue* vthis = inst->getRVal();
    if (Logger::enabled())
        Logger::cout() << "vthis: " << *vthis << '\n';

    LLValue* funcval = vthis;
    // get the vtbl for objects
    funcval = DtoGEPi(funcval, 0, 0, "tmp");
    // load vtbl ptr
    funcval = DtoLoad(funcval);
    // index vtbl
    std::string vtblname = name;
    vtblname.append("@vtbl");
    funcval = DtoGEPi(funcval, 0, fdecl->vtblIndex, vtblname.c_str());
    // load funcptr
    funcval = DtoAlignedLoad(funcval);

    if (Logger::enabled())
        Logger::cout() << "funcval: " << *funcval << '\n';

    // cast to final funcptr type
    funcval = DtoBitCast(funcval, getPtrToType(DtoType(fdecl->type)));

    // postpone naming until after casting to get the name in call instructions
    funcval->setName(name);

    if (Logger::enabled())
        Logger::cout() << "funcval casted: " << *funcval << '\n';

    return funcval;
}
Exemplo n.º 21
0
llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl)
{
    // handle for C vararg intrinsics
    if (DtoIsVaIntrinsic(fdecl))
        return DtoVaFunctionType(fdecl);

    Type *dthis=0, *dnest=0;

    if (fdecl->ident == Id::ensure || fdecl->ident == Id::require) {
        FuncDeclaration *p = fdecl->parent->isFuncDeclaration();
        assert(p);
        AggregateDeclaration *ad = p->isMember2();
        assert(ad);
        dnest = Type::tvoid->pointerTo();
    } else
    if (fdecl->needThis()) {
        if (AggregateDeclaration* ad = fdecl->isMember2()) {
            IF_LOG Logger::println("isMember = this is: %s", ad->type->toChars());
            dthis = ad->type;
            LLType* thisty = DtoType(dthis);
            //Logger::cout() << "this llvm type: " << *thisty << '\n';
            if (ad->isStructDeclaration())
                thisty = getPtrToType(thisty);
        }
        else {
            IF_LOG Logger::println("chars: %s type: %s kind: %s", fdecl->toChars(), fdecl->type->toChars(), fdecl->kind());
            llvm_unreachable("needThis, but invalid parent declaration.");
        }
    }
    else if (fdecl->isNested()) {
        dnest = Type::tvoid->pointerTo();
    }

    LLFunctionType* functype = DtoFunctionType(fdecl->type, getIrFunc(fdecl, true)->irFty, dthis, dnest,
                                               fdecl->isMain(), fdecl->isCtorDeclaration(),
                                               fdecl->llvmInternal == LLVMintrinsic);

    return functype;
}
Exemplo n.º 22
0
LLStructType* DtoModuleReferenceType()
{
    if (gIR->moduleRefType)
        return gIR->moduleRefType;

    // this is a recursive type so start out with a struct without body
    LLStructType* st = LLStructType::create(gIR->context(), "ModuleReference");

    // add members
    std::vector<LLType*> types;
    types.push_back(getPtrToType(st));
#if DMDV1
    types.push_back(DtoType(Module::moduleinfo->type));
#else
    types.push_back(DtoType(Module::moduleinfo->type->pointerTo()));
#endif

    // resolve type
    st->setBody(types);

    // done
    gIR->moduleRefType = st;
    return st;
}
Exemplo n.º 23
0
Arquivo: aa.cpp Projeto: glycerine/ldc
DValue* DtoAAIndex(Loc& loc, Type* type, DValue* aa, DValue* key, bool lvalue)
{
    // D1:
    // call:
    // extern(C) void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, void* pkey)
    // or
    // extern(C) void* _aaIn(AA aa*, TypeInfo keyti, void* pkey)

    // D2:
    // call:
    // extern(C) void* _aaGetX(AA* aa, TypeInfo keyti, size_t valuesize, void* pkey)
    // or
    // extern(C) void* _aaInX(AA aa*, TypeInfo keyti, void* pkey)

    // first get the runtime function
    llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, lvalue?"_aaGetX":"_aaInX");
    LLFunctionType* funcTy = func->getFunctionType();

    // aa param
    LLValue* aaval = lvalue ? aa->getLVal() : aa->getRVal();
    aaval = DtoBitCast(aaval, funcTy->getParamType(0));

    // keyti param
    LLValue* keyti = to_keyti(aa);
    keyti = DtoBitCast(keyti, funcTy->getParamType(1));

    // pkey param
    LLValue* pkey = makeLValue(loc, key);
    pkey = DtoBitCast(pkey, funcTy->getParamType(lvalue ? 3 : 2));

    // call runtime
    LLValue* ret;
    if (lvalue) {
        // valuesize param
        LLValue* valsize = DtoConstSize_t(getTypePaddedSize(DtoType(type)));

        ret = gIR->CreateCallOrInvoke4(func, aaval, keyti, valsize, pkey, "aa.index").getInstruction();
    } else {
        ret = gIR->CreateCallOrInvoke3(func, aaval, keyti, pkey, "aa.index").getInstruction();
    }

    // cast return value
    LLType* targettype = getPtrToType(DtoType(type));
    if (ret->getType() != targettype)
        ret = DtoBitCast(ret, targettype);

    // Only check bounds for rvalues ('aa[key]').
    // Lvalue use ('aa[key] = value') auto-adds an element.
    if (!lvalue && global.params.useArrayBounds) {
        llvm::BasicBlock* oldend = gIR->scopeend();
        llvm::BasicBlock* failbb = llvm::BasicBlock::Create(gIR->context(), "aaboundscheckfail", gIR->topfunc(), oldend);
        llvm::BasicBlock* okbb = llvm::BasicBlock::Create(gIR->context(), "aaboundsok", gIR->topfunc(), oldend);

        LLValue* nullaa = LLConstant::getNullValue(ret->getType());
        LLValue* cond = gIR->ir->CreateICmpNE(nullaa, ret, "aaboundscheck");
        gIR->ir->CreateCondBr(cond, okbb, failbb);

        // set up failbb to call the array bounds error runtime function

        gIR->scope() = IRScope(failbb, okbb);

        std::vector<LLValue*> args;

        // module param
        LLValue *moduleInfoSymbol = gIR->func()->decl->getModule()->moduleInfoSymbol();
        LLType *moduleInfoType = DtoType(Module::moduleinfo->type);
        args.push_back(DtoBitCast(moduleInfoSymbol, getPtrToType(moduleInfoType)));

        // line param
        LLConstant* c = DtoConstUint(loc.linnum);
        args.push_back(c);

        // call
        llvm::Function* errorfn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_array_bounds");
        gIR->CreateCallOrInvoke(errorfn, args);

        // the function does not return
        gIR->ir->CreateUnreachable();

        // if ok, proceed in okbb
        gIR->scope() = IRScope(okbb, oldend);
    }
    return new DVarValue(type, ret);
}
Exemplo n.º 24
0
LLStructType* DtoMutexType()
{
    if (gIR->mutexType)
        return gIR->mutexType;

    // The structures defined here must be the same as in druntime/src/rt/critical.c

    // Windows
    if (global.params.targetTriple.isOSWindows())
    {
        llvm::Type *VoidPtrTy = llvm::Type::getInt8PtrTy(gIR->context());
        llvm::Type *Int32Ty = llvm::Type::getInt32Ty(gIR->context());

        // Build RTL_CRITICAL_SECTION; size is 24 (32bit) or 40 (64bit)
        LLType *rtl_types[] = {
            VoidPtrTy, // Pointer to DebugInfo
            Int32Ty,   // LockCount
            Int32Ty,   // RecursionCount
            VoidPtrTy, // Handle of OwningThread
            VoidPtrTy, // Handle of LockSemaphore
            VoidPtrTy  // SpinCount
        };
        LLStructType* rtl = LLStructType::create(gIR->context(), rtl_types, "RTL_CRITICAL_SECTION");

        // Build D_CRITICAL_SECTION; size is 28 (32bit) or 48 (64bit)
        LLStructType *mutex = LLStructType::create(gIR->context(), "D_CRITICAL_SECTION");
        LLType *types[] = { getPtrToType(mutex), rtl };
        mutex->setBody(types);

        // Cache type
        gIR->mutexType = mutex;

        return mutex;
    }

    // FreeBSD
    else if (global.params.targetTriple.getOS() == llvm::Triple::FreeBSD) {
        // Just a pointer
        return LLStructType::get(gIR->context(), DtoSize_t());
    }

    // pthread_fastlock
    LLType *types2[] = {
        DtoSize_t(),
        LLType::getInt32Ty(gIR->context()) 
    };
    LLStructType* fastlock = LLStructType::get(gIR->context(), types2, false);

    // pthread_mutex
    LLType *types1[] = {
        LLType::getInt32Ty(gIR->context()),
        LLType::getInt32Ty(gIR->context()),
        getVoidPtrType(),
        LLType::getInt32Ty(gIR->context()),
        fastlock
    };
    LLStructType* pmutex = LLStructType::get(gIR->context(), types1, false);

    // D_CRITICAL_SECTION
    LLStructType* mutex = LLStructType::create(gIR->context(), "D_CRITICAL_SECTION");
    LLType *types[] = { getPtrToType(mutex), pmutex };
    mutex->setBody(types);

    // Cache type
    gIR->mutexType = mutex;

    return pmutex;
}
Exemplo n.º 25
0
LLPointerType* getVoidPtrType()
{
    return getPtrToType(LLType::getInt8Ty(gIR->context()));
}
Exemplo n.º 26
0
void IRLandingPad::constructLandingPad(llvm::BasicBlock* inBB)
{
    // save and rewrite scope
    IRScope savedscope = gIR->scope();
    gIR->scope() = IRScope(inBB,savedscope.end);

    // eh_ptr = llvm.eh.exception();
    llvm::Function* eh_exception_fn = GET_INTRINSIC_DECL(eh_exception);
    LLValue* eh_ptr = gIR->ir->CreateCall(eh_exception_fn);

    // build selector arguments
    LLSmallVector<LLValue*, 6> selectorargs;

    // put in classinfos in the right order
    bool hasFinally = false;
    bool hasCatch = false;
    std::deque<IRLandingPadInfo>::iterator it = infos.begin(), end = infos.end();
    for(; it != end; ++it)
    {
        if(it->finallyBody)
            hasFinally = true;
        else
        {
            hasCatch = true;
            assert(it->catchType);
            assert(it->catchType->ir.irStruct);
            selectorargs.insert(selectorargs.begin(), it->catchType->ir.irStruct->getClassInfoSymbol());
        }
    }
    // if there's a finally, the eh table has to have a 0 action
    if(hasFinally)
        selectorargs.push_back(DtoConstUint(0));

    // personality fn
    llvm::Function* personality_fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_eh_personality");
    LLValue* personality_fn_arg = gIR->ir->CreateBitCast(personality_fn, getPtrToType(LLType::getInt8Ty(gIR->context())));
    selectorargs.insert(selectorargs.begin(), personality_fn_arg);

    // eh storage target
    selectorargs.insert(selectorargs.begin(), eh_ptr);

    // if there is a catch and some catch allocated storage, store exception object
    if(hasCatch && catch_var)
    {
        const LLType* objectTy = DtoType(ClassDeclaration::object->type);
        gIR->ir->CreateStore(gIR->ir->CreateBitCast(eh_ptr, objectTy), catch_var);
    }

    // eh_sel = llvm.eh.selector(eh_ptr, cast(byte*)&_d_eh_personality, <selectorargs>);
    llvm::Function* eh_selector_fn = GET_INTRINSIC_DECL(eh_selector);
    LLValue* eh_sel = gIR->ir->CreateCall(eh_selector_fn, selectorargs.begin(), selectorargs.end());

    // emit finallys and 'if' chain to catch the exception
    llvm::Function* eh_typeid_for_fn = GET_INTRINSIC_DECL(eh_typeid_for);
    std::deque<IRLandingPadInfo> infos = this->infos;
    std::stack<size_t> nInfos = this->nInfos;
    std::deque<IRLandingPadInfo>::reverse_iterator rit, rend = infos.rend();
    for(rit = infos.rbegin(); rit != rend; ++rit)
    {
        // if it's a finally, emit its code
        if(rit->finallyBody)
        {
            size_t n = this->nInfos.top();
            this->infos.resize(n);
            this->nInfos.pop();
            rit->finallyBody->toIR(gIR);
        }
        // otherwise it's a catch and we'll add a if-statement
        else
        {
            llvm::BasicBlock *next = llvm::BasicBlock::Create(gIR->context(), "eh.next", gIR->topfunc(), gIR->scopeend());
            LLValue *classInfo = DtoBitCast(rit->catchType->ir.irStruct->getClassInfoSymbol(),
                                            getPtrToType(DtoType(Type::tint8)));
            LLValue *eh_id = gIR->ir->CreateCall(eh_typeid_for_fn, classInfo);
            gIR->ir->CreateCondBr(gIR->ir->CreateICmpEQ(eh_sel, eh_id), rit->target, next);
            gIR->scope() = IRScope(next, gIR->scopeend());
        }
    }

    // restore landing pad infos
    this->infos = infos;
    this->nInfos = nInfos;

    // no catch matched and all finallys executed - resume unwind
    llvm::Function* unwind_resume_fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_eh_resume_unwind");
    gIR->ir->CreateCall(unwind_resume_fn, eh_ptr);
    gIR->ir->CreateUnreachable();

    gIR->scope() = savedscope;
}
Exemplo n.º 27
0
DValue* DtoNewClass(Loc& loc, TypeClass* tc, NewExp* newexp)
{
    // resolve type
    DtoResolveClass(tc->sym);

    // allocate
    LLValue* mem;
    if (newexp->onstack)
    {
        // FIXME align scope class to its largest member
        mem = DtoRawAlloca(DtoType(tc)->getContainedType(0), 0, ".newclass_alloca");
    }
    // custom allocator
    else if (newexp->allocator)
    {
        DtoResolveFunction(newexp->allocator);
        DFuncValue dfn(newexp->allocator, getIrFunc(newexp->allocator)->func);
        DValue* res = DtoCallFunction(newexp->loc, NULL, &dfn, newexp->newargs);
        mem = DtoBitCast(res->getRVal(), DtoType(tc), ".newclass_custom");
    }
    // default allocator
    else
    {
        llvm::Function* fn = LLVM_D_GetRuntimeFunction(loc, gIR->module, "_d_newclass");
        LLConstant* ci = DtoBitCast(getIrAggr(tc->sym)->getClassInfoSymbol(), DtoType(Type::typeinfoclass->type));
        mem = gIR->CreateCallOrInvoke(fn, ci, ".newclass_gc_alloc").getInstruction();
        mem = DtoBitCast(mem, DtoType(tc), ".newclass_gc");
    }

    // init
    DtoInitClass(tc, mem);

    // init inner-class outer reference
    if (newexp->thisexp)
    {
        Logger::println("Resolving outer class");
        LOG_SCOPE;
        DValue* thisval = toElem(newexp->thisexp);
        unsigned idx = getFieldGEPIndex(tc->sym, tc->sym->vthis);
        LLValue* src = thisval->getRVal();
        LLValue* dst = DtoGEPi(mem, 0, idx);
        IF_LOG Logger::cout() << "dst: " << *dst << "\nsrc: " << *src << '\n';
        DtoStore(src, DtoBitCast(dst, getPtrToType(src->getType())));
    }
    // set the context for nested classes
    else if (tc->sym->isNested() && tc->sym->vthis)
    {
        DtoResolveNestedContext(loc, tc->sym, mem);
    }

    // call constructor
    if (newexp->member)
    {
        Logger::println("Calling constructor");
        assert(newexp->arguments != NULL);
        DtoResolveFunction(newexp->member);
        DFuncValue dfn(newexp->member, getIrFunc(newexp->member)->func, mem);
        return DtoCallFunction(newexp->loc, tc, &dfn, newexp->arguments);
    }

    // return default constructed class
    return new DImValue(tc, mem);
}
Exemplo n.º 28
0
void IRLandingPad::constructLandingPad(llvm::BasicBlock* inBB)
{
    // save and rewrite scope
    IRScope savedscope = gIR->scope();
    gIR->scope() = IRScope(inBB,savedscope.end);

    // personality fn
    llvm::Function* personality_fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_eh_personality");
    // create landingpad
    LLType *retType = LLStructType::get(LLType::getInt8PtrTy(gIR->context()), LLType::getInt32Ty(gIR->context()), NULL);
    llvm::LandingPadInst *landingPad = gIR->ir->CreateLandingPad(retType, personality_fn, 0);
    LLValue* eh_ptr = DtoExtractValue(landingPad, 0);
    LLValue* eh_sel = DtoExtractValue(landingPad, 1);

    // add landingpad clauses, emit finallys and 'if' chain to catch the exception
    llvm::Function* eh_typeid_for_fn = GET_INTRINSIC_DECL(eh_typeid_for);
    std::deque<IRLandingPadInfo> infos = this->infos;
    std::stack<size_t> nInfos = this->nInfos;
    std::deque<IRLandingPadInfo>::reverse_iterator rit, rend = infos.rend();
    bool isFirstCatch = true;
    for(rit = infos.rbegin(); rit != rend; ++rit)
    {
        // if it's a finally, emit its code
        if(rit->finallyBody)
        {
            size_t n = this->nInfos.top();
            this->infos.resize(n);
            this->nInfos.pop();
            rit->finallyBody->toIR(gIR);
            landingPad->setCleanup(true);
        }
        // otherwise it's a catch and we'll add a if-statement
        else
        {
            // if it is a first catch and some catch allocated storage, store exception object
            if(isFirstCatch && catch_var)
            {
                LLType* objectTy = DtoType(ClassDeclaration::object->type);
                gIR->ir->CreateStore(gIR->ir->CreateBitCast(eh_ptr, objectTy), catch_var);
                isFirstCatch = false;
            }
            // create next block
            llvm::BasicBlock *next = llvm::BasicBlock::Create(gIR->context(), "eh.next", gIR->topfunc(), gIR->scopeend());
            // get class info symbol
            LLValue *classInfo = rit->catchType->ir.irStruct->getClassInfoSymbol();
            // add that symbol as landing pad clause
            landingPad->addClause(classInfo);
            // call llvm.eh.typeid.for to get class info index in the exception table
            classInfo = DtoBitCast(classInfo, getPtrToType(DtoType(Type::tint8)));
            LLValue *eh_id = gIR->ir->CreateCall(eh_typeid_for_fn, classInfo);
            // check exception selector (eh_sel) against the class info index
            gIR->ir->CreateCondBr(gIR->ir->CreateICmpEQ(eh_sel, eh_id), rit->target, next);
            gIR->scope() = IRScope(next, gIR->scopeend());
        }
    }

    // restore landing pad infos
    this->infos = infos;
    this->nInfos = nInfos;

    // no catch matched and all finallys executed - resume unwind
    llvm::Function* unwind_resume_fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_eh_resume_unwind");
    gIR->ir->CreateCall(unwind_resume_fn, eh_ptr);
    gIR->ir->CreateUnreachable();

    // restore scope
    gIR->scope() = savedscope;
}
Exemplo n.º 29
0
DValue* DtoNestedVariable(Loc& loc, Type* astype, VarDeclaration* vd, bool byref)
{
    IF_LOG Logger::println("DtoNestedVariable for %s @ %s", vd->toChars(), loc.toChars());
    LOG_SCOPE;

    ////////////////////////////////////
    // Locate context value

    Dsymbol* vdparent = vd->toParent2();
    assert(vdparent);

    IrFunction* irfunc = gIR->func();

    // Check whether we can access the needed frame
    FuncDeclaration *fd = irfunc->decl;
    while (fd != vdparent) {
        if (fd->isStatic()) {
            error(loc, "function %s cannot access frame of function %s", irfunc->decl->toPrettyChars(), vdparent->toPrettyChars());
            return new DVarValue(astype, vd, llvm::UndefValue::get(getPtrToType(DtoType(astype))));
        }
        fd = getParentFunc(fd, false);
        assert(fd);
    }

    // is the nested variable in this scope?
    if (vdparent == irfunc->decl)
    {
        LLValue* val = vd->ir.getIrValue();
        return new DVarValue(astype, vd, val);
    }

    LLValue *dwarfValue = 0;
    std::vector<LLValue*> dwarfAddr;

    // get the nested context
    LLValue* ctx = 0;
    if (irfunc->nestedVar) {
        // If this function has its own nested context struct, always load it.
        ctx = irfunc->nestedVar;
        dwarfValue = ctx;
    } else if (irfunc->decl->isMember2()) {
        // If this is a member function of a nested class without its own
        // context, load the vthis member.
        AggregateDeclaration* cd = irfunc->decl->isMember2();
        LLValue* val = irfunc->thisArg;
        if (cd->isClassDeclaration())
            val = DtoLoad(val);
        ctx = DtoLoad(DtoGEPi(val, 0, cd->vthis->ir.irField->index, ".vthis"));
    } else {
        // Otherwise, this is a simple nested function, load from the context
        // argument.
        ctx = DtoLoad(irfunc->nestArg);
        dwarfValue = irfunc->nestArg;
        if (global.params.symdebug)
            gIR->DBuilder.OpDeref(dwarfAddr);
    }
    assert(ctx);

    DtoCreateNestedContextType(vdparent->isFuncDeclaration());
    assert(vd->ir.irLocal);

    ////////////////////////////////////
    // Extract variable from nested context

    LLValue* val = DtoBitCast(ctx, LLPointerType::getUnqual(irfunc->frameType));
    IF_LOG {
        Logger::cout() << "Context: " << *val << '\n';
        Logger::cout() << "of type: " << *irfunc->frameType << '\n';
    }

    unsigned vardepth = vd->ir.irLocal->nestedDepth;
    unsigned funcdepth = irfunc->depth;

    IF_LOG {
        Logger::cout() << "Variable: " << vd->toChars() << '\n';
        Logger::cout() << "Variable depth: " << vardepth << '\n';
        Logger::cout() << "Function: " << irfunc->decl->toChars() << '\n';
        Logger::cout() << "Function depth: " << funcdepth << '\n';
    }

    if (vardepth == funcdepth) {
        // This is not always handled above because functions without
        // variables accessed by nested functions don't create new frames.
        IF_LOG Logger::println("Same depth");
    } else {
        // Load frame pointer and index that...
        if (dwarfValue && global.params.symdebug) {
            gIR->DBuilder.OpOffset(dwarfAddr, val, vd->ir.irLocal->nestedDepth);
            gIR->DBuilder.OpDeref(dwarfAddr);
        }
        IF_LOG Logger::println("Lower depth");
        val = DtoGEPi(val, 0, vd->ir.irLocal->nestedDepth);
        IF_LOG Logger::cout() << "Frame index: " << *val << '\n';
        val = DtoAlignedLoad(val, (std::string(".frame.") + vdparent->toChars()).c_str());
        IF_LOG Logger::cout() << "Frame: " << *val << '\n';
    }

    int idx = vd->ir.irLocal->nestedIndex;
    assert(idx != -1 && "Nested context not yet resolved for variable.");

    if (dwarfValue && global.params.symdebug)
        gIR->DBuilder.OpOffset(dwarfAddr, val, idx);

    val = DtoGEPi(val, 0, idx, vd->toChars());
    IF_LOG {
        Logger::cout() << "Addr: " << *val << '\n';
        Logger::cout() << "of type: " << *val->getType() << '\n';
    }
    if (byref || (vd->isParameter() && vd->ir.irParam->arg->byref)) {
        val = DtoAlignedLoad(val);
        //dwarfOpDeref(dwarfAddr);
        IF_LOG {
            Logger::cout() << "Was byref, now: " << *val << '\n';
            Logger::cout() << "of type: " << *val->getType() << '\n';
        }
    }
Exemplo n.º 30
0
 // Get struct from ABI-mangled representation, and store in the provided location.
 void getL(Type* dty, DValue* v, llvm::Value* lval) {
     LLValue* rval = v->getRVal();
     LLType* pTy = getPtrToType(rval->getType());
     DtoStore(rval, DtoBitCast(lval, pTy));
 }