Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 525 lines (466 sloc) 17.798 kB
3c7ff6c @JeffBezanson formatting changes
JeffBezanson authored
1 // utility procedures used in code generation
2
3 // --- string constants ---
4
5 static std::map<const std::string, GlobalVariable*> stringConstants;
6
7 static GlobalVariable *stringConst(const std::string &txt)
8 {
9 GlobalVariable *gv = stringConstants[txt];
10 static int strno = 0;
11 if (gv == NULL) {
12 std::stringstream ssno;
13 std::string vname;
14 ssno << strno;
15 vname += "_j_str";
16 vname += ssno.str();
17 gv = new GlobalVariable(*jl_Module,
18 ArrayType::get(T_int8, txt.length()+1),
19 true,
20 GlobalVariable::ExternalLinkage,
21 ConstantArray::get(getGlobalContext(),
22 txt.c_str()),
23 vname);
24 stringConstants[txt] = gv;
25 strno++;
26 }
27 return gv;
28 }
29
30 // --- emitting pointers directly into code ---
31
32 static Value *literal_pointer_val(void *p, const Type *t)
33 {
34 #ifdef __LP64__
35 return ConstantExpr::getIntToPtr(ConstantInt::get(T_int64, (uint64_t)p),
36 t);
37 #else
38 return ConstantExpr::getIntToPtr(ConstantInt::get(T_int32, (uint32_t)p),
39 t);
40 #endif
41 }
42
43 static Value *literal_pointer_val(jl_value_t *p)
44 {
45 return literal_pointer_val(p, jl_pvalue_llvmt);
46 }
47
48 static Value *literal_pointer_val(void *p)
49 {
50 return literal_pointer_val(p, T_pint8);
51 }
52
53 // --- generating various error checks ---
54
55 static jl_value_t *llvm_type_to_julia(const Type *t, bool err=true);
56
57 static Value *emit_typeof(Value *p)
58 {
59 // given p, a jl_value_t*, compute its type tag
60 if (p->getType() == jl_pvalue_llvmt) {
61 Value *tt = builder.CreateBitCast(p, jl_ppvalue_llvmt);
62 tt = builder.
63 CreateLoad(builder.CreateGEP(tt,ConstantInt::get(T_int32,0)),
64 false);
65 return tt;
66 }
67 return literal_pointer_val(llvm_type_to_julia(p->getType()));
68 }
69
70 static void emit_error(const std::string &txt, jl_codectx_t *ctx)
71 {
72 std::string txt2 = "in " + ctx->funcName + ": " + txt;
73 std::vector<Value *> zeros(0);
74 zeros.push_back(ConstantInt::get(T_int32, 0));
75 zeros.push_back(ConstantInt::get(T_int32, 0));
76 builder.CreateCall(jlerror_func,
77 builder.CreateGEP(stringConst(txt2),
78 zeros.begin(), zeros.end()));
79 }
80
81 static void error_unless(Value *cond, const std::string &msg, jl_codectx_t *ctx)
82 {
83 BasicBlock *failBB = BasicBlock::Create(getGlobalContext(),"fail",ctx->f);
84 BasicBlock *passBB = BasicBlock::Create(getGlobalContext(),"pass");
85 builder.CreateCondBr(cond, passBB, failBB);
86 builder.SetInsertPoint(failBB);
87 emit_error(msg, ctx);
88 builder.CreateBr(passBB);
89 ctx->f->getBasicBlockList().push_back(passBB);
90 builder.SetInsertPoint(passBB);
91 }
92
93 static void call_error_func_unless(Value *cond, Function *errfunc,
94 jl_codectx_t *ctx)
95 {
96 BasicBlock *failBB = BasicBlock::Create(getGlobalContext(),"fail",ctx->f);
97 BasicBlock *passBB = BasicBlock::Create(getGlobalContext(),"pass");
98 builder.CreateCondBr(cond, passBB, failBB);
99 builder.SetInsertPoint(failBB);
100 builder.CreateCall(errfunc);
101 builder.CreateBr(passBB);
102 ctx->f->getBasicBlockList().push_back(passBB);
103 builder.SetInsertPoint(passBB);
104 }
105
106 static void null_pointer_check(Value *v, jl_codectx_t *ctx)
107 {
108 call_error_func_unless(builder.CreateICmpNE(v, V_null),
109 jluniniterror_func, ctx);
110 }
111
112 static Value *boxed(Value *v);
113
114 static void emit_type_error(Value *x, jl_value_t *type, const std::string &msg,
115 jl_codectx_t *ctx)
116 {
117 std::vector<Value *> zeros(0);
118 zeros.push_back(ConstantInt::get(T_int32, 0));
119 zeros.push_back(ConstantInt::get(T_int32, 0));
120 Value *fname_val = builder.CreateGEP(stringConst(ctx->funcName),
121 zeros.begin(), zeros.end());
122 Value *msg_val = builder.CreateGEP(stringConst(msg),
123 zeros.begin(), zeros.end());
124 builder.CreateCall4(jltypeerror_func,
125 fname_val, msg_val,
126 literal_pointer_val(type), boxed(x));
127 }
128
129 static void emit_typecheck(Value *x, jl_value_t *type, const std::string &msg,
130 jl_codectx_t *ctx)
131 {
132 Value *istype =
133 builder.CreateICmpEQ(emit_typeof(x), literal_pointer_val(type));
134 BasicBlock *failBB = BasicBlock::Create(getGlobalContext(),"fail",ctx->f);
135 BasicBlock *passBB = BasicBlock::Create(getGlobalContext(),"pass");
136 builder.CreateCondBr(istype, passBB, failBB);
137 builder.SetInsertPoint(failBB);
138
139 emit_type_error(x, type, msg, ctx);
140
141 builder.CreateBr(passBB);
142 ctx->f->getBasicBlockList().push_back(passBB);
143 builder.SetInsertPoint(passBB);
144 }
145
146 static Value *emit_bounds_check(Value *i, Value *len, const std::string &msg,
147 jl_codectx_t *ctx)
148 {
149 Value *im1 = builder.CreateSub(i, ConstantInt::get(T_size, 1));
150 Value *ok = builder.CreateICmpULT(im1, len);
151 error_unless(ok, msg, ctx);
152 return im1;
153 }
154
155 static void emit_func_check(Value *x, jl_codectx_t *ctx)
156 {
157 Value *istype1 =
158 builder.CreateICmpEQ(emit_typeof(emit_typeof(x)),
159 literal_pointer_val((jl_value_t*)jl_func_kind));
160 BasicBlock *elseBB1 = BasicBlock::Create(getGlobalContext(),"a", ctx->f);
161 BasicBlock *mergeBB1 = BasicBlock::Create(getGlobalContext(),"b");
162 builder.CreateCondBr(istype1, mergeBB1, elseBB1);
163
164 builder.SetInsertPoint(elseBB1);
165 Value *istype2 =
166 builder.CreateICmpEQ(emit_typeof(x),
167 literal_pointer_val((jl_value_t*)jl_struct_kind));
168 BasicBlock *elseBB2 = BasicBlock::Create(getGlobalContext(),"a", ctx->f);
169 builder.CreateCondBr(istype2, mergeBB1, elseBB2);
170
171 builder.SetInsertPoint(elseBB2);
172 emit_type_error(x, (jl_value_t*)jl_function_type, "apply", ctx);
173
174 builder.CreateBr(mergeBB1);
175 ctx->f->getBasicBlockList().push_back(mergeBB1);
176 builder.SetInsertPoint(mergeBB1);
177 }
178
179 // --- loading and storing the Nth word in an object ---
180
181 static Value *emit_nthptr_addr(Value *v, size_t n)
182 {
183 return builder.CreateGEP(builder.CreateBitCast(v, jl_ppvalue_llvmt),
184 ConstantInt::get(T_int32, n));
185 }
186
187 static Value *emit_nthptr_addr(Value *v, Value *idx)
188 {
189 return builder.CreateGEP(builder.CreateBitCast(v, jl_ppvalue_llvmt), idx);
190 }
191
192 static Value *emit_nthptr(Value *v, size_t n)
193 {
194 // p = (jl_value_t**)v; p[n]
195 Value *vptr = emit_nthptr_addr(v, n);
196 return builder.CreateLoad(vptr, false);
197 }
198
199 static Value *emit_nthptr(Value *v, Value *idx)
200 {
201 // p = (jl_value_t**)v; p[n]
202 Value *vptr = emit_nthptr_addr(v, idx);
203 return builder.CreateLoad(vptr, false);
204 }
205
206 // --- convert boolean value to julia ---
207
208 static Value *julia_bool(Value *cond)
209 {
210 return builder.CreateSelect(cond,
211 literal_pointer_val(jl_true),
212 literal_pointer_val(jl_false));
213 }
214
215 // --- get the inferred type of an AST node ---
216
217 static jl_value_t *expr_type(jl_value_t *e)
218 {
219 if (jl_is_expr(e))
220 return ((jl_expr_t*)e)->etype;
221 if (jl_is_symbolnode(e))
222 return jl_symbolnode_type(e);
223 if (jl_is_topnode(e))
224 return jl_fieldref(e,1);
225 if (jl_is_quotenode(e))
226 return (jl_value_t*)jl_typeof(jl_fieldref(e,0));
227 if (jl_is_symbol(e))
228 return (jl_value_t*)jl_any_type;
229 if (jl_is_lambda_info(e))
230 return (jl_value_t*)jl_any_func;
231 if (jl_is_some_tag_type(e))
232 return (jl_value_t*)jl_wrap_Type(e);
233 return (jl_value_t*)jl_typeof(e);
234 }
235
236 // --- accessing the representations of built-in data types ---
237
238 static Value *emit_tuplelen(Value *t)
239 {
240 Value *lenbits = emit_nthptr(t, 1);
241 #ifdef __LP64__
242 return builder.CreatePtrToInt(lenbits, T_int64);
243 #else
244 return builder.CreatePtrToInt(lenbits, T_int32);
245 #endif
246 }
247
248 static Value *emit_arraysize(Value *t, Value *dim)
249 {
250 int o;
251 #ifdef __LP64__
252 o = 3;
253 #else
254 o = 4;
255 #endif
256 Value *dbits =
257 emit_nthptr(t, builder.CreateAdd(dim,
258 ConstantInt::get(dim->getType(), o)));
259 #ifdef __LP64__
260 return builder.CreatePtrToInt(dbits, T_int64);
261 #else
262 return builder.CreatePtrToInt(dbits, T_int32);
263 #endif
264 }
265
266 static Value *emit_arraysize(Value *t, int dim)
267 {
268 return emit_arraysize(t, ConstantInt::get(T_int32, dim));
269 }
270
271 static Value *emit_arraylen(Value *t)
272 {
273 Value *lenbits = emit_nthptr(t, 2);
274 #ifdef __LP64__
275 return builder.CreatePtrToInt(lenbits, T_int64);
276 #else
277 return builder.CreatePtrToInt(lenbits, T_int32);
278 #endif
279 }
280
281 static Value *emit_arrayptr(Value *t)
282 {
283 return emit_nthptr(t, 1);
284 }
285
286 static Value *bitstype_pointer(Value *x)
287 {
288 return builder.CreateGEP(builder.CreateBitCast(x, jl_ppvalue_llvmt),
289 ConstantInt::get(T_int32, 1));
290 }
291
292 // --- scheme for tagging llvm values with julia types using metadata ---
293
294 static std::map<int, jl_value_t*> typeIdToType;
295 static std::map<jl_value_t*, int> typeToTypeId;
296 static int cur_type_id = 1;
297
298 static int jl_type_to_typeid(jl_value_t *t)
299 {
300 std::map<jl_value_t*, int>::iterator it = typeToTypeId.find(t);
301 if (it == typeToTypeId.end()) {
302 int mine = cur_type_id++;
303 if (mine > 65025)
304 jl_error("unexpected error: too many bits types");
305 typeToTypeId[t] = mine;
306 typeIdToType[mine] = t;
307 return mine;
308 }
309 return (*it).second;
310 }
311
312 static jl_value_t *jl_typeid_to_type(int i)
313 {
314 std::map<int, jl_value_t*>::iterator it = typeIdToType.find(i);
315 if (it == typeIdToType.end()) {
316 jl_error("unexpected error: invalid type id");
317 }
318 return (*it).second;
319 }
320
321 static bool has_julia_type(Value *v)
322 {
323 return ((dyn_cast<Instruction>(v) != NULL) &&
324 ((Instruction*)v)->getMetadata("julia_type")!=NULL);
325 }
326
327 static jl_value_t *julia_type_of_without_metadata(Value *v, bool err=true)
328 {
329 if (dyn_cast<AllocaInst>(v) != NULL ||
330 dyn_cast<GetElementPtrInst>(v) != NULL) {
331 // an alloca always has llvm type pointer
332 return llvm_type_to_julia(v->getType()->getContainedType(0), err);
333 }
334 return llvm_type_to_julia(v->getType(), err);
335 }
336
337 static jl_value_t *julia_type_of(Value *v)
338 {
339 MDNode *mdn;
340 if (dyn_cast<Instruction>(v) == NULL ||
341 (mdn = ((Instruction*)v)->getMetadata("julia_type")) == NULL) {
342 return julia_type_of_without_metadata(v, true);
343 }
344 MDString *md = (MDString*)mdn->getOperand(0);
345 const char *vts = md->getString().data();
346 int id = (vts[0]-1) + (vts[1]-1)*255;
347 return jl_typeid_to_type(id);
348 }
349
350 // see if a julia type maps directly to an llvm type
351 static bool is_julia_type_representable(jl_value_t *jt)
352 {
353 return
354 (jt == (jl_value_t*)jl_bool_type || jt == (jl_value_t*)jl_int8_type ||
355 jt == (jl_value_t*)jl_int16_type || jt == (jl_value_t*)jl_int32_type ||
356 jt == (jl_value_t*)jl_int64_type ||
357 jt == (jl_value_t*)jl_float32_type ||
358 jt == (jl_value_t*)jl_float64_type ||
359 (jl_is_cpointer_type(jt) &&
360 is_julia_type_representable(jl_tparam0(jt))));
361 }
362
363 static Value *NoOpCast(Value *v)
364 {
365 v = CastInst::Create(Instruction::BitCast, v, v->getType());
366 builder.Insert((Instruction*)v);
367 return v;
368 }
369
370 static Value *mark_julia_type(Value *v, jl_value_t *jt)
371 {
372 if (jt == (jl_value_t*)jl_any_type)
373 return v;
374 if (has_julia_type(v) && julia_type_of(v) == jt)
375 return v;
376 if (julia_type_of_without_metadata(v,false) == jt)
377 return NoOpCast(v);
378 if (dyn_cast<Instruction>(v) == NULL)
379 v = NoOpCast(v);
380 assert(dyn_cast<Instruction>(v));
381 char name[3];
382 int id = jl_type_to_typeid(jt);
383 // store id as base-255 to avoid NUL
384 name[0] = (id%255)+1;
385 name[1] = (id/255)+1;
386 name[2] = '\0';
387 MDString *md = MDString::get(jl_LLVMContext, name);
388 Value *const vals[1] = {md};
389 MDNode *mdn = MDNode::get(jl_LLVMContext, vals, 1);
390 ((Instruction*)v)->setMetadata("julia_type", mdn);
391 return v;
392 }
393
394 static Value *mark_julia_type(Value *v, jl_bits_type_t *jt)
395 {
396 return mark_julia_type(v, (jl_value_t*)jt);
397 }
398
399 // --- propagate julia type from value a to b. returns b. ---
400
401 static Value *tpropagate(Value *a, Value *b)
402 {
403 if (has_julia_type(a))
404 return mark_julia_type(b, julia_type_of(a));
405 return b;
406 }
407
408 // --- mapping between julia and llvm types ---
409
410 static const Type *julia_type_to_llvm(jl_value_t *jt, jl_codectx_t *ctx)
411 {
412 if (jt == (jl_value_t*)jl_bool_type) return T_int1;
413 if (jt == (jl_value_t*)jl_float32_type) return T_float32;
414 if (jt == (jl_value_t*)jl_float64_type) return T_float64;
415 //if (jt == (jl_value_t*)jl_null) return T_void;
416 if (jl_is_bits_type(jt) && jl_is_cpointer_type(jt)) {
417 const Type *lt = julia_type_to_llvm(jl_tparam0(jt), ctx);
418 if (lt == NULL)
419 return NULL;
420 if (lt == T_void)
421 lt = T_int8;
422 return PointerType::get(lt, 0);
423 }
424 if (jl_is_bits_type(jt)) {
425 int nb = jl_bitstype_nbits(jt);
426 if (nb == 8) return T_int8;
427 if (nb == 16) return T_int16;
428 if (nb == 32) return T_int32;
429 if (nb == 64) return T_int64;
430 else return Type::getIntNTy(getGlobalContext(), nb);
431 }
432 if (jt == (jl_value_t*)jl_any_type)
433 return jl_pvalue_llvmt;
434 if (jt == (jl_value_t*)jl_bottom_type) return T_void;
435 emit_type_error(literal_pointer_val(jt), (jl_value_t*)jl_bits_kind,
436 "conversion to native type", ctx);
437 return NULL;
438 }
439
440 // NOTE: llvm cannot express all julia types (for example unsigned),
441 // so this is an approximation. it's only correct if the associated LLVM
442 // value is not tagged with our value name hack.
443 // boxed(v) below gets the correct type.
444 static jl_value_t *llvm_type_to_julia(const Type *t, bool throw_error)
445 {
446 if (t == T_int1) return (jl_value_t*)jl_bool_type;
447 if (t == T_int8) return (jl_value_t*)jl_int8_type;
448 if (t == T_int16) return (jl_value_t*)jl_int16_type;
449 if (t == T_int32) return (jl_value_t*)jl_int32_type;
450 if (t == T_int64) return (jl_value_t*)jl_int64_type;
451 if (t == T_float32) return (jl_value_t*)jl_float32_type;
452 if (t == T_float64) return (jl_value_t*)jl_float64_type;
453 if (t == T_void) return (jl_value_t*)jl_bottom_type;
454 if (t == jl_pvalue_llvmt)
455 return (jl_value_t*)jl_any_type;
456 if (t->isPointerTy()) {
457 jl_value_t *elty = llvm_type_to_julia(t->getContainedType(0),
458 throw_error);
459 if (elty != NULL) {
460 return (jl_value_t*)jl_apply_type((jl_value_t*)jl_pointer_type,
461 jl_tuple1(elty));
462 }
463 }
464 if (throw_error) {
465 jl_errorf("cannot convert type %s to a julia type",
466 t->getDescription().c_str());
467 }
468 return NULL;
469 }
470
471 // --- boxing ---
472
473 // this is used to wrap values for generic contexts, where a
474 // dynamically-typed value is required (e.g. argument to unknown function).
475 // if it's already a pointer it's left alone.
476 static Value *boxed(Value *v)
477 {
478 const Type *t = v->getType();
479 if (t == jl_pvalue_llvmt)
480 return v;
481 if (t == T_void)
482 return literal_pointer_val((jl_value_t*)jl_nothing);
483 if (t == T_int1) return julia_bool(v);
484 jl_value_t *jt = julia_type_of(v);
485 jl_bits_type_t *jb = (jl_bits_type_t*)jt;
486 if (jb == jl_int8_type) return builder.CreateCall(box_int8_func, v);
487 if (jb == jl_int16_type) return builder.CreateCall(box_int16_func, v);
488 if (jb == jl_int32_type) return builder.CreateCall(box_int32_func, v);
489 if (jb == jl_int64_type) return builder.CreateCall(box_int64_func, v);
490 if (jb == jl_float32_type) return builder.CreateCall(box_float32_func, v);
491 if (jb == jl_float64_type) return builder.CreateCall(box_float64_func, v);
492 if (jb == jl_uint8_type) return builder.CreateCall(box_uint8_func, v);
493 if (jb == jl_uint16_type) return builder.CreateCall(box_uint16_func, v);
494 if (jb == jl_uint32_type) return builder.CreateCall(box_uint32_func, v);
495 if (jb == jl_uint64_type) return builder.CreateCall(box_uint64_func, v);
6f7ec8c @JeffBezanson adding cache of boxed Chars
JeffBezanson authored
496 if (jb == jl_char_type) return builder.CreateCall(box_char_func, v);
3c7ff6c @JeffBezanson formatting changes
JeffBezanson authored
497 // TODO: skip the call for constant arguments
498 if (jl_is_bits_type(jt)) {
499 if (v->getType()->isPointerTy()) {
500 v = builder.CreatePtrToInt(v, T_size);
501 }
502 int nb = jl_bitstype_nbits(jt);
503 if (nb == 8)
504 return builder.CreateCall2(box8_func, literal_pointer_val(jt), v);
505 if (nb == 16)
506 return builder.CreateCall2(box16_func, literal_pointer_val(jt), v);
507 if (nb == 32)
508 return builder.CreateCall2(box32_func, literal_pointer_val(jt), v);
509 if (nb == 64)
510 return builder.CreateCall2(box64_func, literal_pointer_val(jt), v);
511 size_t sz = sizeof(void*) + (nb+7)/8;
512 Value *newv = builder.CreateCall(jlallocobj_func,
513 ConstantInt::get(T_size, sz));
514 builder.CreateStore(literal_pointer_val(jt),
515 builder.CreateBitCast(newv, jl_ppvalue_llvmt));
516 builder.CreateStore(v,
517 builder.CreateBitCast(bitstype_pointer(newv),
518 PointerType::get(t,0)));
519 // TODO: make sure this is rooted. I think it is.
520 return builder.CreateBitCast(newv, jl_pvalue_llvmt);
521 }
522 assert("Don't know how to box this type" && false);
523 return NULL;
524 }
Something went wrong with that request. Please try again.