Goose  Artifact [48fd7d38c4]

Artifact 48fd7d38c454efddf78e7c1e8ade3ea1cde36f2cc30d784b70a2d52e8dcaa0b2:

  • File bs/builtins/types/runtime/basic.cpp — part of check-in [b2945b5bb1] at 2021-03-05 17:56:37 on branch trunk — Implemented refinement type predicate unification. Predicate violations by variable initialization are now properly detected. (user: achavasse size: 7082)

#include "builtins/builtins.h"
#include "codegen/codegen.h"
#include "builtins/helpers.h"

using namespace goose;
using namespace goose::builtins;
using namespace goose::codegen;

namespace goose::builtins
{
    void SetupRuntimeBasicTypes( Env& e )
    {
        e.storeValue( AppendToVectorTerm( RootIdentity(), TSID( half ) ), ANYTERM( _ ), ValueToEIR( ToValue( HalfFloatType() ) ) );
        e.storeValue( AppendToVectorTerm( RootIdentity(), TSID( float ) ), ANYTERM( _ ), ValueToEIR( ToValue( FloatType() ) ) );
        e.storeValue( AppendToVectorTerm( RootIdentity(), TSID( double ) ), ANYTERM( _ ), ValueToEIR( ToValue( DoubleFloatType() ) ) );

        RegisterBuiltinFunc< Eager< Value > ( uint32_t ) >( e, "uint"_sid,
            []( uint32_t numBits )
            {
                return ToValue( IntegerType( numBits ) );
            } );

        RegisterBuiltinFunc< Eager< Value > ( uint32_t ) >( e, "sint"_sid,
            []( uint32_t numBits )
            {
                return ToValue( IntegerType( numBits, true ) );
            } );
    }

    const Term& IntegerType::Pattern::GetPattern()
    {
        static auto pattern = ValueToEIR( Value( TypeType(), MkStdRTType( TSID( integer ),
            nullptr,
            VEC( HOLE( "size"_sid ), HOLE( "signedness"_sid ) ) ) ) );

        return pattern;
    }

    const Term& IntegerType::PatternSigned::GetPattern()
    {
        static auto pattern = ValueToEIR( Value( TypeType(), MkStdRTType( TSID( integer ),
            nullptr,
            VEC( HOLE( "size"_sid ), TERM( 1U ) ) ) ) );

        return pattern;
    }

    const Term& IntegerType::PatternUnsigned::GetPattern()
    {
        static auto pattern = ValueToEIR( Value( TypeType(), MkStdRTType( TSID( integer ),
            nullptr,
            VEC( HOLE( "size"_sid ), TERM( 0U ) ) ) ) );

        return pattern;
    }

    const Term& IntegerType::PatternUnsigned32::GetPattern()
    {
        static auto pattern = ValueToEIR( Value( TypeType(), MkStdRTType( TSID( integer ),
            nullptr,
            VEC( TERM( 32U ), TERM( 0U ) ) ) ) );

        return pattern;
    }

    llvm::Type* GetLLVMType( const HalfFloatType& t )
    {
        return llvm::Type::getHalfTy( GetLLVMContext() );
    }

    llvm::Type* GetLLVMType( const FloatType& t )
    {
        return llvm::Type::getFloatTy( GetLLVMContext() );
    }

    llvm::Type* GetLLVMType( const DoubleFloatType& t )
    {
        return llvm::Type::getDoubleTy( GetLLVMContext() );
    }

    llvm::Type* GetLLVMType( const IntegerType& t )
    {
        return llvm::IntegerType::get( GetLLVMContext(), t.m_numBits );
    }
}

namespace goose::eir
{
    //// Half
    Value Bridge< HalfFloatType >::ToValue( const HalfFloatType& t )
    {
        return Value( Type(), MkStdRTType( TSID( half ), GetLLVMType( t ) ) );
    }

    optional< HalfFloatType > Bridge< HalfFloatType >::FromValue( const Value& v )
    {
        if( v != ToValue( HalfFloatType() ) )
            return nullopt;

        return {};
    }

    //// Float
    Value Bridge< FloatType >::ToValue( const FloatType& t )
    {
        return Value( Type(), MkStdRTType( TSID( float ), GetLLVMType( t ) ) );
    }

