Mercurial > projects > dang
comparison gen/CodeGen.d @ 173:50b98a06a200
Start of support for virtual functions
author | Anders Halager <halager@gmail.com> |
---|---|
date | Thu, 24 Jul 2008 20:40:04 +0200 |
parents | f0385c044065 |
children | 20ff3c31f600 |
comparison
equal
deleted
inserted
replaced
172:01c2c49775ef | 173:50b98a06a200 |
---|---|
220 GlobalVariable g = m.addGlobal(t, id.get); | 220 GlobalVariable g = m.addGlobal(t, id.get); |
221 g.initializer = ConstantInt.GetS(t, 0); | 221 g.initializer = ConstantInt.GetS(t, 0); |
222 table[varDecl.identifier.get] = g; | 222 table[varDecl.identifier.get] = g; |
223 break; | 223 break; |
224 | 224 |
225 case DeclType.ClassDecl: | |
226 auto cdecl = cast(ClassDecl)decl; | |
227 SmallArray!(Constant) functions; | |
228 foreach (d; cdecl.decls) | |
229 { | |
230 auto func = cast(FuncDecl)d; | |
231 if (func is null) | |
232 continue; | |
233 genRootDecl(func); | |
234 auto llvm_f = m.getNamedFunction(symbolName(func)); | |
235 functions ~= Constant.GetBitCast(llvm_f, BytePtr); | |
236 } | |
237 auto class_vtbl = ConstantArray.Get(BytePtr, functions.unsafe()); | |
238 auto gv = m.addGlobal(class_vtbl, cdecl.identifier.get ~ "_vtable"); | |
239 gv.linkage = Linkage.Weak; | |
240 gv.globalConstant = true; | |
241 break; | |
242 | |
225 default: | 243 default: |
226 break; | 244 break; |
227 } | 245 } |
228 } | 246 } |
229 | 247 |
246 RValue src = genExpression(varDecl.init); | 264 RValue src = genExpression(varDecl.init); |
247 storeThroughLValue(dst, src, id.type); | 265 storeThroughLValue(dst, src, id.type); |
248 } | 266 } |
249 break; | 267 break; |
250 | 268 |
251 case DeclType.FuncDecl: | 269 case DeclType.FuncDecl, |
270 DeclType.StructDecl, | |
271 DeclType.ClassDecl: | |
252 genRootDecl(decl); | 272 genRootDecl(decl); |
253 break; | 273 break; |
254 | 274 |
255 default: | 275 default: |
256 break; | 276 break; |
343 DType type = callExp.exp.type; | 363 DType type = callExp.exp.type; |
344 assert (type.isFunction(), "Can only call functions"); | 364 assert (type.isFunction(), "Can only call functions"); |
345 scope args = new Value[callExp.args.length]; | 365 scope args = new Value[callExp.args.length]; |
346 foreach (i, arg; callExp.args) | 366 foreach (i, arg; callExp.args) |
347 args[i] = genExpression(arg).value; | 367 args[i] = genExpression(arg).value; |
348 llvm(type); | 368 DFunction ftype = type.asFunction(); |
349 Function f = null; | 369 Type llvm_ftype = llvm(ftype); |
370 Value f = null; | |
350 if (callExp.callSym is null) | 371 if (callExp.callSym is null) |
351 { | 372 { |
352 // Do a virtual function call | 373 // Do a virtual function call |
353 f = m.getNamedFunction(symbolName(callExp.exp)); | 374 f = genLValue(callExp.exp).getAddress(); |
375 f = b.buildLoad(f, "func_pointer"); | |
376 f = b.buildBitCast( | |
377 f, | |
378 PointerType.Get(llvm_ftype), | |
379 ftype.name); | |
354 } | 380 } |
355 else | 381 else |
356 { | 382 { |
357 auto sym = callExp.callSym; | 383 auto sym = callExp.callSym; |
358 f = m.getNamedFunction(sym.getMangledFQN()); | 384 f = m.getNamedFunction(sym.getMangledFQN()); |
359 } | 385 } |
360 DFunction f_type = type.asFunction(); | 386 bool isVoid = ftype.returnType is DType.Void; |
361 bool isVoid = f_type.returnType is DType.Void; | |
362 auto r = b.buildCall(f, args, isVoid? "" : "call"); | 387 auto r = b.buildCall(f, args, isVoid? "" : "call"); |
363 return RValue(r); | 388 return RValue(r); |
364 case ExpType.CastExp: | 389 case ExpType.CastExp: |
365 auto castExp = cast(CastExp)exp; | 390 auto castExp = cast(CastExp)exp; |
366 exp = castExp.exp; | 391 exp = castExp.exp; |
685 case ExpType.Identifier: | 710 case ExpType.Identifier: |
686 auto id = cast(Identifier)mem.target; | 711 auto id = cast(Identifier)mem.target; |
687 auto child = mem.child; | 712 auto child = mem.child; |
688 Value v = table.find(id.get); | 713 Value v = table.find(id.get); |
689 DType t = id.type; | 714 DType t = id.type; |
690 auto st = t.asStruct; | 715 if (auto st = t.asStruct) |
691 | 716 { |
692 int i = st.indexOf(child.get); | 717 int i = st.indexOf(child.get); |
693 | 718 if (i == -1) |
694 Value[2] vals; | 719 { |
695 vals[0] = ZeroIndex; | 720 auto fname = mem.getSymbol.getMangledFQN(); |
696 vals[1] = ConstantInt.GetU(IntegerType.Int32, i); | 721 auto f = m.getNamedFunction(fname); |
697 | 722 return LValue(f); |
698 Value val = b.buildGEP(v, vals, id.get~"."~child.get); | 723 } |
699 return LValue(val); | 724 |
725 Value[2] vals; | |
726 vals[0] = ZeroIndex; | |
727 vals[1] = ConstantInt.GetU(IntegerType.Int32, i); | |
728 | |
729 Value val = b.buildGEP(v, vals, id.get~"."~child.get); | |
730 return LValue(val); | |
731 } | |
732 else if (auto ct = t.asClass) | |
733 { | |
734 int i = ct.indexOf(child.get); | |
735 Value[2] vals; | |
736 vals[0] = ZeroIndex; | |
737 // A normal member | |
738 if (i != -1) | |
739 { | |
740 vals[1] = ConstantInt.GetU(IntegerType.Int32, i); | |
741 Value val = b.buildGEP(v, vals, id.get~"."~child.get); | |
742 return LValue(val); | |
743 } | |
744 // A method | |
745 else | |
746 { | |
747 vals[1] = ZeroIndex; | |
748 //vals[1] = ConstantInt.GetU(IntegerType.Int32, 1); | |
749 auto vtbl_name = ct.name ~ "_vtable"; | |
750 auto vtbl = m.getNamedGlobal(vtbl_name); | |
751 v = vtbl; | |
752 } | |
753 | |
754 Value val = b.buildGEP(v, vals, id.get~"."~child.get); | |
755 return LValue(val); | |
756 } | |
757 else | |
758 assert(0, "Can only access members in classes " | |
759 "and structs"); | |
700 | 760 |
701 case ExpType.MemberReference: | 761 case ExpType.MemberReference: |
702 auto addr = genLValue(mem.target).getAddress(); | 762 auto addr = genLValue(mem.target).getAddress(); |
703 auto child = mem.child; | 763 auto child = mem.child; |
704 DStruct t = mem.target.type.asStruct(); | 764 DStruct t = mem.target.type.asStruct(); |