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

[stdlib] Refactor external_call() and inline _LITRefPackHelper into VariadicPack #3632

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
d529081
refactor external_call and inline _LITRefPackHelper into VariadicPack
martinvuyk Oct 10, 2024
bd00c75
fix details
martinvuyk Oct 10, 2024
e601cf2
Merge branch 'nightly' into add-externalcall-variadicpack-overload
martinvuyk Oct 10, 2024
5ebfeff
fix details
martinvuyk Oct 10, 2024
048985e
Merge branch 'add-externalcall-variadicpack-overload' of github.com:m…
martinvuyk Oct 10, 2024
d37c1d1
fix details
martinvuyk Oct 10, 2024
c1c37b5
fix details
martinvuyk Oct 10, 2024
bfbe7e6
fix details
martinvuyk Oct 10, 2024
47ff4ff
fix details
martinvuyk Oct 10, 2024
44bcb5b
fix details
martinvuyk Oct 10, 2024
62c7b66
delete code as suggested by @soraros
martinvuyk Oct 10, 2024
c70274b
take char_ptr helper to another PR as suggested by @soraros
martinvuyk Oct 10, 2024
3a43fad
Merge remote-tracking branch 'upstream/nightly' into add-externalcall…
martinvuyk Oct 14, 2024
675eefe
fix detail
martinvuyk Oct 14, 2024
c014f1b
Merge branch 'nightly' into add-externalcall-variadicpack-overload
martinvuyk Oct 14, 2024
d9e879f
Merge remote-tracking branch 'upstream/nightly' into add-externalcall…
martinvuyk Oct 21, 2024
6e44e10
Merge branch 'add-externalcall-variadicpack-overload' of github.com:m…
martinvuyk Oct 21, 2024
bd5d75a
fix detail
martinvuyk Oct 21, 2024
c2269eb
fix detail
martinvuyk Oct 21, 2024
d92fa04
Merge remote-tracking branch 'upstream/nightly' into add-externalcall…
martinvuyk Nov 4, 2024
636a466
fix details
martinvuyk Nov 5, 2024
cc56be4
return _litrefpackhelper
martinvuyk Nov 5, 2024
a93b6c7
return _litrefpackhelper to previous state
martinvuyk Nov 5, 2024
359464b
return _litrefpackhelper to previous state
martinvuyk Nov 5, 2024
222d8a5
Merge remote-tracking branch 'upstream/nightly' into add-externalcall…
martinvuyk Nov 6, 2024
67ef981
fix detail
martinvuyk Nov 6, 2024
872a192
retry github CI
martinvuyk Nov 6, 2024
af22094
Merge branch 'nightly' into add-externalcall-variadicpack-overload
martinvuyk Nov 6, 2024
a9d898b
Merge remote-tracking branch 'upstream/nightly' into add-externalcall…
martinvuyk Nov 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 14 additions & 12 deletions stdlib/src/builtin/builtin_list.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -634,45 +634,47 @@ struct VariadicPack[
# C Pack Utilities
# ===-------------------------------------------------------------------===#

# This is the element_types list lowered to `variadic<type>` type for kgen.
alias _kgen_element_types = rebind[
__mlir_type.`!kgen.variadic<!kgen.type>`
](Self.element_types)

# Use variadic_ptr_map to construct the type list of the !kgen.pack that the
# !lit.ref.pack will lower to. It exposes the pointers introduced by the
# references.
"""This is the element_types list lowered to `variadic<type>` type for kgen.
"""
alias _variadic_pointer_types = __mlir_attr[
`#kgen.param.expr<variadic_ptr_map, `,
Self._kgen_element_types,
`, 0: index>: !kgen.variadic<!kgen.type>`,
]

# This is the !kgen.pack type with pointer elements.
"""Use variadic_ptr_map to construct the type list of the !kgen.pack that
the !lit.ref.pack will lower to. It exposes the pointers introduced by the
references.
"""
alias _kgen_pack_with_pointer_type = __mlir_type[
`!kgen.pack<:variadic<type> `, Self._variadic_pointer_types, `>`
]
"""This is the !kgen.pack type with pointer elements."""

# This rebinds `in_pack` to the equivalent `!kgen.pack` with kgen pointers.
@doc_private
@always_inline("nodebug")
fn get_as_kgen_pack(self) -> Self._kgen_pack_with_pointer_type:
"""This rebinds `in_pack` to the equivalent `!kgen.pack` with kgen
pointers."""
return rebind[Self._kgen_pack_with_pointer_type](self._value)

alias _variadic_with_pointers_removed = __mlir_attr[
`#kgen.param.expr<variadic_ptrremove_map, `,
Self._variadic_pointer_types,
`>: !kgen.variadic<!kgen.type>`,
]

# This is the `!kgen.pack` type that happens if one loads all the elements
# of the pack.
alias _loaded_kgen_pack_type = __mlir_type[
`!kgen.pack<:variadic<type> `, Self._variadic_with_pointers_removed, `>`
]
"""This is the `!kgen.pack` type that happens if one loads all the elements
of the pack.
"""

# This returns the stored KGEN pack after loading all of the elements.
@doc_private
@always_inline("nodebug")
fn get_loaded_kgen_pack(self) -> Self._loaded_kgen_pack_type:
"""This returns the stored KGEN pack after loading all of the elements.
"""
return __mlir_op.`kgen.pack.load`(self.get_as_kgen_pack())
54 changes: 24 additions & 30 deletions stdlib/src/builtin/io.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ from sys import (
_libc as libc,
)
from sys._libc import dup, fclose, fdopen, fflush
from sys.ffi import OpaquePointer
from sys.ffi import OpaquePointer, c_char

from utils import Span, write_buffered, write_args
from collections import InlineArray
Expand Down Expand Up @@ -159,19 +159,16 @@ fn _flush(file: FileDescriptor = stdout):
@no_inline
fn _printf[
fmt: StringLiteral, *types: AnyType
](*arguments: *types, file: FileDescriptor = stdout):
# The argument pack will contain references for each value in the pack,
# but we want to pass their values directly into the C printf call. Load
# all the members of the pack.
var loaded_pack = arguments.get_loaded_kgen_pack()
](*args: *types, file: FileDescriptor = stdout):
var loaded_pack = args.get_loaded_kgen_pack()
var f = fmt.unsafe_ptr().bitcast[c_char]()

@parameter
if is_nvidia_gpu():
_ = external_call["vprintf", Int32](
fmt.unsafe_cstr_ptr(), Pointer.address_of(loaded_pack)
)
_ = external_call["vprintf", Int32](f, Pointer.address_of(loaded_pack))
else:
with _fdopen(file) as fd:
# FIXME: external_call should handle this
_ = __mlir_op.`pop.external_call`[
func = "KGEN_CompilerRT_fprintf".value,
variadicType = __mlir_attr[
Expand All @@ -181,7 +178,7 @@ fn _printf[
`) -> !pop.scalar<si32>`,
],
_type=Int32,
](fd, fmt.unsafe_cstr_ptr(), loaded_pack)
](fd, f, loaded_pack)


# ===----------------------------------------------------------------------=== #
Expand All @@ -192,7 +189,7 @@ fn _printf[
@no_inline
fn _snprintf[
fmt: StringLiteral, *types: AnyType
](str: UnsafePointer[UInt8], size: Int, *arguments: *types) -> Int:
](str: UnsafePointer[UInt8], size: Int, *args: *types) -> Int:
"""Writes a format string into an output pointer.

Parameters:
Expand All @@ -202,29 +199,26 @@ fn _snprintf[
Args:
str: A pointer into which the format string is written.
size: At most, `size - 1` bytes are written into the output string.
arguments: Arguments interpolated into the format string.
args: Arguments interpolated into the format string.

Returns:
The number of bytes written into the output string.
"""
# The argument pack will contain references for each value in the pack,
# but we want to pass their values directly into the C snprintf call. Load
# all the members of the pack.
var loaded_pack = arguments.get_loaded_kgen_pack()

return int(
__mlir_op.`pop.external_call`[
func = "snprintf".value,
variadicType = __mlir_attr[
`(`,
`!kgen.pointer<scalar<si8>>,`,
`!pop.scalar<index>, `,
`!kgen.pointer<scalar<si8>>`,
`) -> !pop.scalar<si32>`,
],
_type=Int32,
](str, size, fmt.unsafe_cstr_ptr(), loaded_pack)
)

# FIXME: external_call should handle this
var f = fmt.unsafe_ptr().bitcast[c_char]()
var num = __mlir_op.`pop.external_call`[
func = "snprintf".value,
variadicType = __mlir_attr[
`(`,
`!kgen.pointer<scalar<si8>>,`,
`!pop.scalar<index>, `,
`!kgen.pointer<scalar<si8>>`,
`) -> !pop.scalar<si32>`,
],
_type=Int32,
](str.bitcast[c_char](), size, f, args.get_loaded_kgen_pack())
return int(num)


# ===----------------------------------------------------------------------=== #
Expand Down
4 changes: 2 additions & 2 deletions stdlib/src/sys/_assembly.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ fn inlined_assembly[
*types: AnyType,
constraints: StringLiteral,
has_side_effect: Bool = True,
](*arguments: *types) -> result_type:
](*args: *types) -> result_type:
"""Generates assembly via inline assembly."""
var loaded_pack = arguments.get_loaded_kgen_pack()
var loaded_pack = args.get_loaded_kgen_pack()

@parameter
if _mlirtype_is_eq[result_type, NoneType]():
Expand Down
70 changes: 39 additions & 31 deletions stdlib/src/sys/ffi.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -467,39 +467,52 @@ fn _get_global_or_null[name: StringLiteral]() -> OpaquePointer:
# ===----------------------------------------------------------------------===#


@always_inline("nodebug")
@always_inline
fn external_call[
callee: StringLiteral, type: AnyTrivialRegType, *types: AnyType
](*arguments: *types) -> type:
callee: StringLiteral, return_type: AnyTrivialRegType, *T: AnyType
](*args: *T) -> return_type:
"""Calls an external function.

Args:
arguments: The arguments to pass to the external function.
args: The arguments to pass to the external function.

Parameters:
callee: The name of the external function.
type: The return type.
types: The argument types.
callee: The name of the external function.
return_type: The return type.
T: The argument types.

Returns:
The external call result.
The external call result.
"""
return external_call[callee, return_type](args)

# The argument pack will contain references for each value in the pack,
# but we want to pass their values directly into the C printf call. Load
# all the members of the pack.
var loaded_pack = arguments.get_loaded_kgen_pack()

@always_inline("nodebug")
fn external_call[
callee: StringLiteral, return_type: AnyTrivialRegType
](args: VariadicPack[element_trait=AnyType]) -> return_type:
"""Calls an external function.

Parameters:
callee: The name of the external function.
return_type: The return type.

Args:
args: The arguments to pass to the external function.

Returns:
The external call result.
"""
var p = args.get_loaded_kgen_pack()

@parameter
if _mlirtype_is_eq[type, NoneType]():
__mlir_op.`pop.external_call`[func = callee.value, _type=None](
loaded_pack
)
return rebind[type](None)
if _mlirtype_is_eq[return_type, NoneType]():
__mlir_op.`pop.external_call`[func = callee.value, _type=None](p)
return rebind[return_type](None)
else:
return __mlir_op.`pop.external_call`[func = callee.value, _type=type](
loaded_pack
)
return __mlir_op.`pop.external_call`[
func = callee.value, _type=return_type
](p)


# ===----------------------------------------------------------------------===#
Expand All @@ -509,29 +522,24 @@ fn external_call[

@always_inline("nodebug")
fn _external_call_const[
callee: StringLiteral, type: AnyTrivialRegType, *types: AnyType
](*arguments: *types) -> type:
callee: StringLiteral, return_type: AnyTrivialRegType, *types: AnyType
](*args: *types) -> return_type:
"""Mark the external function call as having no observable effects to the
program state. This allows the compiler to optimize away successive calls
to the same function.

Args:
arguments: The arguments to pass to the external function.
args: The arguments to pass to the external function.

Parameters:
callee: The name of the external function.
type: The return type.
return_type: The return type.
types: The argument types.

Returns:
The external call result.
"""

# The argument pack will contain references for each value in the pack,
# but we want to pass their values directly into the C printf call. Load
# all the members of the pack.
var loaded_pack = arguments.get_loaded_kgen_pack()

return __mlir_op.`pop.external_call`[
func = callee.value,
resAttrs = __mlir_attr.`[{llvm.noundef}]`,
Expand All @@ -541,5 +549,5 @@ fn _external_call_const[
`argMem = none, `,
`inaccessibleMem = none>`,
],
_type=type,
](loaded_pack)
_type=return_type,
](args.get_loaded_kgen_pack())
21 changes: 10 additions & 11 deletions stdlib/src/sys/intrinsics.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -36,25 +36,24 @@ fn llvm_intrinsic[
type: AnyTrivialRegType,
*types: AnyType,
has_side_effect: Bool = True,
](*arguments: *types) -> type:
"""Calls an LLVM intrinsic with no arguments.

Calls an LLVM intrinsic with the name intrin and return type type.
](*args: *types) -> type:
"""Calls an LLVM intrinsic with the name intrin and return type `type`.

Parameters:
intrin: The name of the llvm intrinsic.
type: The return type of the intrinsic.
types: The argument types for the function.
has_side_effect: If `True` the intrinsic will have side effects, otherwise its pure.
intrin: The name of the llvm intrinsic.
type: The return type of the intrinsic.
types: The argument types for the function.
has_side_effect: If `True` the intrinsic will have side effects,
otherwise its pure.

Args:
arguments: The arguments to the function.
args: The arguments to the function.

Returns:
The result of calling the llvm intrinsic with no arguments.
The result of calling the llvm intrinsic with no arguments.
"""

var loaded_pack = arguments.get_loaded_kgen_pack()
var loaded_pack = args.get_loaded_kgen_pack()

@parameter
if _mlirtype_is_eq[type, NoneType]():
Expand Down