#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();
}
}