changeset 173:50b98a06a200

Start of support for virtual functions
author Anders Halager <halager@gmail.com>
date Thu, 24 Jul 2008 20:40:04 +0200
parents 01c2c49775ef
children 20ff3c31f600
files ast/Decl.d gen/CodeGen.d
diffstat 2 files changed, 74 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- 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);
     }
--- 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();