| 1 |
#include "gen/llvm.h" |
|---|
| 2 |
|
|---|
| 3 |
#include "mtype.h" |
|---|
| 4 |
#include "module.h" |
|---|
| 5 |
#include "declaration.h" |
|---|
| 6 |
#include "aggregate.h" |
|---|
| 7 |
|
|---|
| 8 |
#include "gen/aa.h" |
|---|
| 9 |
#include "gen/runtime.h" |
|---|
| 10 |
#include "gen/tollvm.h" |
|---|
| 11 |
#include "gen/llvmhelpers.h" |
|---|
| 12 |
#include "gen/logger.h" |
|---|
| 13 |
#include "gen/irstate.h" |
|---|
| 14 |
#include "gen/dvalue.h" |
|---|
| 15 |
#include "ir/irmodule.h" |
|---|
| 16 |
|
|---|
| 17 |
// returns the keytype typeinfo |
|---|
| 18 |
static LLValue* to_keyti(DValue* key) |
|---|
| 19 |
{ |
|---|
| 20 |
// keyti param |
|---|
| 21 |
Type* keytype = key->getType(); |
|---|
| 22 |
return DtoTypeInfoOf(keytype, false); |
|---|
| 23 |
} |
|---|
| 24 |
|
|---|
| 25 |
///////////////////////////////////////////////////////////////////////////////////// |
|---|
| 26 |
|
|---|
| 27 |
DValue* DtoAAIndex(Loc& loc, Type* type, DValue* aa, DValue* key, bool lvalue) |
|---|
| 28 |
{ |
|---|
| 29 |
// call: |
|---|
| 30 |
// extern(C) void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, void* pkey) |
|---|
| 31 |
// or |
|---|
| 32 |
// extern(C) void* _aaIn(AA aa*, TypeInfo keyti, void* pkey) |
|---|
| 33 |
|
|---|
| 34 |
// first get the runtime function |
|---|
| 35 |
llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, lvalue?"_aaGet":"_aaIn"); |
|---|
| 36 |
const llvm::FunctionType* funcTy = func->getFunctionType(); |
|---|
| 37 |
|
|---|
| 38 |
// aa param |
|---|
| 39 |
LLValue* aaval = lvalue ? aa->getLVal() : aa->getRVal(); |
|---|
| 40 |
aaval = DtoBitCast(aaval, funcTy->getParamType(0)); |
|---|
| 41 |
|
|---|
| 42 |
// keyti param |
|---|
| 43 |
LLValue* keyti = to_keyti(key); |
|---|
| 44 |
keyti = DtoBitCast(keyti, funcTy->getParamType(1)); |
|---|
| 45 |
|
|---|
| 46 |
// pkey param |
|---|
| 47 |
LLValue* pkey = makeLValue(loc, key); |
|---|
| 48 |
pkey = DtoBitCast(pkey, funcTy->getParamType(lvalue ? 3 : 2)); |
|---|
| 49 |
|
|---|
| 50 |
// call runtime |
|---|
| 51 |
LLValue* ret; |
|---|
| 52 |
if (lvalue) { |
|---|
| 53 |
// valuesize param |
|---|
| 54 |
LLValue* valsize = DtoConstSize_t(getTypePaddedSize(DtoType(type))); |
|---|
| 55 |
|
|---|
| 56 |
ret = gIR->CreateCallOrInvoke4(func, aaval, keyti, valsize, pkey, "aa.index").getInstruction(); |
|---|
| 57 |
} else { |
|---|
| 58 |
ret = gIR->CreateCallOrInvoke3(func, aaval, keyti, pkey, "aa.index").getInstruction(); |
|---|
| 59 |
} |
|---|
| 60 |
|
|---|
| 61 |
// cast return value |
|---|
| 62 |
const LLType* targettype = getPtrToType(DtoType(type)); |
|---|
| 63 |
if (ret->getType() != targettype) |
|---|
| 64 |
ret = DtoBitCast(ret, targettype); |
|---|
| 65 |
|
|---|
| 66 |
// Only check bounds for rvalues ('aa[key]'). |
|---|
| 67 |
// Lvalue use ('aa[key] = value') auto-adds an element. |
|---|
| 68 |
if (!lvalue && global.params.useArrayBounds) { |
|---|
| 69 |
llvm::BasicBlock* oldend = gIR->scopeend(); |
|---|
| 70 |
llvm::BasicBlock* failbb = llvm::BasicBlock::Create(gIR->context(), "aaboundscheckfail", gIR->topfunc(), oldend); |
|---|
| 71 |
llvm::BasicBlock* okbb = llvm::BasicBlock::Create(gIR->context(), "aaboundsok", gIR->topfunc(), oldend); |
|---|
| 72 |
|
|---|
| 73 |
LLValue* nullaa = LLConstant::getNullValue(ret->getType()); |
|---|
| 74 |
LLValue* cond = gIR->ir->CreateICmpNE(nullaa, ret, "aaboundscheck"); |
|---|
| 75 |
gIR->ir->CreateCondBr(cond, okbb, failbb); |
|---|
| 76 |
|
|---|
| 77 |
// set up failbb to call the array bounds error runtime function |
|---|
| 78 |
|
|---|
| 79 |
gIR->scope() = IRScope(failbb, okbb); |
|---|
| 80 |
|
|---|
| 81 |
std::vector<LLValue*> args; |
|---|
| 82 |
|
|---|
| 83 |
// file param |
|---|
| 84 |
IrModule* irmod = getIrModule(NULL); |
|---|
| 85 |
args.push_back(DtoLoad(irmod->fileName)); |
|---|
| 86 |
|
|---|
| 87 |
// line param |
|---|
| 88 |
LLConstant* c = DtoConstUint(loc.linnum); |
|---|
| 89 |
args.push_back(c); |
|---|
| 90 |
|
|---|
| 91 |
// call |
|---|
| 92 |
llvm::Function* errorfn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_array_bounds"); |
|---|
| 93 |
gIR->CreateCallOrInvoke(errorfn, args.begin(), args.end()); |
|---|
| 94 |
|
|---|
| 95 |
// the function does not return |
|---|
| 96 |
gIR->ir->CreateUnreachable(); |
|---|
| 97 |
|
|---|
| 98 |
// if ok, proceed in okbb |
|---|
| 99 |
gIR->scope() = IRScope(okbb, oldend); |
|---|
| 100 |
} |
|---|
| 101 |
return new DVarValue(type, ret); |
|---|
| 102 |
} |
|---|
| 103 |
|
|---|
| 104 |
///////////////////////////////////////////////////////////////////////////////////// |
|---|
| 105 |
|
|---|
| 106 |
DValue* DtoAAIn(Loc& loc, Type* type, DValue* aa, DValue* key) |
|---|
| 107 |
{ |
|---|
| 108 |
// call: |
|---|
| 109 |
// extern(C) void* _aaIn(AA aa*, TypeInfo keyti, void* pkey) |
|---|
| 110 |
|
|---|
| 111 |
// first get the runtime function |
|---|
| 112 |
llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_aaIn"); |
|---|
| 113 |
const llvm::FunctionType* funcTy = func->getFunctionType(); |
|---|
| 114 |
|
|---|
| 115 |
if (Logger::enabled()) |
|---|
| 116 |
Logger::cout() << "_aaIn = " << *func << '\n'; |
|---|
| 117 |
|
|---|
| 118 |
// aa param |
|---|
| 119 |
LLValue* aaval = aa->getRVal(); |
|---|
| 120 |
if (Logger::enabled()) |
|---|
| 121 |
{ |
|---|
| 122 |
Logger::cout() << "aaval: " << *aaval << '\n'; |
|---|
| 123 |
Logger::cout() << "totype: " << *funcTy->getParamType(0) << '\n'; |
|---|
| 124 |
} |
|---|
| 125 |
aaval = DtoBitCast(aaval, funcTy->getParamType(0)); |
|---|
| 126 |
|
|---|
| 127 |
// keyti param |
|---|
| 128 |
LLValue* keyti = to_keyti(key); |
|---|
| 129 |
keyti = DtoBitCast(keyti, funcTy->getParamType(1)); |
|---|
| 130 |
|
|---|
| 131 |
// pkey param |
|---|
| 132 |
LLValue* pkey = makeLValue(loc, key); |
|---|
| 133 |
pkey = DtoBitCast(pkey, funcTy->getParamType(2)); |
|---|
| 134 |
|
|---|
| 135 |
// call runtime |
|---|
| 136 |
LLValue* ret = gIR->CreateCallOrInvoke3(func, aaval, keyti, pkey, "aa.in").getInstruction(); |
|---|
| 137 |
|
|---|
| 138 |
// cast return value |
|---|
| 139 |
const LLType* targettype = DtoType(type); |
|---|
| 140 |
if (ret->getType() != targettype) |
|---|
| 141 |
ret = DtoBitCast(ret, targettype); |
|---|
| 142 |
|
|---|
| 143 |
return new DImValue(type, ret); |
|---|
| 144 |
} |
|---|
| 145 |
|
|---|
| 146 |
///////////////////////////////////////////////////////////////////////////////////// |
|---|
| 147 |
|
|---|
| 148 |
void DtoAARemove(Loc& loc, DValue* aa, DValue* key) |
|---|
| 149 |
{ |
|---|
| 150 |
// call: |
|---|
| 151 |
// extern(C) void _aaDel(AA aa, TypeInfo keyti, void* pkey) |
|---|
| 152 |
|
|---|
| 153 |
// first get the runtime function |
|---|
| 154 |
llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_aaDel"); |
|---|
| 155 |
const llvm::FunctionType* funcTy = func->getFunctionType(); |
|---|
| 156 |
|
|---|
| 157 |
if (Logger::enabled()) |
|---|
| 158 |
Logger::cout() << "_aaDel = " << *func << '\n'; |
|---|
| 159 |
|
|---|
| 160 |
// aa param |
|---|
| 161 |
LLValue* aaval = aa->getRVal(); |
|---|
| 162 |
if (Logger::enabled()) |
|---|
| 163 |
{ |
|---|
| 164 |
Logger::cout() << "aaval: " << *aaval << '\n'; |
|---|
| 165 |
Logger::cout() << "totype: " << *funcTy->getParamType(0) << '\n'; |
|---|
| 166 |
} |
|---|
| 167 |
aaval = DtoBitCast(aaval, funcTy->getParamType(0)); |
|---|
| 168 |
|
|---|
| 169 |
// keyti param |
|---|
| 170 |
LLValue* keyti = to_keyti(key); |
|---|
| 171 |
keyti = DtoBitCast(keyti, funcTy->getParamType(1)); |
|---|
| 172 |
|
|---|
| 173 |
// pkey param |
|---|
| 174 |
LLValue* pkey = makeLValue(loc, key); |
|---|
| 175 |
pkey = DtoBitCast(pkey, funcTy->getParamType(2)); |
|---|
| 176 |
|
|---|
| 177 |
// build arg vector |
|---|
| 178 |
LLSmallVector<LLValue*, 3> args; |
|---|
| 179 |
args.push_back(aaval); |
|---|
| 180 |
args.push_back(keyti); |
|---|
| 181 |
args.push_back(pkey); |
|---|
| 182 |
|
|---|
| 183 |
// call runtime |
|---|
| 184 |
gIR->CreateCallOrInvoke(func, args.begin(), args.end()); |
|---|
| 185 |
} |
|---|
| 186 |
|
|---|
| 187 |
///////////////////////////////////////////////////////////////////////////////////// |
|---|
| 188 |
|
|---|
| 189 |
LLValue* DtoAAEquals(Loc& loc, TOK op, DValue* l, DValue* r) |
|---|
| 190 |
{ |
|---|
| 191 |
Type* t = l->getType()->toBasetype(); |
|---|
| 192 |
assert(t == r->getType()->toBasetype() && "aa equality is only defined for aas of same type"); |
|---|
| 193 |
|
|---|
| 194 |
llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_aaEq"); |
|---|
| 195 |
const llvm::FunctionType* funcTy = func->getFunctionType(); |
|---|
| 196 |
|
|---|
| 197 |
LLValue* aaval = DtoBitCast(l->getRVal(), funcTy->getParamType(0)); |
|---|
| 198 |
LLValue* abval = DtoBitCast(r->getRVal(), funcTy->getParamType(1)); |
|---|
| 199 |
LLValue* aaTypeInfo = DtoTypeInfoOf(t); |
|---|
| 200 |
LLValue* res = gIR->CreateCallOrInvoke3(func, aaval, abval, aaTypeInfo, "aaEqRes").getInstruction(); |
|---|
| 201 |
|
|---|
| 202 |
res = gIR->ir->CreateICmpNE(res, DtoConstInt(0), "tmp"); |
|---|
| 203 |
if (op == TOKnotequal) |
|---|
| 204 |
res = gIR->ir->CreateNot(res, "tmp"); |
|---|
| 205 |
return res; |
|---|
| 206 |
} |
|---|