1 module d.llvm.expression;
2 
3 import d.llvm.local;
4 
5 import d.ir.expression;
6 import d.ir.symbol;
7 import d.ir.type;
8 
9 import source.location;
10 
11 import util.visitor;
12 
13 import llvm.c.core;
14 
15 struct ExpressionGen {
16 	private LocalPass pass;
17 	alias pass this;
18 	
19 	this(LocalPass pass) {
20 		this.pass = pass;
21 	}
22 	
23 	LLVMValueRef visit(Expression e) {
24 		if (auto ce = cast(CompileTimeExpression) e) {
25 			// XXX: for some resaon, pass.pass is need as
26 			// alias this doesn't kick in.
27 			import d.llvm.constant;
28 			return ConstantGen(pass.pass).visit(ce);
29 		}
30 		
31 		return this.dispatch!(function LLVMValueRef(Expression e) {
32 			import source.exception;
33 			throw new CompileException(
34 				e.location,
35 				typeid(e).toString() ~ " is not supported",
36 			);
37 		})(e);
38 	}
39 	
40 	private LLVMValueRef addressOf(E)(E e) if (is(E : Expression)) in {
41 		assert(e.isLvalue, "e must be an lvalue");
42 	} do {
43 		return AddressOfGen(pass).visit(e);
44 	}
45 	
46 	private LLVMValueRef buildLoad(LLVMValueRef ptr, TypeQualifier q) {
47 		auto l = LLVMBuildLoad(builder, ptr, "");
48 		final switch(q) with(TypeQualifier) {
49 			case Mutable, Inout, Const:
50 				break;
51 			
52 			case Shared, ConstShared:
53 				import llvm.c.target;
54 				LLVMSetAlignment(l, LLVMABIAlignmentOfType(targetData, LLVMTypeOf(l)));
55 				LLVMSetOrdering(l, LLVMAtomicOrdering.SequentiallyConsistent);
56 				break;
57 			
58 			case Immutable:
59 				// TODO: !invariant.load
60 				break;
61 		}
62 		
63 		return l;
64 	}
65 	
66 	private LLVMValueRef loadAddressOf(E)(E e) if (is(E : Expression)) in {
67 		assert(e.isLvalue, "e must be an lvalue");
68 	} do {
69 		auto q = e.type.qualifier;
70 		return buildLoad(addressOf(e), q);
71 	}
72 	
73 	private LLVMValueRef buildStore(LLVMValueRef ptr, LLVMValueRef val, TypeQualifier q) {
74 		auto s = LLVMBuildStore(builder, val, ptr);
75 		final switch(q) with(TypeQualifier) {
76 			case Mutable, Inout, Const:
77 				break;
78 			
79 			case Shared, ConstShared:
80 				import llvm.c.target;
81 				LLVMSetAlignment(s, LLVMABIAlignmentOfType(targetData, LLVMTypeOf(val)));
82 				LLVMSetOrdering(s, LLVMAtomicOrdering.SequentiallyConsistent);
83 				break;
84 			
85 			case Immutable:
86 				// TODO: !invariant.load
87 				break;
88 		}
89 		
90 		return s;
91 	}
92 	
93 	private auto handleBinaryOp(alias LLVMBuildOp)(BinaryExpression e) {
94 		// XXX: should be useless, but parameters's order of evaluation is bugguy.
95 		auto lhs = visit(e.lhs);
96 		auto rhs = visit(e.rhs);
97 		
98 		return LLVMBuildOp(builder, lhs, rhs, "");
99 	}
100 	
101 	private auto handleLogicalBinary(bool shortCircuitOnTrue)(BinaryExpression e) {
102 		auto lhs = visit(e.lhs);
103 		
104 		auto lhsBB = LLVMGetInsertBlock(builder);
105 		auto fun = LLVMGetBasicBlockParent(lhsBB);
106 		
107 		static if (shortCircuitOnTrue) {
108 			auto rhsBB = LLVMAppendBasicBlockInContext(llvmCtx, fun, "or_rhs");
109 			auto mergeBB = LLVMAppendBasicBlockInContext(llvmCtx, fun, "or_merge");
110 			LLVMBuildCondBr(builder, lhs, mergeBB, rhsBB);
111 		} else {
112 			auto rhsBB = LLVMAppendBasicBlockInContext(llvmCtx, fun, "and_rhs");
113 			auto mergeBB = LLVMAppendBasicBlockInContext(llvmCtx, fun, "and_merge");
114 			LLVMBuildCondBr(builder, lhs, rhsBB, mergeBB);
115 		}
116 		
117 		// Emit rhs
118 		LLVMPositionBuilderAtEnd(builder, rhsBB);
119 		
120 		auto rhs = visit(e.rhs);
121 		
122 		// Conclude that block.
123 		LLVMBuildBr(builder, mergeBB);
124 		
125 		// Codegen of lhs can change the current block, so we put everything in order.
126 		rhsBB = LLVMGetInsertBlock(builder);
127 		LLVMMoveBasicBlockAfter(mergeBB, rhsBB);
128 		LLVMPositionBuilderAtEnd(builder, mergeBB);
129 		
130 		// Generate phi to get the result.
131 		import d.llvm.type;
132 		auto phiNode = LLVMBuildPhi(
133 			builder,
134 			TypeGen(pass.pass).visit(e.type),
135 			"",
136 		);
137 		
138 		LLVMValueRef[2] incomingValues;
139 		incomingValues[0] = lhs;
140 		incomingValues[1] = rhs;
141 		
142 		LLVMBasicBlockRef[2] incomingBlocks;
143 		incomingBlocks[0] = lhsBB;
144 		incomingBlocks[1] = rhsBB;
145 		
146 		LLVMAddIncoming(
147 			phiNode,
148 			incomingValues.ptr,
149 			incomingBlocks.ptr,
150 			incomingValues.length,
151 		);
152 		
153 		return phiNode;
154 	}
155 	
156 	LLVMValueRef visit(BinaryExpression e) {
157 		final switch(e.op) with(BinaryOp) {
158 			case Comma :
159 				visit(e.lhs);
160 				return visit(e.rhs);
161 			
162 			case Assign :
163 				auto lhs = addressOf(e.lhs);
164 				auto rhs = visit(e.rhs);
165 				
166 				buildStore(lhs, rhs, e.lhs.type.qualifier);
167 				return rhs;
168 			
169 			case Add :
170 				return handleBinaryOp!LLVMBuildAdd(e);
171 			
172 			case Sub :
173 				return handleBinaryOp!LLVMBuildSub(e);
174 			
175 			case Mul :
176 				return handleBinaryOp!LLVMBuildMul(e);
177 			
178 			case UDiv :
179 				return handleBinaryOp!LLVMBuildUDiv(e);
180 			
181 			case SDiv :
182 				return handleBinaryOp!LLVMBuildSDiv(e);
183 			
184 			case URem :
185 				return handleBinaryOp!LLVMBuildURem(e);
186 			
187 			case SRem :
188 				return handleBinaryOp!LLVMBuildSRem(e);
189 			
190 			case Pow :
191 				assert(0, "Not implemented");
192 			
193 			case Or :
194 				return handleBinaryOp!LLVMBuildOr(e);
195 			
196 			case And :
197 				return handleBinaryOp!LLVMBuildAnd(e);
198 			
199 			case Xor :
200 				return handleBinaryOp!LLVMBuildXor(e);
201 			
202 			case LeftShift :
203 				return handleBinaryOp!LLVMBuildShl(e);
204 			
205 			case UnsignedRightShift :
206 				return handleBinaryOp!LLVMBuildLShr(e);
207 			
208 			case SignedRightShift :
209 				return handleBinaryOp!LLVMBuildAShr(e);
210 			
211 			case LogicalOr :
212 				return handleLogicalBinary!true(e);
213 			
214 			case LogicalAnd :
215 				return handleLogicalBinary!false(e);
216 		}
217 	}
218 	
219 	private LLVMValueRef handleComparison(
220 		ICmpExpression e,
221 		LLVMIntPredicate pred,
222 	) {
223 		// XXX: should be useless, but parameters's order of evaluation
224 		// not enforced by DMD.
225 		auto lhs = visit(e.lhs);
226 		auto rhs = visit(e.rhs);
227 		
228 		return LLVMBuildICmp(builder, pred, lhs, rhs, "");
229 	}
230 	
231 	private LLVMValueRef handleComparison(
232 		ICmpExpression e,
233 		LLVMIntPredicate signedPredicate,
234 		LLVMIntPredicate unsignedPredicate,
235 	) {
236 		auto t = e.lhs.type.getCanonical();
237 		if (t.kind == TypeKind.Builtin) {
238 			return handleComparison(
239 				e,
240 				t.builtin.isSigned()
241 					? signedPredicate
242 					: unsignedPredicate,
243 			);
244 		}
245 		
246 		if (t.kind == TypeKind.Pointer) {
247 			return handleComparison(e, unsignedPredicate);
248 		}
249 		
250 		auto t1 = e.lhs.type.toString(context);
251 		auto t2 = e.rhs.type.toString(context);
252 		assert(0, "Can't compare " ~ t1 ~ " with " ~ t2);
253 	}
254 	
255 	LLVMValueRef visit(ICmpExpression e) {
256 		final switch(e.op) with(ICmpOp) {
257 			case Equal :
258 				return handleComparison(e, LLVMIntPredicate.EQ);
259 			
260 			case NotEqual :
261 				return handleComparison(e, LLVMIntPredicate.NE);
262 			
263 			case Greater :
264 				return handleComparison(e, LLVMIntPredicate.SGT, LLVMIntPredicate.UGT);
265 			
266 			case GreaterEqual :
267 				return handleComparison(e, LLVMIntPredicate.SGE, LLVMIntPredicate.UGE);
268 			
269 			case Less :
270 				return handleComparison(e, LLVMIntPredicate.SLT, LLVMIntPredicate.ULT);
271 			
272 			case LessEqual :
273 				return handleComparison(e, LLVMIntPredicate.SLE, LLVMIntPredicate.ULE);
274 		}
275 	}
276 	
277 	LLVMValueRef visit(UnaryExpression e) {
278 		final switch(e.op) with(UnaryOp) {
279 			case AddressOf :
280 				return addressOf(e.expr);
281 			
282 			case Dereference :
283 				return buildLoad(visit(e.expr), e.type.qualifier);
284 			
285 			case PreInc :
286 				auto q = e.expr.type.qualifier;
287 				auto ptr = addressOf(e.expr);
288 				auto value = buildLoad(ptr, q);
289 				auto type = LLVMTypeOf(value);
290 				
291 				if (LLVMGetTypeKind(type) == LLVMTypeKind.Pointer) {
292 					auto one = LLVMConstInt(LLVMInt32TypeInContext(llvmCtx), 1, true);
293 					value = LLVMBuildInBoundsGEP(builder, value, &one, 1, "");
294 				} else {
295 					value = LLVMBuildAdd(builder, value, LLVMConstInt(type, 1, true), "");
296 				}
297 				
298 				LLVMBuildStore(builder, value, ptr);
299 				return value;
300 			
301 			case PreDec :
302 				auto q = e.expr.type.qualifier;
303 				auto ptr = addressOf(e.expr);
304 				auto value = buildLoad(ptr, q);
305 				auto type = LLVMTypeOf(value);
306 				
307 				if (LLVMGetTypeKind(type) == LLVMTypeKind.Pointer) {
308 					auto one = LLVMConstInt(LLVMInt32TypeInContext(llvmCtx), -1, true);
309 					value = LLVMBuildInBoundsGEP(builder, value, &one, 1, "");
310 				} else {
311 					value = LLVMBuildSub(builder, value, LLVMConstInt(type, 1, true), "");
312 				}
313 				
314 				LLVMBuildStore(builder, value, ptr);
315 				return value;
316 			
317 			case PostInc :
318 				auto q = e.expr.type.qualifier;
319 				auto ptr = addressOf(e.expr);
320 				auto value = buildLoad(ptr, q);
321 				auto ret = value;
322 				auto type = LLVMTypeOf(value);
323 				
324 				if (LLVMGetTypeKind(type) == LLVMTypeKind.Pointer) {
325 					auto one = LLVMConstInt(LLVMInt32TypeInContext(llvmCtx), 1, true);
326 					value = LLVMBuildInBoundsGEP(builder, value, &one, 1, "");
327 				} else {
328 					value = LLVMBuildAdd(builder, value, LLVMConstInt(type, 1, true), "");
329 				}
330 				
331 				LLVMBuildStore(builder, value, ptr);
332 				return ret;
333 			
334 			case PostDec :
335 				auto q = e.expr.type.qualifier;
336 				auto ptr = addressOf(e.expr);
337 				auto value = buildLoad(ptr, q);
338 				auto ret = value;
339 				auto type = LLVMTypeOf(value);
340 				
341 				if (LLVMGetTypeKind(type) == LLVMTypeKind.Pointer) {
342 					auto one = LLVMConstInt(LLVMInt32TypeInContext(llvmCtx), -1, true);
343 					value = LLVMBuildInBoundsGEP(builder, value, &one, 1, "");
344 				} else {
345 					value = LLVMBuildSub(builder, value, LLVMConstInt(type, 1, true), "");
346 				}
347 				
348 				LLVMBuildStore(builder, value, ptr);
349 				return ret;
350 			
351 			case Plus :
352 				return visit(e.expr);
353 			
354 			case Minus :
355 				import d.llvm.type;
356 				return LLVMBuildSub(
357 					builder,
358 					LLVMConstInt(TypeGen(pass.pass).visit(e.type), 0, true),
359 					visit(e.expr),
360 					"",
361 				);
362 			
363 			case Not :
364 				import d.llvm.type;
365 				return LLVMBuildICmp(
366 					builder,
367 					LLVMIntPredicate.EQ,
368 					LLVMConstInt(TypeGen(pass.pass).visit(e.type), 0, true),
369 					visit(e.expr),
370 					"",
371 				);
372 			
373 			case Complement :
374 				import d.llvm.type;
375 				return LLVMBuildXor(
376 					builder,
377 					visit(e.expr),
378 					LLVMConstInt(TypeGen(pass.pass).visit(e.type), -1, true),
379 					"",
380 				);
381 		}
382 	}
383 	
384 	LLVMValueRef visit(TernaryExpression e) {
385 		auto cond = visit(e.condition);
386 		
387 		auto condBB  = LLVMGetInsertBlock(builder);
388 		auto fun = LLVMGetBasicBlockParent(condBB);
389 		
390 		auto lhsBB = LLVMAppendBasicBlockInContext(llvmCtx, fun, "ternary_lhs");
391 		auto rhsBB = LLVMAppendBasicBlockInContext(llvmCtx, fun, "ternary_rhs");
392 		auto mergeBB = LLVMAppendBasicBlockInContext(llvmCtx, fun, "ternary_merge");
393 		
394 		LLVMBuildCondBr(builder, cond, lhsBB, rhsBB);
395 		
396 		// Emit lhs
397 		LLVMPositionBuilderAtEnd(builder, lhsBB);
398 		auto lhs = visit(e.lhs);
399 		// Conclude that block.
400 		LLVMBuildBr(builder, mergeBB);
401 		
402 		// Codegen of lhs can change the current block, so we put everything in order.
403 		lhsBB = LLVMGetInsertBlock(builder);
404 		LLVMMoveBasicBlockAfter(rhsBB, lhsBB);
405 		
406 		// Emit rhs
407 		LLVMPositionBuilderAtEnd(builder, rhsBB);
408 		auto rhs = visit(e.rhs);
409 		// Conclude that block.
410 		LLVMBuildBr(builder, mergeBB);
411 		
412 		// Codegen of rhs can change the current block, so we put everything in order.
413 		rhsBB = LLVMGetInsertBlock(builder);
414 		LLVMMoveBasicBlockAfter(mergeBB, rhsBB);
415 		
416 		// Generate phi to get the result.
417 		LLVMPositionBuilderAtEnd(builder, mergeBB);
418 		
419 		import d.llvm.type;
420 		auto phiNode = LLVMBuildPhi(
421 			builder,
422 			TypeGen(pass.pass).visit(e.type),
423 			"",
424 		);
425 		
426 		LLVMValueRef[2] incomingValues;
427 		incomingValues[0] = lhs;
428 		incomingValues[1] = rhs;
429 		
430 		LLVMBasicBlockRef[2] incomingBlocks;
431 		incomingBlocks[0] = lhsBB;
432 		incomingBlocks[1] = rhsBB;
433 		
434 		LLVMAddIncoming(
435 			phiNode,
436 			incomingValues.ptr,
437 			incomingBlocks.ptr,
438 			incomingValues.length,
439 		);
440 		
441 		return phiNode;
442 	}
443 	
444 	LLVMValueRef visit(VariableExpression e) {
445 		return (e.var.storage == Storage.Enum || e.var.isFinal)
446 			? declare(e.var)
447 			: loadAddressOf(e);
448 	}
449 	
450 	LLVMValueRef visit(FieldExpression e) {
451 		if (e.isLvalue) {
452 			return loadAddressOf(e);
453 		}
454 		
455 		assert(e.expr.type.kind != TypeKind.Union, "rvalue unions not implemented.");
456 		return LLVMBuildExtractValue(builder, visit(e.expr), e.field.index, "");
457 	}
458 	
459 	LLVMValueRef visit(FunctionExpression e) {
460 		return declare(e.fun);
461 	}
462 	
463 	LLVMValueRef visit(DelegateExpression e) {
464 		auto type = e.type.getCanonical().asFunctionType();
465 		auto tCtxs = type.contexts;
466 		auto eCtxs = e.contexts;
467 		
468 		auto length = cast(uint) tCtxs.length;
469 		assert(eCtxs.length == length);
470 		
471 		import d.llvm.type;
472 		auto dg = LLVMGetUndef(TypeGen(pass.pass).visit(type));
473 		
474 		foreach (i, c; eCtxs) {
475 			auto ctxValue = tCtxs[i].isRef
476 				? addressOf(c)
477 				: visit(c);
478 			
479 			dg = LLVMBuildInsertValue(builder, dg, ctxValue, cast(uint) i, "");
480 		}
481 		
482 		LLVMValueRef fun;
483 		if (auto m = cast(Method) e.method) {
484 			assert(m.hasThis);
485 			assert(
486 				eCtxs[m.hasContext].type.getCanonical().dclass,
487 				"Virtual dispatch can only be done on classes"
488 			);
489 			
490 			auto thisPtr = LLVMBuildExtractValue(builder, dg, m.hasContext, "");
491 			auto vtblPtr = LLVMBuildStructGEP(builder, thisPtr, 0, "");
492 			auto vtbl = LLVMBuildLoad(builder, vtblPtr, "vtbl");
493 			auto funPtr = LLVMBuildStructGEP(builder, vtbl, m.index, "");
494 			fun = LLVMBuildLoad(builder, funPtr, "");
495 		} else {
496 			fun = declare(e.method);
497 		}
498 		
499 		dg = LLVMBuildInsertValue(builder, dg, fun, length, "");
500 		return dg;
501 	}
502 	
503 	LLVMValueRef visit(NewExpression e) {
504 		auto ctor = declare(e.ctor);
505 		
506 		import std.algorithm, std.array;
507 		auto args = e.args.map!(a => visit(a)).array();
508 		
509 		import d.llvm.type;
510 		auto type = TypeGen(pass.pass).visit(e.type);
511 		LLVMValueRef size = LLVMSizeOf(
512 			(e.type.kind == TypeKind.Class)
513 				? LLVMGetElementType(type)
514 				: type,
515 		);
516 		
517 		auto allocFun = declare(pass.object.getGCThreadLocalAllow());
518 		auto alloc = buildCall(allocFun, [size]);
519 		auto ptr = LLVMBuildPointerCast(builder, alloc, type, "");
520 		
521 		// XXX: This should be set on the alloc function instead of the callsite.
522 		LLVMAddCallSiteAttribute(
523 			alloc,
524 			LLVMAttributeReturnIndex,
525 			getAttribute("noalias"),
526 		);
527 		
528 		auto thisArg = visit(e.dinit);
529 		auto thisType = LLVMTypeOf(LLVMGetFirstParam(ctor));
530 		bool isClass = LLVMGetTypeKind(thisType) == LLVMTypeKind.Pointer;
531 		if (isClass) {
532 			auto ptrType = LLVMPointerType(LLVMTypeOf(thisArg), 0);
533 			auto thisPtr = LLVMBuildBitCast(builder, ptr, ptrType, "");
534 			LLVMBuildStore(builder, thisArg, thisPtr);
535 			thisArg = LLVMBuildBitCast(builder, ptr, thisType, "");
536 		}
537 		
538 		args = thisArg ~ args;
539 		auto obj = buildCall(ctor, args);
540 		if (!isClass) {
541 			LLVMBuildStore(builder, obj, ptr);
542 		}
543 		
544 		return ptr;
545 	}
546 	
547 	LLVMValueRef visit(IndexExpression e) in {
548 		assert(e.isLvalue, "e must be an lvalue");
549 	} do {
550 		return loadAddressOf(e);
551 	}
552 	
553 	auto genBoundCheck(Location location, LLVMValueRef condition) {
554 		auto fun = LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder));
555 		
556 		auto failBB = LLVMAppendBasicBlockInContext(llvmCtx, fun, "bound_fail");
557 		auto okBB = LLVMAppendBasicBlockInContext(llvmCtx, fun, "bound_ok");
558 		
559 		auto br = LLVMBuildCondBr(builder, condition, okBB, failBB);
560 		
561 		// We assume that bound check fail is unlikely.
562 		LLVMSetMetadata(br, profKindID, unlikelyBranch);
563 		
564 		// Emit bound check fail code.
565 		LLVMPositionBuilderAtEnd(builder, failBB);
566 		
567 		auto floc = location.getFullLocation(context);
568 		
569 		LLVMValueRef[2] args;
570 		args[0] = buildDString(floc.getSource().getFileName().toString());
571 		args[1] = LLVMConstInt(
572 			LLVMInt32TypeInContext(llvmCtx),
573 			floc.getStartLineNumber(),
574 			false,
575 		);
576 		
577 		buildCall(declare(pass.object.getArrayOutOfBounds()), args);
578 		
579 		LLVMBuildUnreachable(builder);
580 		
581 		// And continue regular program flow.
582 		LLVMPositionBuilderAtEnd(builder, okBB);
583 	}
584 	
585 	LLVMValueRef visit(SliceExpression e) {
586 		auto t = e.sliced.type.getCanonical();
587 		
588 		LLVMValueRef length, ptr;
589 		if (t.kind == TypeKind.Slice) {
590 			auto slice = visit(e.sliced);
591 			
592 			length = LLVMBuildExtractValue(builder, slice, 0, ".length");
593 			ptr = LLVMBuildExtractValue(builder, slice, 1, ".ptr");
594 		} else if (t.kind == TypeKind.Pointer) {
595 			ptr = visit(e.sliced);
596 		} else if (t.kind == TypeKind.Array) {
597 			length = LLVMConstInt(LLVMInt64TypeInContext(llvmCtx), t.size, false);
598 			
599 			import d.llvm.type;
600 			auto ptrType = LLVMPointerType(TypeGen(pass.pass).visit(t.element), 0);
601 			ptr = LLVMBuildBitCast(builder, addressOf(e.sliced), ptrType, "");
602 		} else {
603 			assert(0, "Don't know how to slice " ~ e.type.toString(context));
604 		}
605 		
606 		auto i64 = LLVMInt64TypeInContext(llvmCtx);
607 		auto first = LLVMBuildZExt(builder, visit(e.first), i64, "");
608 		auto second = LLVMBuildZExt(builder, visit(e.second), i64, "");
609 		
610 		auto condition = LLVMBuildICmp(builder, LLVMIntPredicate.ULE, first, second, "");
611 		if (length) {
612 			auto boundCheck = LLVMBuildICmp(builder, LLVMIntPredicate.ULE, second, length, "");
613 			condition = LLVMBuildAnd(builder, condition, boundCheck, "");
614 		}
615 		
616 		genBoundCheck(e.location, condition);
617 		
618 		import d.llvm.type;
619 		auto slice = LLVMGetUndef(TypeGen(pass.pass).visit(e.type));
620 		
621 		auto sub = LLVMBuildSub(builder, second, first, "");
622 		slice = LLVMBuildInsertValue(builder, slice, sub, 0, "");
623 		
624 		ptr = LLVMBuildInBoundsGEP(builder, ptr, &first, 1, "");
625 		slice = LLVMBuildInsertValue(builder, slice, ptr, 1, "");
626 		
627 		return slice;
628 	}
629 	
630 	// FIXME: This is public because of intrinsic codegen.
631 	// Once we support sequence return, we can make that private.
632 	LLVMValueRef buildBitCast(LLVMValueRef v, LLVMTypeRef t) {
633 		auto k = LLVMGetTypeKind(t);
634 		if (k != LLVMTypeKind.Struct) {
635 			assert(k != LLVMTypeKind.Array);
636 			return LLVMBuildBitCast(builder, v, t, "");
637 		}
638 		
639 		auto vt = LLVMTypeOf(v);
640 		assert(LLVMGetTypeKind(vt) == LLVMTypeKind.Struct);
641 		
642 		auto count = LLVMCountStructElementTypes(t);
643 		assert(LLVMCountStructElementTypes(vt) == count);
644 		
645 		LLVMTypeRef[] types;
646 		types.length = count;
647 		
648 		LLVMGetStructElementTypes(t, types.ptr);
649 		
650 		auto ret = LLVMGetUndef(t);
651 		foreach (i; 0 .. count) {
652 			ret = LLVMBuildInsertValue(builder, ret, buildBitCast(
653 				LLVMBuildExtractValue(builder, v, i, ""),
654 				types[i],
655 			), i, "");
656 		}
657 		
658 		return ret;
659 	}
660 	
661 	LLVMValueRef visit(CastExpression e) {
662 		import d.llvm.type;
663 		auto type = TypeGen(pass.pass).visit(e.type);
664 		auto value = visit(e.expr);
665 		
666 		final switch(e.kind) with(CastKind) {
667 			case Exact, Qual :
668 				return value;
669 			
670 			case Bit :
671 				return buildBitCast(value, type);
672 			
673 			case UPad :
674 				return LLVMBuildZExt(builder, value, type, "");
675 			
676 			case SPad :
677 				return LLVMBuildSExt(builder, value, type, "");
678 			
679 			case Trunc :
680 				return LLVMBuildTrunc(builder, value, type, "");
681 			
682 			case IntToPtr :
683 				return LLVMBuildIntToPtr(builder, value, type, "");
684 			
685 			case PtrToInt :
686 				return LLVMBuildPtrToInt(builder, value, type, "");
687 			
688 			case IntToBool :
689 				return LLVMBuildICmp(
690 					builder,
691 					LLVMIntPredicate.NE,
692 					value,
693 					LLVMConstInt(LLVMTypeOf(value), 0, false),
694 					"",
695 				);
696 			
697 			case Down :
698 				import d.llvm.type;
699 				auto obj = TypeGen(pass.pass).visit(pass.object.getObject());
700 				
701 				LLVMValueRef[2] args;
702 				args[0] = LLVMBuildBitCast(builder, value, obj, "");
703 				args[1] = getTypeid(e.type);
704 				
705 				auto result = buildCall(declare(pass.object.getClassDowncast()), args[]);
706 				return LLVMBuildBitCast(builder, result, type, "");
707 			
708 			case Invalid :
709 				assert(0, "Invalid cast");
710 		}
711 	}
712 	
713 	LLVMValueRef visit(ArrayLiteral e) {
714 		auto t = e.type;
715 		auto count = cast(uint) e.values.length;
716 		
717 		import d.llvm.type;
718 		auto et = TypeGen(pass.pass).visit(t.element);
719 		auto type = LLVMArrayType(et, count);
720 		auto array = LLVMGetUndef(type);
721 		
722 		uint i = 0;
723 		import std.algorithm;
724 		foreach(v; e.values.map!(v => visit(v))) {
725 			array = LLVMBuildInsertValue(builder, array, v, i++, "");
726 		}
727 		
728 		if (t.kind == TypeKind.Array) {
729 			return array;
730 		}
731 		
732 		auto ptrType = LLVMPointerType(type, 0);
733 		auto ptr = LLVMConstNull(ptrType);
734 		
735 		if (count > 0) {
736 			// We have a slice, we need to allocate.
737 			auto allocFun = declare(pass.object.getGCThreadLocalAllow());
738 			auto alloc = buildCall(allocFun, [LLVMSizeOf(type)]);
739 			ptr = LLVMBuildPointerCast(builder, alloc, ptrType, "");
740 			
741 			// XXX: This should be set on the alloc function instead of the callsite.
742 			LLVMAddCallSiteAttribute(
743 				alloc,
744 				LLVMAttributeReturnIndex,
745 				getAttribute("noalias"),
746 			);
747 			
748 			// Store all the values on heap.
749 			LLVMBuildStore(builder, array, ptr);
750 		}
751 		
752 		// Build the slice.
753 		auto slice = LLVMGetUndef(TypeGen(pass.pass).visit(t));
754 		auto i64 = LLVMInt64TypeInContext(llvmCtx);
755 		auto llvmCount = LLVMConstInt(i64, count, false);
756 		slice = LLVMBuildInsertValue(builder, slice, llvmCount, 0, "");
757 		
758 		auto elPtrType = LLVMPointerType(et, 0);
759 		ptr = LLVMBuildPointerCast(builder, ptr, elPtrType, "");
760 		slice = LLVMBuildInsertValue(builder, slice, ptr, 1, "");
761 		
762 		return slice;
763 	}
764 	
765 	auto buildCall(LLVMValueRef callee, LLVMValueRef[] args) {
766 		// Check if we need to invoke.
767 		if (!lpBB) {
768 			return LLVMBuildCall(
769 				builder,
770 				callee,
771 				args.ptr,
772 				cast(uint) args.length,
773 				"",
774 			);
775 		}
776 		
777 		auto currentBB = LLVMGetInsertBlock(builder);
778 		auto fun = LLVMGetBasicBlockParent(currentBB);
779 		auto thenBB = LLVMAppendBasicBlockInContext(llvmCtx, fun, "then");
780 		auto ret = LLVMBuildInvoke(
781 			builder,
782 			callee,
783 			args.ptr,
784 			cast(uint) args.length,
785 			thenBB,
786 			lpBB,
787 			"",
788 		);
789 		
790 		LLVMMoveBasicBlockAfter(thenBB, currentBB);
791 		LLVMPositionBuilderAtEnd(builder, thenBB);
792 		
793 		return ret;
794 	}
795 	
796 	private LLVMValueRef buildCall(CallExpression c) {
797 		auto cType = c.callee.type.getCanonical().asFunctionType();
798 		auto contexts = cType.contexts;
799 		auto params = cType.parameters;
800 		
801 		LLVMValueRef[] args;
802 		args.length = contexts.length + c.args.length;
803 		
804 		auto callee = visit(c.callee);
805 		foreach (i, ctx; contexts) {
806 			args[i] = LLVMBuildExtractValue(builder, callee, cast(uint) i, "");
807 		}
808 		
809 		auto firstarg = contexts.length;
810 		if (firstarg) {
811 			callee = LLVMBuildExtractValue(builder, callee, cast(uint) contexts.length, "");
812 		}
813 		
814 		uint i = 0;
815 		foreach(t; params) {
816 			args[i + firstarg] = t.isRef
817 				? addressOf(c.args[i])
818 				: visit(c.args[i]);
819 			i++;
820 		}
821 		
822 		// Handle variadic functions.
823 		while(i < c.args.length) {
824 			args[i + firstarg] = visit(c.args[i]);
825 			i++;
826 		}
827 		
828 		return buildCall(callee, args);
829 	}
830 	
831 	LLVMValueRef visit(CallExpression c) {
832 		return c.callee.type.asFunctionType().returnType.isRef
833 			? LLVMBuildLoad(builder, buildCall(c), "")
834 			: buildCall(c);
835 	}
836 	
837 	LLVMValueRef visit(IntrinsicExpression e) {
838 		import d.llvm.intrinsic, d.llvm.type;
839 		return buildBitCast(
840 			IntrinsicGen(pass).build(e.intrinsic, e.args),
841 			// XXX: This is necessary until returning sequence is supported.
842 			TypeGen(pass.pass).visit(e.type),
843 		);
844 	}
845 	
846 	LLVMValueRef visit(TupleExpression e) {
847 		import d.llvm.type;
848 		auto tuple = LLVMGetUndef(TypeGen(pass.pass).visit(e.type));
849 		
850 		uint i = 0;
851 		import std.algorithm;
852 		foreach(v; e.values.map!(v => visit(v))) {
853 			tuple = LLVMBuildInsertValue(builder, tuple, v, i++, "");
854 		}
855 		
856 		return tuple;
857 	}
858 	
859 	LLVMValueRef visit(DynamicTypeidExpression e) {
860 		auto vtblPtr = LLVMBuildStructGEP(builder, visit(e.argument), 0, "");
861 		auto vtbl = LLVMBuildLoad(builder, vtblPtr, "");
862 		
863 		import d.llvm.type;
864 		auto classInfo = TypeGen(pass.pass).visit(pass.object.getClassInfo());
865 		
866 		// The classInfo is just before the vtbls in memory.
867 		// So we cast the pointer and look at index -1 to get it.
868 		auto ptr = LLVMBuildBitCast(builder, vtbl, classInfo, "");
869 		auto idx = LLVMConstInt(LLVMInt32TypeInContext(llvmCtx), -1, true);
870 		return LLVMBuildGEP(builder, ptr, &idx, 1, "");
871 	}
872 	
873 	private LLVMValueRef getTypeid(Type t) {
874 		t = t.getCanonical();
875 		assert(t.kind == TypeKind.Class, "Not implemented");
876 		
877 		// Ensure that the thing is generated.
878 		auto c = t.dclass;
879 		
880 		import d.llvm.type;
881 		TypeGen(pass.pass).visit(c);
882 		
883 		return TypeGen(pass.pass).getTypeInfo(c);
884 	}
885 	
886 	LLVMValueRef visit(StaticTypeidExpression e) {
887 		return getTypeid(e.argument);
888 	}
889 	
890 	LLVMValueRef visit(VtblExpression e) {
891 		// Vtbl do not have a known type in D, so we need to cast.
892 		import d.llvm.type;
893 		return LLVMBuildPointerCast(
894 			builder,
895 			TypeGen(pass.pass).getVtbl(e.dclass),
896 			TypeGen(pass.pass).visit(e.type),
897 			"",
898 		);
899 	}
900 }
901 
902 struct AddressOfGen {
903 	private LocalPass pass;
904 	alias pass this;
905 	
906 	this(LocalPass pass) {
907 		this.pass = pass;
908 	}
909 	
910 	LLVMValueRef visit(Expression e) in {
911 		assert(e.isLvalue, "You can only compute addresses of lvalues.");
912 	} do {
913 		return this.dispatch(e);
914 	}
915 	
916 	private LLVMValueRef valueOf(E)(E e) if (is(E : Expression)) {
917 		return ExpressionGen(pass).visit(e);
918 	}
919 	
920 	LLVMValueRef visit(VariableExpression e) in {
921 		assert(e.var.storage != Storage.Enum, "enum have no address.");
922 		assert(!e.var.isFinal, "finals have no address.");
923 	} do {
924 		return declare(e.var);
925 	}
926 	
927 	LLVMValueRef visit(FieldExpression e) {
928 		auto base = e.expr;
929 		auto type = base.type.getCanonical();
930 		
931 		LLVMValueRef ptr;
932 		switch(type.kind) with(TypeKind) {
933 			case Slice, Struct, Union:
934 				ptr = visit(base);
935 				break;
936 			
937 			// XXX: Remove pointer. libd do not dererefence as expected.
938 			case Pointer, Class:
939 				ptr = valueOf(base);
940 				break;
941 			
942 			default:
943 				assert(
944 					0,
945 					"Address of field only work on aggregate types, not "
946 						~ type.toString(context));
947 		}
948 		
949 		// Make the type is not opaque.
950 		// XXX: Find a factorized way to load and gep that ensure
951 		// the indexed is not opaque and load metadata are correct.
952 		import d.llvm.type;
953 		TypeGen(pass.pass).visit(type);
954 		
955 		ptr = LLVMBuildStructGEP(builder, ptr, e.field.index, "");
956 		if (type.kind != TypeKind.Union) {
957 			return ptr;
958 		}
959 		
960 		return LLVMBuildBitCast(
961 			builder,
962 			ptr,
963 			LLVMPointerType(TypeGen(pass.pass).visit(e.type), 0),
964 			"",
965 		);
966 	}
967 	
968 	LLVMValueRef visit(ContextExpression e) in {
969 		assert(
970 			e.type.kind == TypeKind.Context,
971 			"ContextExpression must be of ContextType"
972 		);
973 	} do {
974 		return pass.getContext(e.type.context);
975 	}
976 	
977 	LLVMValueRef visit(UnaryExpression e) {
978 		if (e.op == UnaryOp.Dereference) {
979 			return valueOf(e.expr);
980 		}
981 		
982 		assert(0, "not an lvalue ??");
983 	}
984 	
985 	LLVMValueRef visit(CastExpression e) {
986 		import d.llvm.type;
987 		auto type = TypeGen(pass.pass).visit(e.type);
988 		auto value = visit(e.expr);
989 		
990 		final switch(e.kind) with(CastKind) {
991 			case Exact, Qual :
992 				return value;
993 			
994 			case Bit :
995 				return LLVMBuildBitCast(
996 					builder,
997 					value,
998 					LLVMPointerType(type, 0),
999 					"",
1000 				);
1001 			
1002 			case Invalid, IntToPtr, PtrToInt, Down :
1003 			case IntToBool, Trunc, SPad, UPad :
1004 				assert(0, "Not an lvalue");
1005 		}
1006 	}
1007 	
1008 	LLVMValueRef visit(CallExpression c) {
1009 		return ExpressionGen(pass).buildCall(c);
1010 	}
1011 	
1012 	LLVMValueRef visit(IndexExpression e) {
1013 		return computeIndexPtr(e.location, e.indexed, e.index);
1014 	}
1015 	
1016 	auto computeIndexPtr(Location location, Expression indexed, Expression index) {
1017 		auto t = indexed.type.getCanonical();
1018 		if (t.kind == TypeKind.Slice) {
1019 			auto slice = valueOf(indexed);
1020 			auto i64 = LLVMInt64TypeInContext(llvmCtx);
1021 			auto i = LLVMBuildZExt(builder, valueOf(index), i64, "");
1022 			auto length = LLVMBuildExtractValue(builder, slice, 0, ".length");
1023 			auto condition = LLVMBuildICmp(builder, LLVMIntPredicate.ULT, i, length, "");
1024 			genBoundCheck(location, condition);
1025 			
1026 			auto ptr = LLVMBuildExtractValue(builder, slice, 1, ".ptr");
1027 			return LLVMBuildInBoundsGEP(builder, ptr, &i, 1, "");
1028 		} else if (t.kind == TypeKind.Pointer) {
1029 			auto ptr = valueOf(indexed);
1030 			auto i = valueOf(index);
1031 			return LLVMBuildInBoundsGEP(builder, ptr, &i, 1, "");
1032 		} else if (t.kind == TypeKind.Array) {
1033 			auto ptr = visit(indexed);
1034 			auto i = valueOf(index);
1035 			
1036 			auto i64 = LLVMInt64TypeInContext(llvmCtx);
1037 			auto condition = LLVMBuildICmp(
1038 				builder,
1039 				LLVMIntPredicate.ULT,
1040 				LLVMBuildZExt(builder, i, i64, ""),
1041 				LLVMConstInt(LLVMInt64TypeInContext(llvmCtx), t.size, false),
1042 				"",
1043 			);
1044 			
1045 			genBoundCheck(location, condition);
1046 			
1047 			LLVMValueRef[2] indices;
1048 			indices[0] = LLVMConstInt(i64, 0, false);
1049 			indices[1] = i;
1050 			
1051 			return LLVMBuildInBoundsGEP(builder, ptr, indices.ptr, indices.length, "");
1052 		}
1053 		
1054 		assert(0, "Don't know how to index " ~ indexed.type.toString(context));
1055 	}
1056 	
1057 	auto genBoundCheck(Location location, LLVMValueRef condition) {
1058 		return ExpressionGen(pass).genBoundCheck(location, condition);
1059 	}
1060 }