Wiki Roadmap Timeline Tickets New Ticket Source Search Help / Guide About Trac Login

root/gen/aa.cpp

Revision 1643:8f121883bce8, 6.6 kB (checked in by Kelly Wilson <wilsonk cpsc.ucalgary.ca>, 2 years ago)

Apply patch from klickverbot. This is his 'proper fix' patch for bug #395.

Line 
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 }
Note: See TracBrowser for help on using the browser.
Copyright © 2008, LDC Development Team.