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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions