Loading context.cpp +29 −12 Original line number Diff line number Diff line Loading @@ -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 ) { Loading Loading @@ -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(); Loading @@ -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; } Loading context.hpp +3 −1 Original line number Diff line number Diff line Loading @@ -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; Loading parser.y +9 −7 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -486,9 +494,6 @@ unary_expr $$ = $2; $$.cat = seagol::Value::LVALUE; } if ( $$.type()->isPointerTy() && $$.type()->getPointerElementType()->isFunctionTy() ) $$.cat.callable = true; } } ; Loading Loading @@ -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 { Loading pointers.glum +8 −0 Original line number Diff line number Diff line Loading @@ -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 ); } semantic.hpp +6 −3 Original line number Diff line number Diff line Loading @@ -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; } Loading Loading
context.cpp +29 −12 Original line number Diff line number Diff line Loading @@ -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 ) { Loading Loading @@ -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(); Loading @@ -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; } Loading
context.hpp +3 −1 Original line number Diff line number Diff line Loading @@ -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; Loading
parser.y +9 −7 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -486,9 +494,6 @@ unary_expr $$ = $2; $$.cat = seagol::Value::LVALUE; } if ( $$.type()->isPointerTy() && $$.type()->getPointerElementType()->isFunctionTy() ) $$.cat.callable = true; } } ; Loading Loading @@ -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 { Loading
pointers.glum +8 −0 Original line number Diff line number Diff line Loading @@ -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 ); }
semantic.hpp +6 −3 Original line number Diff line number Diff line Loading @@ -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; } Loading