@@ -1208,6 +1208,8 @@ class LLVMCompiler {
12081208 std::unordered_map<std::string, llvm::StructType*> structTypes;
12091209 std::unordered_map<std::string, llvm::StructType*> unionTypes;
12101210 std::unordered_map<std::string, llvm::StructType*> classTypes;
1211+ std::unordered_map<std::string, llvm::GlobalVariable*> vtables;
1212+ std::unordered_map<std::string, std::unordered_map<std::string, int >> vtableSlotIndex;
12111213 std::unordered_map<std::string, std::unordered_map<std::string, std::vector<llvm::Function*>>> classMethods;
12121214 llvm::Value* currentThis = nullptr ;
12131215 std::string currentClassName = " " ;
@@ -1321,7 +1323,7 @@ class LLVMCompiler {
13211323 } else if (auto unaryOp = std::get_if<UnaryOpNode*>(&node)) {
13221324 std::string type = getExpressionType ((*unaryOp)->node , strip);
13231325 if ((*unaryOp)->op_tok .type == TokenType::MUL ) {
1324- if (type.ends_with (" *" )) { type.pop_back (); }
1326+ if (type.ends_with (" *" ) && strip ) { type.pop_back (); }
13251327 }
13261328 return type;
13271329 } else if (auto binOp = std::get_if<BinOpNode*>(&node)) {
@@ -1541,6 +1543,7 @@ class LLVMCompiler {
15411543 return addr;
15421544 } else if (auto unary = std::get_if<UnaryOpNode*>(&node)) {
15431545 if ((*unary)->op_tok .type == TokenType::MUL ) { return emitExpr ((*unary)->node ); }
1546+ if ((*unary)->op_tok .type == TokenType::AMPERSAND ) { return emitLValue ((*unary)->node ); }
15441547 } else if (auto prop = std::get_if<PropertyAccessNode*>(&node)) {
15451548 return emitPropertyAddress (**prop);
15461549 } else if (auto call = std::get_if<CallNode*>(&node)) {
@@ -2130,6 +2133,24 @@ class LLVMCompiler {
21302133 }
21312134 return builder->CreateCall (method, reconciled, name + " _result" );
21322135 }
2136+ std::string resolveVirtualTargetClass (const std::string& declaredClass,
2137+ const std::string& methodName,
2138+ size_t argCount) {
2139+ for (auto & m : userTypes[declaredClass].classMethods ) {
2140+ if (m.name_tok .value == methodName && m.params .size () == argCount)
2141+ return declaredClass;
2142+ }
2143+ for (auto & [name, info] : userTypes) {
2144+ if (info.baseClassName == declaredClass) {
2145+ for (auto & m : info.classMethods ) {
2146+ if (m.name_tok .value == methodName && m.params .size () == argCount)
2147+ return name;
2148+ }
2149+ }
2150+ }
2151+ return declaredClass;
2152+ }
2153+
21332154 llvm::Function* findMethodOverload (const std::string& className, const std::string& methodName, const std::vector<llvm::Value*>& args) {
21342155 std::string resolvedClassName = className;
21352156 if (className.find (" ::" ) == std::string::npos && !getCurrentNamespace ().empty ()) {
@@ -2220,6 +2241,38 @@ class LLVMCompiler {
22202241
22212242 return nullptr ;
22222243 }
2244+ llvm::Value* emitVirtualOrDirectCall (
2245+ const std::string& ty,
2246+ const std::string& methodName,
2247+ llvm::Value* payload,
2248+ const std::vector<llvm::Value*>& args)
2249+ {
2250+ auto vtableIt = vtables.find (ty);
2251+ auto slotIt = vtableSlotIndex.find (ty);
2252+ if (vtableIt != vtables.end () && slotIt != vtableSlotIndex.end ()) {
2253+ std::string mangledName = ty + " _" + methodName;
2254+ auto indexIt = slotIt->second .find (mangledName);
2255+ if (indexIt != slotIt->second .end ()) {
2256+ int slotIndex = indexIt->second ;
2257+ llvm::StructType* classTy = classTypes[ty];
2258+ llvm::Value* vptrField = builder->CreateStructGEP (classTy, payload, 0 , " vptr_field" );
2259+ llvm::Value* vptr = builder->CreateLoad (builder->getPtrTy (), vptrField, " vptr" );
2260+ llvm::Value* fnPtrAddr = builder->CreateGEP (builder->getPtrTy (), vptr,
2261+ builder->getInt32 (slotIndex), " vtable_slot" );
2262+ llvm::Value* fnPtr = builder->CreateLoad (builder->getPtrTy (), fnPtrAddr, " fn_ptr" );
2263+
2264+ llvm::Function* method = findMethodOverload (ty, methodName, args);
2265+ if (!method) return nullptr ;
2266+
2267+ std::vector<llvm::Value*> allArgs = {payload};
2268+ allArgs.insert (allArgs.end (), args.begin (), args.end ());
2269+ return builder->CreateCall (method->getFunctionType (), fnPtr, allArgs);
2270+ }
2271+ }
2272+ llvm::Function* method = findMethodOverload (ty, methodName, args);
2273+ if (!method) return nullptr ;
2274+ return emitMethodCall (method, payload, args, methodName);
2275+ }
22232276 llvm::Function* generateSpecializedMethod (const std::string& className, size_t methodIdx, const std::vector<std::string>& concreteTypes,
22242277 const std::string& specializedName) {
22252278 llvm::Function* savedFunction = currentFunction;
0 commit comments