Closed RedCubeDev-ByteSpace closed 2 years ago
Hi @RedCubeDev-ByteSpace!
Glad to see you are getting into compiler design and development! It's a great passion and you will hopefully have a lot of fun implementing your own compiler :)
Given the following input C source file:
typedef int (*FooFunc)(int x, int y);
typedef double (*BarFunc)(double v);
typedef struct {
FooFunc foo_func;
BarFunc bar_func;
} StructType;
int foo(int x, int y) {
return x + y;
}
double bar(double v) {
return 2.0*v;
}
int main() {
StructType baz;
baz.foo_func = foo;
baz.bar_func = bar;
double result = baz.bar_func(3.0);
return baz.foo_func(12, 30);
}
And the corresponding LLVM IR (by running the command clang -S -emit-llvm -o foo.ll foo.c
):
; ModuleID = 'foo.c'
source_filename = "foo.c"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"
%struct.StructType = type { i32 (i32, i32)*, double (double)* }
; Function Attrs: noinline nounwind optnone sspstrong uwtable
define dso_local i32 @foo(i32 %0, i32 %1) #0 {
%3 = alloca i32, align 4
%4 = alloca i32, align 4
store i32 %0, i32* %3, align 4
store i32 %1, i32* %4, align 4
%5 = load i32, i32* %3, align 4
%6 = load i32, i32* %4, align 4
%7 = add nsw i32 %5, %6
ret i32 %7
}
; Function Attrs: noinline nounwind optnone sspstrong uwtable
define dso_local double @bar(double %0) #0 {
%2 = alloca double, align 8
store double %0, double* %2, align 8
%3 = load double, double* %2, align 8
%4 = fmul double 2.000000e+00, %3
ret double %4
}
; Function Attrs: noinline nounwind optnone sspstrong uwtable
define dso_local i32 @main() #0 {
%1 = alloca i32, align 4
%2 = alloca %struct.StructType, align 8
%3 = alloca double, align 8
store i32 0, i32* %1, align 4
%4 = getelementptr inbounds %struct.StructType, %struct.StructType* %2, i32 0, i32 0
store i32 (i32, i32)* @foo, i32 (i32, i32)** %4, align 8
%5 = getelementptr inbounds %struct.StructType, %struct.StructType* %2, i32 0, i32 1
store double (double)* @bar, double (double)** %5, align 8
%6 = getelementptr inbounds %struct.StructType, %struct.StructType* %2, i32 0, i32 1
%7 = load double (double)*, double (double)** %6, align 8
%8 = call double %7(double 3.000000e+00)
store double %8, double* %3, align 8
%9 = getelementptr inbounds %struct.StructType, %struct.StructType* %2, i32 0, i32 0
%10 = load i32 (i32, i32)*, i32 (i32, i32)** %9, align 8
%11 = call i32 %10(i32 12, i32 30)
ret i32 %11
}
attributes #0 = { noinline nounwind optnone sspstrong uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
!llvm.module.flags = !{!0, !1, !2, !3, !4}
!llvm.ident = !{!5}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 7, !"PIC Level", i32 2}
!2 = !{i32 7, !"PIE Level", i32 2}
!3 = !{i32 7, !"uwtable", i32 1}
!4 = !{i32 7, !"frame-pointer", i32 2}
!5 = !{!"clang version 13.0.1"}
We can see that the struct type containing the two function pointers is as follows:
%struct.StructType = type { i32 (i32, i32)*, double (double)* }
To produce a corresponding struct type using the llir/llvm
API, the type has to be the same, both structurally (have the same struct fields with the same types) and the same type name (i.e. %struct.StructType
in this case).
package main
import (
"fmt"
"github.com/llir/llvm/ir/types"
)
func main() {
i32RetType := types.I32
i32XParamType := types.I32
i32YParamType := types.I32
fooFuncType := types.NewFunc(i32RetType, i32XParamType, i32YParamType)
doubleRetType := types.Double
doubleVParamType := types.Double
barFuncType := types.NewFunc(doubleRetType, doubleVParamType)
structType := types.NewStruct(fooFuncType, barFuncType)
structType.SetName("struct.StructType")
fmt.Println(structType)
}
The above Go program will output:
%struct.StructType
In particular, take a look at the documentation of ir/types.NewFunc.
Wish you all the best and happy coding!
Cheers, Robin
Oh wow thanks for the quick reply!
I see, alright thank you a lot for taking the time to explain this to me :D
Glad the explanation helped! :)
I'll close this issue for now, if you wonder something in the future, feel free to open a new issue or re-open this one.
Happy coding!
Cheers, Robin
Hello there 👋
Ive been working on a compiler for a couple weeks and started work on some object oriented constructs.
For that I have written all the necessary code in C using structs and functions. I would now like use those structs in my go-compiled program. (I assume using external structs works the same way as using external functions (just declaring it and the linker takes care of the rest))
The problem I am currently facing is that these structs contain function pointers but sadly I have no idea how to create a function pointer type and use it for a type definition. I also couldnt find any info online, in the linked documentation, or in any other github issues.
Also this project is really lacking in (noob friendly) documentation haha
I hope someone here can help me out ^^