# HG changeset patch # User Anders Halager # Date 1216924804 -7200 # Node ID 50b98a06a200c296e84edebffcde08b30630dd5b # Parent 01c2c49775eff583b288a668513dc5f608d43014 Start of support for virtual functions diff -r 01c2c49775ef -r 50b98a06a200 ast/Decl.d --- a/ast/Decl.d Thu Jul 24 20:31:24 2008 +0200 +++ b/ast/Decl.d Thu Jul 24 20:40:04 2008 +0200 @@ -246,7 +246,7 @@ this.identifier = identifier; auto name = new Identifier(identifier.loc, "__vptr"); - auto type = new IdentifierTypeExp(identifier.loc, "int"); + auto type = new IdentifierTypeExp(identifier.loc, "byte"); auto p_type = new PointerTypeExp(type); decls ~= new VarDecl(p_type, name, null); } diff -r 01c2c49775ef -r 50b98a06a200 gen/CodeGen.d --- a/gen/CodeGen.d Thu Jul 24 20:31:24 2008 +0200 +++ b/gen/CodeGen.d Thu Jul 24 20:40:04 2008 +0200 @@ -222,6 +222,24 @@ table[varDecl.identifier.get] = g; break; + case DeclType.ClassDecl: + auto cdecl = cast(ClassDecl)decl; + SmallArray!(Constant) functions; + foreach (d; cdecl.decls) + { + auto func = cast(FuncDecl)d; + if (func is null) + continue; + genRootDecl(func); + auto llvm_f = m.getNamedFunction(symbolName(func)); + functions ~= Constant.GetBitCast(llvm_f, BytePtr); + } + auto class_vtbl = ConstantArray.Get(BytePtr, functions.unsafe()); + auto gv = m.addGlobal(class_vtbl, cdecl.identifier.get ~ "_vtable"); + gv.linkage = Linkage.Weak; + gv.globalConstant = true; + break; + default: break; } @@ -248,7 +266,9 @@ } break; - case DeclType.FuncDecl: + case DeclType.FuncDecl, + DeclType.StructDecl, + DeclType.ClassDecl: genRootDecl(decl); break; @@ -345,20 +365,25 @@ scope args = new Value[callExp.args.length]; foreach (i, arg; callExp.args) args[i] = genExpression(arg).value; - llvm(type); - Function f = null; + DFunction ftype = type.asFunction(); + Type llvm_ftype = llvm(ftype); + Value f = null; if (callExp.callSym is null) { // Do a virtual function call - f = m.getNamedFunction(symbolName(callExp.exp)); + f = genLValue(callExp.exp).getAddress(); + f = b.buildLoad(f, "func_pointer"); + f = b.buildBitCast( + f, + PointerType.Get(llvm_ftype), + ftype.name); } else { auto sym = callExp.callSym; f = m.getNamedFunction(sym.getMangledFQN()); } - DFunction f_type = type.asFunction(); - bool isVoid = f_type.returnType is DType.Void; + bool isVoid = ftype.returnType is DType.Void; auto r = b.buildCall(f, args, isVoid? "" : "call"); return RValue(r); case ExpType.CastExp: @@ -687,16 +712,51 @@ auto child = mem.child; Value v = table.find(id.get); DType t = id.type; - auto st = t.asStruct; + if (auto st = t.asStruct) + { + int i = st.indexOf(child.get); + if (i == -1) + { + auto fname = mem.getSymbol.getMangledFQN(); + auto f = m.getNamedFunction(fname); + return LValue(f); + } - int i = st.indexOf(child.get); + Value[2] vals; + vals[0] = ZeroIndex; + vals[1] = ConstantInt.GetU(IntegerType.Int32, i); - Value[2] vals; - vals[0] = ZeroIndex; - vals[1] = ConstantInt.GetU(IntegerType.Int32, i); + Value val = b.buildGEP(v, vals, id.get~"."~child.get); + return LValue(val); + } + else if (auto ct = t.asClass) + { + int i = ct.indexOf(child.get); + Value[2] vals; + vals[0] = ZeroIndex; + // A normal member + if (i != -1) + { + vals[1] = ConstantInt.GetU(IntegerType.Int32, i); + Value val = b.buildGEP(v, vals, id.get~"."~child.get); + return LValue(val); + } + // A method + else + { + vals[1] = ZeroIndex; + //vals[1] = ConstantInt.GetU(IntegerType.Int32, 1); + auto vtbl_name = ct.name ~ "_vtable"; + auto vtbl = m.getNamedGlobal(vtbl_name); + v = vtbl; + } - Value val = b.buildGEP(v, vals, id.get~"."~child.get); - return LValue(val); + Value val = b.buildGEP(v, vals, id.get~"."~child.get); + return LValue(val); + } + else + assert(0, "Can only access members in classes " + "and structs"); case ExpType.MemberReference: auto addr = genLValue(mem.target).getAddress();