Skip to content

The virtual function is not correctly invoked. #420

@sybs5968

Description

@sybs5968

Hello, when I try to translate operations with Polygeist that call virtual functions, I find that the base class calls the functions of the base class, not the functions overridden by the subclass. The sample I used is as follows. The comments are the translated result. The command I used is cgeist test.cpp --function=main --resource-dir=/Polygeist/llvm-project/build/lib/clang/18 -I /Polygeist/tools/cgeist/Test/polybench/utilities -S

In the base class, vfunc is an addition operation. In the subclass, it is rewritten as a subtraction operation. The final translation is the addition operation of the base class(%12 = arith.addi %10, %11 : i32) instead of the expected subtraction operation of the subclass.

#include <new>
#include <cstdio>
class SimStream {
public:
    int n;
    SimStream() {
        n = 0;
    }
    virtual int vfunc(int val1 , int val2) {
        return val1 + val2;
    }
};

class subSimStream : public SimStream {
public:
    int vfunc(int val1 , int val2) override {
        return val1 - val2;
    }
};

int myfunc(SimStream *ptr , int val1 , int val2) {
    int output = ptr->vfunc(val1 , val2);
    return output;
}

int main() {
    SimStream *r = new subSimStream;
    int val1 , val2 , output;
    scanf("%d%d" , &val1 , &val2);
    output = r->vfunc(val1 , val2);
    printf("output = %d\n" , output);
    delete r;
    return 0;
}

/*
module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<i32, dense<32> : vector<2xi32>>, #dlti.dl_entry<f16, dense<16> : vector<2xi32>>, #dlti.dl_entry<f64, dense<64> : vector<2xi32>>, #dlti.dl_entry<i16, dense<16> : vector<2xi32>>, #dlti.dl_entry<f128, dense<128> : vector<2xi32>>, #dlti.dl_entry<i8, dense<8> : vector<2xi32>>, #dlti.dl_entry<i1, dense<8> : vector<2xi32>>, #dlti.dl_entry<!llvm.ptr, dense<64> : vector<4xi32>>, #dlti.dl_entry<f80, dense<128> : vector<2xi32>>, #dlti.dl_entry<i64, dense<64> : vector<2xi32>>, #dlti.dl_entry<!llvm.ptr<272>, dense<64> : vector<4xi32>>, #dlti.dl_entry<!llvm.ptr<271>, dense<32> : vector<4xi32>>, #dlti.dl_entry<!llvm.ptr<270>, dense<32> : vector<4xi32>>, #dlti.dl_entry<"dlti.stack_alignment", 128 : i32>, #dlti.dl_entry<"dlti.endianness", "little">>, llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", llvm.target_triple = "x86_64-unknown-linux-gnu", "polygeist.target-cpu" = "x86-64", "polygeist.target-features" = "+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87", "polygeist.tune-cpu" = "generic"} {
  llvm.func @free(!llvm.ptr)
  llvm.mlir.global internal constant @str1("output = %d\0A\00") {addr_space = 0 : i32}
  llvm.func @printf(!llvm.ptr, ...) -> i32
  llvm.mlir.global internal constant @str0("%d%d\00") {addr_space = 0 : i32}
  llvm.func @scanf(!llvm.ptr, ...) -> i32
  func.func @main() -> i32 attributes {llvm.linkage = #llvm.linkage<external>} {
    %c0_i32 = arith.constant 0 : i32
    %0 = llvm.mlir.undef : i32
    %alloca = memref.alloca() : memref<1xi32>
    affine.store %0, %alloca[0] : memref<1xi32>
    %alloca_0 = memref.alloca() : memref<1xi32>
    affine.store %0, %alloca_0[0] : memref<1xi32>
    %alloc = memref.alloc() : memref<1x!llvm.struct<(struct<packed (ptr, i32, array<4 x i8>)>)>>
    %cast = memref.cast %alloc : memref<1x!llvm.struct<(struct<packed (ptr, i32, array<4 x i8>)>)>> to memref<?x!llvm.struct<(struct<packed (ptr, i32, array<4 x i8>)>)>>
    call @_ZN12subSimStreamC1Ev(%cast) : (memref<?x!llvm.struct<(struct<packed (ptr, i32, array<4 x i8>)>)>>) -> ()
    %1 = "polygeist.memref2pointer"(%alloc) : (memref<1x!llvm.struct<(struct<packed (ptr, i32, array<4 x i8>)>)>>) -> !llvm.ptr
    %2 = llvm.mlir.zero : !llvm.ptr
    %3 = llvm.icmp "ne" %1, %2 : !llvm.ptr
    %4 = arith.select %3, %1, %2 : !llvm.ptr
    %5 = llvm.mlir.addressof @str0 : !llvm.ptr
    %6 = llvm.getelementptr %5[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<5 x i8>
    %7 = "polygeist.memref2pointer"(%alloca_0) : (memref<1xi32>) -> !llvm.ptr
    %8 = "polygeist.memref2pointer"(%alloca) : (memref<1xi32>) -> !llvm.ptr
    %9 = llvm.call @scanf(%6, %7, %8) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr, !llvm.ptr, !llvm.ptr) -> i32
    %10 = affine.load %alloca_0[0] : memref<1xi32>
    %11 = affine.load %alloca[0] : memref<1xi32>
    %12 = arith.addi %10, %11 : i32
    %13 = llvm.mlir.addressof @str1 : !llvm.ptr
    %14 = llvm.getelementptr %13[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<13 x i8>
    %15 = llvm.call @printf(%14, %12) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr, i32) -> i32
    llvm.call @free(%4) : (!llvm.ptr) -> ()
    return %c0_i32 : i32
  }
  func.func @_ZN12subSimStreamC1Ev(%arg0: memref<?x!llvm.struct<(struct<packed (ptr, i32, array<4 x i8>)>)>>) attributes {llvm.linkage = #llvm.linkage<linkonce_odr>} {
    %0 = "polygeist.memref2pointer"(%arg0) : (memref<?x!llvm.struct<(struct<packed (ptr, i32, array<4 x i8>)>)>>) -> !llvm.ptr
    %1 = "polygeist.pointer2memref"(%0) : (!llvm.ptr) -> memref<?x!llvm.struct<packed (ptr, i32, array<4 x i8>)>>
    call @_ZN9SimStreamC1Ev(%1) : (memref<?x!llvm.struct<packed (ptr, i32, array<4 x i8>)>>) -> ()
    return
  }
  func.func @_ZN9SimStream5vfuncEii(%arg0: memref<?x!llvm.struct<packed (ptr, i32, array<4 x i8>)>>, %arg1: i32, %arg2: i32) -> i32 attributes {llvm.linkage = #llvm.linkage<linkonce_odr>} {
    %0 = arith.addi %arg1, %arg2 : i32
    return %0 : i32
  }
  func.func @_ZN9SimStreamC1Ev(%arg0: memref<?x!llvm.struct<packed (ptr, i32, array<4 x i8>)>>) attributes {llvm.linkage = #llvm.linkage<linkonce_odr>} {
    %c0_i32 = arith.constant 0 : i32
    %0 = "polygeist.memref2pointer"(%arg0) : (memref<?x!llvm.struct<packed (ptr, i32, array<4 x i8>)>>) -> !llvm.ptr
    %1 = llvm.getelementptr %0[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<packed (ptr, i32, array<4 x i8>)>
    llvm.store %c0_i32, %1 : i32, !llvm.ptr
    return
  }
}
*/

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions