Verified Commit e2490fca authored by Adam Matoušek's avatar Adam Matoušek
Browse files

Casts. Do not track callability manually.

parent 15f9eaff
Loading
Loading
Loading
Loading
+29 −12
Original line number Diff line number Diff line
@@ -5,10 +5,10 @@

namespace seagol {

const Value::Category Value::LVALUE = { 1, 0, 1, 0 };
const Value::Category Value::RVALUE = { 0, 0, 0, 0 };
const Value::Category Value::CVALUE = { 0, 1, 0, 0 };
const Value::Category Value::FVALUE = { 1, 0, 0, 1 };
const Value::Category Value::LVALUE = { 1, 0, 1 };
const Value::Category Value::RVALUE = { 0, 0, 0 };
const Value::Category Value::CVALUE = { 0, 1, 0 };
const Value::Category Value::FVALUE = { 1, 0, 0 };

llvm::Type* Context::get_type( typeid_t id )
{
@@ -64,16 +64,14 @@ bool Context::coercible( llvm::Type *from, llvm::Type *to )
    return false;
}

ExprInfo Context::coerce( ExprInfo expr, llvm::Type *to, bool rvalise )
ExprInfo Context::coerce( ExprInfo expr, llvm::Type *to )
{
    if ( !to )
        to = expr.type();

    if ( rvalise && expr.loadable() ) {
    if ( expr.loadable() ) {
        expr.rvalise();
        expr.llval = irb.CreateLoad( expr.llval );
        if ( to->isPointerTy() && to->getPointerElementType()->isFunctionTy() )
            expr.cat.callable = true;
    }

    auto *from = expr.type();
@@ -93,10 +91,29 @@ ExprInfo Context::coerce( ExprInfo expr, llvm::Type *to, bool rvalise )
        }
        expr.rvalise();
    }
    if ( from->isFunctionTy() && to->isPointerTy() &&
            to->getPointerElementType() == from ) {
        expr.cat.callable = 1;
    return expr;
}

bool Context::castable( llvm::Type *from, llvm::Type *to )
{
    if ( coercible( from, to ) )
        return true;
    if ( from->isIntOrPtrTy() && to->isIntOrPtrTy() )
        return true;
    return false;
}

ExprInfo Context::cast( ExprInfo expr, llvm::Type * to )
{
    auto *from = expr.type();
    if ( coercible( from, to ) )
        return coerce( expr, to );

    expr.rvalise();

    if ( from->isIntOrPtrTy() && to->isIntOrPtrTy() )
        expr.llval = irb.CreateBitOrPointerCast( expr.llval, to );

    return expr;
}

+3 −1
Original line number Diff line number Diff line
@@ -32,7 +32,9 @@ struct Context {

    llvm::Type* get_type( typeid_t );
    bool coercible( llvm::Type *, llvm::Type * );
    ExprInfo coerce( ExprInfo, llvm::Type * t = nullptr, bool rvalise = true );
    ExprInfo coerce( ExprInfo, llvm::Type * t = nullptr );
    bool castable( llvm::Type *, llvm::Type * );
    ExprInfo cast( ExprInfo, llvm::Type * );
    bool promotable( ExprInfo, ExprInfo );
    std::pair< ExprInfo, ExprInfo > promote( ExprInfo, ExprInfo );
    std::string format_type( llvm::Type* ) const;
+9 −7
Original line number Diff line number Diff line
@@ -455,7 +455,15 @@ aexpr

cast_expr
    : unary_expr
    | '(' type ')' cast_expr { NOT_IMPLEMENTED(@$) }
    | '(' complete_type[to_type] ')' cast_expr[from_ex] {
        auto *from_type = $from_ex.type();
        if ( ! ctx.castable( from_type, $to_type ) ) {
            error( @$, "invalid cast from `"s + pt( from_type ) +
                    "\' to `" + pt( $to_type ) + '\'' );
        } else {
            $$ = ctx.cast( $from_ex, $to_type );
        }
    }
    ;

unary_expr
@@ -486,9 +494,6 @@ unary_expr
                $$ = $2;
                $$.cat = seagol::Value::LVALUE;
            }
            if ( $$.type()->isPointerTy() &&
                    $$.type()->getPointerElementType()->isFunctionTy() )
                $$.cat.callable = true;
        }
    }
    ;
@@ -558,9 +563,6 @@ primary_expr
            $$.cat = seagol::Value::FVALUE;
        } else {
            $$.cat = seagol::Value::LVALUE;
            if ( $1->type->isPointerTy() &&
                    $1->type->getPointerElementType()->isFunctionTy() )
                $$.cat.callable = true;
        }
    }
    | CONSTANT_I {
+8 −0
Original line number Diff line number Diff line
@@ -34,3 +34,11 @@ int fptr2() {
    f = add;
    return f(5, f(4, 6));
}

void cast( long a ) {
    int x = 42;
    long y = (char) a;
    long *py = &y;
    *(char *) py = 20;
    ((void(*)(int)) &fptr2)( 42 );
}
+6 −3
Original line number Diff line number Diff line
@@ -78,14 +78,17 @@ struct Value {
        uint8_t addressable : 1; // If 1, then then llval is the address
        uint8_t constant    : 1;
        uint8_t assignable  : 1;
        uint8_t callable    : 1;
    } cat;
    bool addressable() const { return cat.addressable; }
    bool loadable() const { return cat.addressable && cat.assignable; }
    bool constant() const { return cat.constant; }
    bool assignable() const { return cat.assignable; }
    bool callable() const { return cat.callable; }
    bool derefable() const { return pointer() || cat.callable; }
    bool callable() const {
        return llvm::isa< llvm::Function >( llval ) ||
                ( type()->isPointerTy() &&
                  type()->getPointerElementType()->isFunctionTy() );
    }
    bool derefable() const { return pointer() || callable(); }
    bool pointer() const { return type()->isPointerTy(); }
    void setCategory( Category category ) { cat = category; }