    optional< FloatType > Bridge< FloatType >::FromValue( const Value& v )
    {
        if( v != ToValue( FloatType() ) )
            return nullopt;

        return {};
    }

    //// Double
    Value Bridge< DoubleFloatType >::ToValue( const DoubleFloatType& t )
    {
        return Value( Type(), MkStdRTType( TSID( double ), GetLLVMType( t ) ) );
    }

    optional< DoubleFloatType > Bridge< DoubleFloatType >::FromValue( const Value& v )
    {
        if( v != ToValue( DoubleFloatType() ) )
            return nullopt;

        return {};
    }

    //// Integer
    Value Bridge< IntegerType >::ToValue( const IntegerType& t )
    {
        return Value( Type(), MkStdRTType( TSID( integer ), GetLLVMType( t ),
            VEC( TERM( t.m_numBits ), t.m_signed ? TERM( 1U ) : TERM( 0U ) ) ) );
    }

    optional< IntegerType > Bridge< IntegerType >::FromValue( const Value& v )
    {
        auto result = Decompose( v.val(),
            Vec(
                Lit( "integer"_sid ),
                SubTerm(),
                Val< void* >(),
                Vec(
                    Val< uint32_t >(),
                    Val< uint32_t >()
                )
            )
        );

        if( !result )
            return nullopt;

        auto&& [predicates, llvmType, params] = *result;
        auto&& [numBits, signd] = params;
        return IntegerType( numBits, !!signd );
    }

    Term Bridge< APSInt >::Type( const APSInt& i )
    {
        return ValueToEIR( eir::ToValue(
            IntegerType( i.getBitWidth(), i.isSigned() ) ) );
    }

    Value Bridge< APSInt >::ToValue( const APSInt& i )
    {
        return Value( Type( i ), TERM( i ) );
    }

    optional< APSInt > Bridge< APSInt >::FromValue( const Value& v )
    {
        {
            auto result = Decompose( v.val(),
                Val< APSInt >()
            );

            if( result )
                return *result;
        }

        {
            auto result = Decompose( v.val(),
                Val< BigInt >()
            );

            if( result )
            {
                auto intType = *FromValue< IntegerType >( *ValueFromEIR( v.type() ) );

                if( intType.m_signed )
                    return APSInt( result->get().getAPSInt().sextOrTrunc( intType.m_numBits ), false );
                else
                    return APSInt( result->get().getAPSInt().zextOrTrunc( intType.m_numBits ), true );
            }
        }

        return nullopt;
    }


    const Term& Bridge< uint8_t >::Type()
    {
        static auto type = ValueToEIR( eir::ToValue(
            IntegerType( 8, false ) ) );
        return type;
    }

    Value Bridge< uint8_t >::ToValue( uint8_t x )
    {
        return eir::ToValue( APSInt::getUnsigned( x ).trunc( 8 ) );
    }

    optional< uint8_t > Bridge< uint8_t >::FromValue( const Value& v )
    {
        return FromValue< APSInt >( v )->getLimitedValue();
    }


    const Term& Bridge< uint32_t >::Type()
    {
        static auto type = ValueToEIR( eir::ToValue(
            IntegerType( 32, false ) ) );
        return type;
    }

    Value Bridge< uint32_t >::ToValue( uint32_t x )
    {
        return eir::ToValue( APSInt::getUnsigned( x ).trunc( 32 ) );
    }

    optional< uint32_t > Bridge< uint32_t >::FromValue( const Value& v )
    {
        return FromValue< APSInt >( v )->getLimitedValue();
    }


    const Term& Bridge< uint64_t >::Type()
    {
        static auto type = ValueToEIR( eir::ToValue(
            IntegerType( 64, false ) ) );
        return type;
    }

    Value Bridge< uint64_t >::ToValue( uint64_t x )
    {
        return eir::ToValue( APSInt::getUnsigned( x ) );
    }

    optional< uint64_t > Bridge< uint64_t >::FromValue( const Value& v )
    {
        if( !v.isConstant() )
            return nullopt;
        return FromValue< APSInt >( v )->getLimitedValue();
    }
}