mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-03 00:20:40 +03:00

DSliceValue is still a special case and contains pointer and length separately, which are packed to a LL struct in getRVal(). It'd probably pay off to do it the other way around and store the LL struct as single value and allowing for access to the components.
149 lines
3.7 KiB
C++
149 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(llvm::Value *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 DImValue::definedInFuncEntryBB() { return isDefinedInFuncEntryBB(val); }
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
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;
|
||
}
|
||
|
||
DVarValue::DVarValue(Type *t, LLValue *v, bool isSpecialRefVar)
|
||
: DValue(t, v), isSpecialRefVar(isSpecialRefVar) {
|
||
assert(v && "Unexpected null llvm::Value.");
|
||
assert(checkVarValueType(v->getType(), isSpecialRefVar));
|
||
}
|
||
|
||
LLValue *DVarValue::getLVal() { return isSpecialRefVar ? DtoLoad(val) : val; }
|
||
|
||
LLValue *DVarValue::getRVal() {
|
||
assert(val);
|
||
|
||
llvm::Value *storage = val;
|
||
if (isSpecialRefVar) {
|
||
storage = DtoLoad(storage);
|
||
}
|
||
|
||
if (DtoIsInMemoryOnly(type->toBasetype())) {
|
||
return storage;
|
||
}
|
||
|
||
llvm::Value *rawValue = DtoLoad(storage);
|
||
|
||
if (type->toBasetype()->ty == Tbool) {
|
||
assert(rawValue->getType() == llvm::Type::getInt8Ty(gIR->context()));
|
||
return gIR->ir->CreateTrunc(rawValue,
|
||
llvm::Type::getInt1Ty(gIR->context()));
|
||
}
|
||
|
||
return rawValue;
|
||
}
|
||
|
||
LLValue *DVarValue::getRefStorage() {
|
||
assert(isSpecialRefVar);
|
||
return val;
|
||
}
|
||
|
||
bool DVarValue::definedInFuncEntryBB() { return isDefinedInFuncEntryBB(val); }
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
LLValue *DSliceValue::getRVal() {
|
||
assert(len);
|
||
assert(ptr);
|
||
return DtoAggrPair(len, ptr);
|
||
}
|
||
|
||
bool DSliceValue::definedInFuncEntryBB() {
|
||
return isDefinedInFuncEntryBB(len) && isDefinedInFuncEntryBB(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) {}
|
||
|
||
LLValue *DFuncValue::getRVal() {
|
||
assert(val);
|
||
return val;
|
||
}
|
||
|
||
bool DFuncValue::definedInFuncEntryBB() {
|
||
if (!isDefinedInFuncEntryBB(val)) {
|
||
return false;
|
||
}
|
||
|
||
if (vthis && !isDefinedInFuncEntryBB(vthis)) {
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
DConstValue::DConstValue(Type *t, llvm::Constant *con)
|
||
: DValue(t, static_cast<LLValue *>(con)) {}
|
||
|
||
LLValue *DConstValue::getRVal() {
|
||
assert(val);
|
||
return val;
|
||
}
|