mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-02 16:11:08 +03:00
127 lines
3.7 KiB
C++
127 lines
3.7 KiB
C++
//===-- dvalue.cpp --------------------------------------------------------===//
|
||
//
|
||
// LDC – the LLVM D compiler
|
||
//
|
||
// This file is distributed under the BSD-style LDC license. See the LICENSE
|
||
// file for details.
|
||
//
|
||
//===----------------------------------------------------------------------===//
|
||
|
||
#include "gen/dvalue.h"
|
||
#include "declaration.h"
|
||
#include "gen/irstate.h"
|
||
#include "gen/llvm.h"
|
||
#include "gen/llvmhelpers.h"
|
||
#include "gen/logger.h"
|
||
#include "gen/tollvm.h"
|
||
|
||
namespace {
|
||
bool isDefinedInFuncEntryBB(LLValue *v) {
|
||
auto instr = llvm::dyn_cast<llvm::Instruction>(v);
|
||
if (!instr) {
|
||
// Global, constant, ...
|
||
return true;
|
||
}
|
||
|
||
auto bb = instr->getParent();
|
||
if (bb != &(bb->getParent()->getEntryBlock())) {
|
||
return false;
|
||
}
|
||
|
||
// An invoke instruction in the entry BB does not necessarily dominate the
|
||
// rest of the function because of the failure path.
|
||
return !llvm::isa<llvm::InvokeInst>(instr);
|
||
}
|
||
}
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
bool DValue::definedInFuncEntryBB() { return isDefinedInFuncEntryBB(val); }
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
DImValue::DImValue(Type *t, llvm::Value *v) : DValue(t, v) {
|
||
assert(!DtoIsInMemoryOnly(t) &&
|
||
"Cannot represent memory-only type as immediate DValue");
|
||
}
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
DConstValue::DConstValue(Type *t, llvm::Constant *con) : DValue(t, con) {}
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
static bool checkVarValueType(LLType *t, bool extraDeref) {
|
||
if (extraDeref) {
|
||
llvm::PointerType *pt = llvm::dyn_cast<llvm::PointerType>(t);
|
||
if (!pt) {
|
||
return false;
|
||
}
|
||
|
||
t = pt->getElementType();
|
||
}
|
||
|
||
llvm::PointerType *pt = llvm::dyn_cast<llvm::PointerType>(t);
|
||
if (!pt) {
|
||
return false;
|
||
}
|
||
|
||
// bools should not be stored as i1 any longer.
|
||
if (pt->getElementType() == llvm::Type::getInt1Ty(gIR->context())) {
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
DLValue::DLValue(Type *t, LLValue *v) : DValue(t, v) {
|
||
assert(checkVarValueType(v->getType(), false));
|
||
}
|
||
|
||
LLValue *DLValue::getRVal() {
|
||
if (DtoIsInMemoryOnly(type->toBasetype())) {
|
||
llvm_unreachable("getRVal() for memory-only type");
|
||
return nullptr;
|
||
}
|
||
|
||
LLValue *rawValue = DtoLoad(val);
|
||
if (type->toBasetype()->ty != Tbool)
|
||
return rawValue;
|
||
|
||
assert(rawValue->getType() == llvm::Type::getInt8Ty(gIR->context()));
|
||
return gIR->ir->CreateTrunc(rawValue, llvm::Type::getInt1Ty(gIR->context()));
|
||
}
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
DSpecialRefValue::DSpecialRefValue(Type *t, LLValue *v) : DLValue(v, t) {
|
||
assert(checkVarValueType(v->getType(), true));
|
||
}
|
||
|
||
LLValue *DSpecialRefValue::getLVal() { return DtoLoad(val); }
|
||
|
||
LLValue *DSpecialRefValue::getRVal() {
|
||
return DLValue(type, getLVal()).getRVal();
|
||
}
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
DSliceValue::DSliceValue(Type *t, LLValue *length, LLValue *ptr)
|
||
: DValue(t, DtoAggrPair(length, ptr)) {}
|
||
|
||
LLValue *DSliceValue::getLength() { return DtoExtractValue(val, 0, ".len"); }
|
||
|
||
LLValue *DSliceValue::getPtr() { return DtoExtractValue(val, 1, ".ptr"); }
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
DFuncValue::DFuncValue(Type *t, FuncDeclaration *fd, LLValue *v, LLValue *vt)
|
||
: DValue(t, v), func(fd), vthis(vt) {}
|
||
|
||
DFuncValue::DFuncValue(FuncDeclaration *fd, LLValue *v, LLValue *vt)
|
||
: DValue(fd->type, v), func(fd), vthis(vt) {}
|
||
|
||
bool DFuncValue::definedInFuncEntryBB() {
|
||
return isDefinedInFuncEntryBB(val) &&
|
||
(!vthis || isDefinedInFuncEntryBB(vthis));
|
||
}
|