-
Notifications
You must be signed in to change notification settings - Fork 79
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
module.NewTypeDef
has unexpected side effects
#226
Comments
Do you want a type is an alias of i64 here? |
Yes. So my first module used |
@mewmew I guess here have two problems
|
Because I think the quick fix here is clone the |
Yes, this is what I ended up doing: func clone(typ types.Type) types.Type {
switch typ := typ.(type) {
case *types.VoidType:
return &types.VoidType{}
case *types.MMXType:
return &types.MMXType{}
case *types.LabelType:
return &types.LabelType{}
case *types.TokenType:
return &types.TokenType{}
case *types.MetadataType:
return &types.MetadataType{}
case *types.IntType:
return &types.IntType{BitSize: typ.BitSize}
case *types.FloatType:
return &types.FloatType{Kind: typ.Kind}
case *types.PointerType:
return &types.PointerType{ElemType: typ.ElemType, AddrSpace: typ.AddrSpace}
case *types.ArrayType:
return &types.ArrayType{Len: typ.Len, ElemType: typ.ElemType}
case *types.VectorType:
return &types.VectorType{Scalable: typ.Scalable, Len: typ.Len, ElemType: typ.ElemType}
case *types.FuncType:
return &types.FuncType{RetType: typ.RetType, Params: typ.Params, Variadic: typ.Variadic}
case *types.StructType:
return &types.StructType{Packed: typ.Packed, Fields: typ.Fields, Opaque: typ.Opaque}
}
panic(fmt.Errorf("support for type %T not yet implemented", typ))
} |
Cloning is painful in Go, this is also why we have no idea how to provide a general solution in this case. |
It's not perfect, but gets the job done for now. |
Hi Peter, Happy to see you exploring the unknowns of LLVM IR in Go : ) Also saw that you came in touch with @alecthomas's With regards to As for this issue. As you've both mentioned, this is an unfortunate side effect of changing aspects of global variables of the m := ir.NewModule()
i64 := types.NewInt(64)
helloType := m.NewTypeDef("hello", i64) With regards to the unexpected side effects, I think we can add some documentation to ir.Module.NewTypeDef to help avoid this for other users. Cheerful regards, |
Added docs in 5d46090 to help avoid the unexpected side effect in the future. Let me know if the docs are clear enough, or if they need to be rephrased. Cheers, |
wow, I don't even remember there has |
Hey @mewmew Highly appreciate your feedback. Yes, I'm writing an LLVM frontend for my hobby programming language :) Btw. your library is pretty stunning. I wouldn't even try to guess how much time it takes to map out the entire LLVM IR syntax. Thanks for the suggestion. I will go with While we are at it. Whats to way to create an alias of an alias? Similar to this. typedef i64 hello;
typedef hello world; Thanks |
@mewmew Few constructors are missing for types like float or double, there is no &types.FloatType{Kind: types.FloatKindFloat} Also as far as I can tell, there is no way to make an alias (TypeDef) to another alias, like: typedef i64 hello;
typedef hello world; Because ir.Module's for _, t := range m.TypeDefs {
// Name=LocalIdent '=' 'type' Typ=OpaqueType
//
// Name=LocalIdent '=' 'type' Typ=Type
fw.Fprintf("%s = type %s\n", t, t.LLString())
} |
Haha, happy to hear you like the library! Yeah, quite a lot of time went into writing the BNF grammar for LLVM IR, but it was fun too! Also, is the repo for your hobby language open source? Would be cool to check out.
Hmm, I think you're right. If you really want it, you could create a custom type which implements the types.Type interface. Here's a proof of concept, it's not pretty, but it seems to work ^^ package main
import (
"fmt"
"github.com/llir/llvm/ir"
"github.com/llir/llvm/ir/types"
)
func main() {
m := ir.NewModule()
i64 := types.NewInt(64)
helloType := m.NewTypeDef("hello", i64)
aliasType := &AliasType{
name: "world",
Type: helloType,
}
m.TypeDefs = append(m.TypeDefs, aliasType)
fmt.Println(m)
}
type AliasType struct {
// alias name.
name string
// underlying type.
types.Type
}
func (a *AliasType) Name() string {
return a.name
}
func (a *AliasType) SetName(name string) {
a.name = name
}
func (a *AliasType) String() string {
return "%" + a.name // NOTE: the proper way to encode local identifiers is to use `enc.LocalName`.
}
func (a *AliasType) LLString() string {
if len(a.Type.Name()) == 0 {
return a.Type.LLString()
}
return "%" + a.Type.Name() // NOTE: the proper way to encode local identifiers is to use `enc.LocalName`.
} NOTE: the proper way to encode local identifiers is to use Line 49 in 5d46090
Cheers, |
Genius. I totally overlooked the fact that types.Type is an interface that can be implemented. Thanks so much for the example! Yeah sure, I just open-sourced it here: https://github.com/klvnptr/k I welcome any feedback. |
@mewmew I tried to use the above suggested |
Hi @klvnptr! Wish you a happy new years : )
Ah, damn. That sucks. I know we've been thinking of how to make the internal So, sorry for the pain. This is work we wish to do. But as with many things in life, time is not always on our side. Don't wait for a quick change on this one as it will require quite fundamental restructuring of the internal logic of Until then, we'll have to find joys in other parts of life ^^ Wish you a great year to come! |
hey Robin, no worries, I will work around it :) thanks much. |
The following code has unexpected side effects on the convenience types:
Because
NewTypeDef
sets the type's name. Which is okay, but next time if I usetypes.I64
it will have namehello
since, the convenience type is a pointer. To be honest, I don't really have an idea how to solve this. But it took me about 3 hours of debugging till I figured out why my i64 types calledhello
in LLVM IR.The text was updated successfully, but these errors were encountered: