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 10 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
106 changes: 37 additions & 69 deletions stdlib/src/builtin/builtin_list.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -463,23 +463,30 @@ struct VariadicListMem[


# ===----------------------------------------------------------------------===#
# _LITRefPackHelper
# VariadicPack
# ===----------------------------------------------------------------------===#


alias _AnyTypeMetaType = __mlir_type[`!lit.anytrait<`, AnyType, `>`]


@value
struct _LITRefPackHelper[
is_mutable: Bool, //,
lifetime: Lifetime[is_mutable].type,
address_space: __mlir_type.index,
martinvuyk marked this conversation as resolved.
Show resolved Hide resolved
@register_passable
struct VariadicPack[
elt_is_mutable: __mlir_type.i1, //,
lifetime: Lifetime[Bool {value: elt_is_mutable}].type,
element_trait: _AnyTypeMetaType,
*element_types: element_trait,
]:
"""This struct mirrors the !lit.ref.pack type, and provides aliases and
methods that are useful for working with it."""
](Sized):
"""A utility class to access variadic pack arguments and provide an API for
doing things with them.

Parameters:
elt_is_mutable: True if the elements of the list are mutable for an
inout or owned argument pack.
lifetime: The reference lifetime of the underlying elements.
element_trait: The trait that each element of the pack conforms to.
element_types: The list of types held by the argument pack.
"""

alias _mlir_type = __mlir_type[
`!lit.ref.pack<:variadic<`,
Expand All @@ -488,89 +495,42 @@ struct _LITRefPackHelper[
element_types,
`, `,
lifetime,
`, `,
address_space,
`>`,
]

var storage: Self._mlir_type
var _value: Self._mlir_type
var _is_owned: Bool

# 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.
alias kgen_pack_with_pointer_type = __mlir_type[
"""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 rebinds `in_pack` to the equivalent `!kgen.pack` with kgen pointers.
fn get_as_kgen_pack(self) -> Self.kgen_pack_with_pointer_type:
return rebind[Self.kgen_pack_with_pointer_type](self.storage)

"""This is the !kgen.pack type with pointer elements."""
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[
alias _loaded_kgen_pack_type = __mlir_type[
`!kgen.pack<:variadic<type> `, Self._variadic_with_pointers_removed, `>`
]

# This returns the stored KGEN pack after loading all of the elements.
fn get_loaded_kgen_pack(self) -> Self.loaded_kgen_pack_type:
return __mlir_op.`kgen.pack.load`(self.get_as_kgen_pack())


# ===----------------------------------------------------------------------===#
# VariadicPack
# ===----------------------------------------------------------------------===#


@register_passable
struct VariadicPack[
elt_is_mutable: __mlir_type.i1, //,
lifetime: Lifetime[Bool {value: elt_is_mutable}].type,
element_trait: _AnyTypeMetaType,
*element_types: element_trait,
](Sized):
"""A utility class to access variadic pack arguments and provide an API for
doing things with them.

Parameters:
elt_is_mutable: True if the elements of the list are mutable for an
inout or owned argument pack.
lifetime: The reference lifetime of the underlying elements.
element_trait: The trait that each element of the pack conforms to.
element_types: The list of types held by the argument pack.
"""This is the `!kgen.pack` type that happens if one loads all the elements
of the pack.
"""

alias _mlir_type = __mlir_type[
`!lit.ref.pack<:variadic<`,
element_trait,
`> `,
element_types,
`, `,
lifetime,
`>`,
]

var _value: Self._mlir_type
var _is_owned: Bool

# ===-------------------------------------------------------------------===#
# Life cycle methods
# ===-------------------------------------------------------------------===#
Expand Down Expand Up @@ -690,3 +650,11 @@ struct VariadicPack[
@parameter
for i in range(Self.__len__()):
func[i](self[i])

@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`(
rebind[Self._kgen_pack_with_pointer_type](self._value)
)
53 changes: 22 additions & 31 deletions stdlib/src/builtin/io.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@ from sys import (
_libc as libc,
)
from sys._libc import dup, fclose, fdopen, fflush
from sys.ffi import OpaquePointer
from sys.ffi import OpaquePointer, char_ptr

from builtin.builtin_list import _LITRefPackHelper
from builtin.dtype import _get_dtype_printf_format
from builtin.file_descriptor import FileDescriptor
from memory import UnsafePointer
Expand Down Expand Up @@ -158,19 +157,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 = _LITRefPackHelper(arguments._value).get_loaded_kgen_pack()
](*args: *types, file: FileDescriptor = stdout):
var loaded_pack = args._get_loaded_kgen_pack()
var f = char_ptr(fmt)

@parameter
if triple_is_nvidia_cuda():
_ = 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: externall_call should handle this
_ = __mlir_op.`pop.external_call`[
func = "KGEN_CompilerRT_fprintf".value,
variadicType = __mlir_attr[
Expand All @@ -180,7 +176,7 @@ fn _printf[
`) -> !pop.scalar<si32>`,
],
_type=Int32,
](fd, fmt.unsafe_cstr_ptr(), loaded_pack)
](fd, f, loaded_pack)


# ===----------------------------------------------------------------------=== #
Expand All @@ -191,7 +187,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 @@ -201,29 +197,24 @@ 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 = _LITRefPackHelper(arguments._value).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: externall_call should handle this
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,
](char_ptr(str), size, char_ptr(fmt), args._get_loaded_kgen_pack())
return int(num)


@no_inline
Expand Down
5 changes: 2 additions & 3 deletions stdlib/src/sys/_assembly.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
"""This module includes the inlined_assembly function."""

from sys.intrinsics import _mlirtype_is_eq
from builtin.builtin_list import _LITRefPackHelper

# ===----------------------------------------------------------------------===#
# 0-arg
Expand All @@ -27,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 = _LITRefPackHelper(arguments._value).get_loaded_kgen_pack()
var loaded_pack = args._get_loaded_kgen_pack()

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