Skip to content
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

ir.InlineAsm does not implement value.Named #33

Closed
driusan opened this issue Jul 7, 2018 · 10 comments
Closed

ir.InlineAsm does not implement value.Named #33

driusan opened this issue Jul 7, 2018 · 10 comments
Milestone

Comments

@driusan
Copy link

driusan commented Jul 7, 2018

The documentation for NewCall says it may have one of the following types:

*ir.Function
*types.Param
*constant.ExprBitCast
*ir.InstBitCast
*ir.InstLoad
*ir.InlineAsm

However, ir.InlineAsm doesn't implement the value.Named interface, so trying to use it as the callee parameter results in a compile time error about *ir.InlineAsm not implementing GetName()

@mewmew mewmew closed this as completed in 2814926 Jul 7, 2018
@mewmew
Copy link
Member

mewmew commented Jul 7, 2018

@driusan good catch. The ir.NewCall function used value.Value as the type of the callee, while the ir.BasicBlock.NewCall method used value.Named as the type of the callee.

This has been fixed, and now both constructors use value.Value.

Cheers
/u

mewmew added a commit that referenced this issue Nov 30, 2018
@pwaller
Copy link
Member

pwaller commented Mar 1, 2019

I think this got broken again at some point? I get an error telling me that the .Type() of the InlineAsm I pass is not a FuncType.

llvm/ir/inst_other.go

Lines 344 to 355 in f20e2cd

t, ok := inst.Callee.Type().(*types.PointerType)
if !ok {
panic(fmt.Errorf("invalid callee type; expected *types.PointerType, got %T", inst.Callee.Type()))
}
sig, ok := t.ElemType.(*types.FuncType)
if !ok {
panic(fmt.Errorf("invalid callee type; expected *types.FuncType, got %T", t.ElemType))
}
if sig.Variadic {
inst.Typ = sig
} else {
inst.Typ = sig.RetType

@pwaller pwaller reopened this Mar 1, 2019
@mewmew
Copy link
Member

mewmew commented Mar 2, 2019

There are many special cases to consider in LLVM IR, I keep learning of new ones even after years of playing with these things. Thanks for re-opening the issue. It seem, the proper solution is to do a type switch and allow a function type directly (to cater for inline asm values).

@mewmew
Copy link
Member

mewmew commented Mar 2, 2019

To be honest, another solution could be to have inline asm values have pointer to function type, instead of function type. How does the official LLVM distribution treat inline asm types? As func type or pointer to func type?

@mewmew
Copy link
Member

mewmew commented Mar 2, 2019

A simple test program that should produce the return code 42.

package main

import (
	"fmt"

	"github.com/llir/llvm/ir"
	"github.com/llir/llvm/ir/constant"
	"github.com/llir/llvm/ir/types"
)

func main() {
	m := ir.NewModule()
	// inline asm
	funcType := types.NewFunc(types.I32, types.I32)
	asm := ir.NewInlineAsm(funcType, "add $1,$0", "=Q,Q,~{dirflag},~{fpsr},~{flags}")
	// main
	main := m.NewFunc("main", types.I32)
	entry := main.NewBlock("")
	result := entry.NewCall(asm, constant.NewInt(types.I32, 21))
	entry.NewRet(result)
	fmt.Println(m)
}
u@x1 ~/D/g/s/p/aa3> go run main.go > b.ll
u@x1 ~/D/g/s/p/aa3> lli b.ll ; echo $status
42

mewmew added a commit to mewpull/llvm that referenced this issue Mar 2, 2019
Prior to this commit, the callee had to be of pointer
to function type (as is the type of functions declared
in the global scope of the module).

However, to allow inline asm values to have function
type instead of pointer to function type, the type
checking of NewCall is relaxed.

Fixes llir#33.
@pwaller
Copy link
Member

pwaller commented Mar 3, 2019

Hmm, I'm uncertain whether my complaint was valid or not. Part of the issue was that I didn't understand how to use inline asm properly. With what you've written above and #74 I'm now happily able to use it. I don't have any strong feelings about how this should work.

@mewmew
Copy link
Member

mewmew commented Mar 4, 2019

Before closing this issue, I still wish we could evaluate how the official LLVM distribution treats the type of inline asm, and then decide to be consistent with that.

This would follow the Principle of Least Surprise, for any user coming from official LLVM to llir/llvm.

@pwaller, do you have the LLVM C++ distribution installed, and if so, could you write a minimal test just to verify if inline asm has pointer to func type or func type?

@dannypsnl
Copy link
Member

Do not have a computer to try now, but I guess https://stackoverflow.com/questions/29184031/how-to-get-llvm-inline-asm-operands-type would help?

@mewmew
Copy link
Member

mewmew commented Mar 4, 2019

@dannypsnl, thanks!

From https://stackoverflow.com/questions/29184031/how-to-get-llvm-inline-asm-operands-type:

In LLVM, InlineAsm is a subclass of Value, and the associated value is always of type pointer-to-function.

So, we can close this issue. And let users create inline asm values with type pointer to function type.

@mewmew mewmew closed this as completed Mar 4, 2019
@pwaller
Copy link
Member

pwaller commented Mar 4, 2019

I added a bullet to the typechecking issue #65 - we should type-check the arg to NewInlineAsm. Also, it would seem reasonable to me for that function to accept either a types.Func or types.Pointer - in the former case simply wrapping the func with types.NewPointer.

@mewmew mewmew added this to the v0.3 milestone Dec 5, 2019
mewmew added a commit that referenced this issue Dec 5, 2019
Note sure when you'd want to call a null function, but since its
valid LLVM IR we should ensure that the null constant has the correct
type, which is pointer to function type for all callees.

An old but related issue #33.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants