void DoShift( void ) { stack_entry *left; int shift; left = StkEntry( 1 ); RValue( ExprSP ); ConvertTo( ExprSP, TK_INTEGER, TM_SIGNED, 0 ); shift = I32FetchTrunc( ExprSP->v.sint ); RValue( left ); switch( left->info.kind ) { case TK_BOOL: case TK_ENUM: case TK_CHAR: case TK_INTEGER: if( shift >= 0 ) { U64ShiftL( &left->v.uint, shift, &left->v.uint ); } else if( (left->info.modifier & TM_MOD_MASK) == TM_UNSIGNED ) { U64ShiftR( &left->v.uint, -shift, &left->v.uint ); } else { I64ShiftR( &left->v.sint, -shift, &left->v.sint ); } break; default: Error( ERR_NONE, LIT_ENG( ERR_ILL_TYPE ) ); break; } CombineEntries( left, left, ExprSP ); }
RValue Inst::Deref(CodeContext& context, RValue value, bool recursive) { auto retVal = RValue(value.value(), value.stype()); while (retVal.stype()->isPointer()) { retVal = RValue(new LoadInst(retVal, "", context), retVal.stype()->subType()); if (!recursive) break; } return retVal; }
/* ApplyBinary - apply a binary operator to operands */ static void ApplyBinary(EvalState *c, int op, PVAL *left, PVAL *right) { RValue(c, right); if (op == '=') { if (left->type != TYPE_VARIABLE) Error(c, "expecting a variable to the left of '='"); left->v.var->value = right->v.value; left->v.var->bound = TRUE; left->type = TYPE_NUMBER; left->v.value = right->v.value; } else { RValue(c, left); switch (op) { case '|': left->v.value = (VALUE)((int)left->v.value | (int)right->v.value); break; case '^': left->v.value = (VALUE)((int)left->v.value ^ (int)right->v.value); break; case '&': left->v.value = (VALUE)((int)left->v.value & (int)right->v.value); break; case TKN_SHL: left->v.value = (VALUE)((int)left->v.value << (int)right->v.value); break; case TKN_SHR: left->v.value = (VALUE)((int)left->v.value >> (int)right->v.value); break; case '+': left->v.value += right->v.value; break; case '-': left->v.value -= right->v.value; break; case '*': left->v.value *= right->v.value; break; case '/': if ((int)right->v.value == 0) Error(c, "division by zero"); left->v.value /= right->v.value; break; case '%': if ((int)left->v.value == 0) Error(c, "division by zero"); left->v.value = (VALUE)((int)left->v.value % (int)right->v.value); break; default: Error(c, "internal error in ApplyFunction -- '%c' (%d)", op, op); break; } } }
RValue Inst::Cmp(int type, RValue lhs, RValue rhs, CodeContext& context) { if (CastMatch(context, lhs, rhs)) return RValue(); auto pred = getPredicate(type, lhs.stype(), context); auto cmpType = lhs.stype()->isVec()? lhs.stype()->subType() : lhs.stype(); auto op = cmpType->isFloating()? Instruction::FCmp : Instruction::ICmp; auto cmp = CmpInst::Create(op, pred, lhs, rhs, "", context); auto retType = lhs.stype()->isVec()? SType::getVec(context, SType::getBool(context), lhs.stype()->size()) : SType::getBool(context); return RValue(cmp, retType); }
RValue Inst::SizeOf(CodeContext& context, SType* type) { if (!type) { return RValue(); } else if (type->isAuto()) { context.addError("size of auto is invalid"); return RValue(); } else if (type->isVoid()) { context.addError("size of void is invalid"); return RValue(); } auto itype = SType::getInt(context, 64, true); auto size = ConstantInt::get(*itype, SType::allocSize(context, type)); return RValue(size, itype); }
void Pdb::Explorer() { VectorMap<String, Value> prev = DataMap(explorer); explorer.Clear(); try { String x = ~expexp; if(!IsNull(x)) { CParser p(x); Val v = Exp(p); Vis(explorer, "=", prev, Visualise(v)); if(v.type >= 0 && v.ref == 0 && !v.rvalue) Explore(v, prev); if(v.ref > 0 && GetRVal(v).address) for(int i = 0; i < 20; i++) Vis(explorer, Format("[%d]", i), prev, Visualise(DeRef(Compute(v, RValue(i), '+')))); } } catch(CParser::Error e) { Visual v; v.Cat(e, LtRed); explorer.Add("", RawPickToValue(v)); } exback.Enable(exprev.GetCount()); exfw.Enable(exnext.GetCount()); }
static int EndTry( void ) { int parent_scope; TREEPTR expr; TREEPTR func; TREEPTR tree; TYPEPTR typ; int expr_type; DropBreakLabel(); /* _leave jumps to this label */ parent_scope = BlockStack->parent_index; tree = LeafNode( OPR_TRY ); tree->op.st.try_index = BlockStack->try_index; tree->op.st.parent_scope = parent_scope; AddStmt( tree ); if( (CurToken == T__EXCEPT) || (CurToken == T___EXCEPT) ) { NextToken(); BlockStack->block_type = T__EXCEPT; BlockStack->break_label = NextLabel(); Jump( BlockStack->break_label ); DeadCode = 0; tree = LeafNode( OPR_EXCEPT ); tree->op.st.try_sym_handle = DummyTrySymbol(); tree->op.st.parent_scope = parent_scope; AddStmt( tree ); CompFlags.exception_filter_expr = 1; expr = RValue( BracketExpr() ); CompFlags.exception_filter_expr = 0; CompFlags.exception_handler = 1; typ = TypeOf( expr ); expr_type = DataTypeOf( typ ); if( expr_type != TYPE_VOID ) { if( expr_type > TYPE_ULONG ) { CErr1( ERR_EXPR_MUST_BE_INTEGRAL ); } } func = VarLeaf( SymGetPtr( SymExcept ), SymExcept ); func->op.opr = OPR_FUNCNAME; expr = ExprNode( NULL, OPR_PARM, expr ); expr->expr_type = typ; expr->op.result_type = typ; tree = ExprNode( func, OPR_CALL, expr ); tree->expr_type = GetType( TYPE_VOID ); AddStmt( tree ); return( 1 ); } else if( (CurToken == T__FINALLY) || (CurToken == T___FINALLY) ) { CompFlags.in_finally_block = 1; NextToken(); BlockStack->block_type = T__FINALLY; DeadCode = 0; tree = LeafNode( OPR_FINALLY ); tree->op.st.try_sym_handle = DummyTrySymbol(); tree->op.st.parent_scope = parent_scope; AddStmt( tree ); return( 1 ); } return( 0 ); }
RValue Inst::PointerMath(int type, RValue ptr, RValue val, CodeContext& context) { if (type != ParserBase::TT_INC && type != ParserBase::TT_DEC) { context.addError("pointer arithmetic only valid using ++/-- operators"); return ptr; } auto ptrVal = GetElementPtrInst::Create(ptr, val.value(), "", context); return RValue(ptrVal, ptr.stype()); }
void DoPlus( void ) { stack_entry *left; left = StkEntry( 1 ); LRValue( left ); RValue( ExprSP ); switch( ExprSP->info.kind ) { case TK_POINTER: case TK_ADDRESS: /* get the pointer as the left operand */ left = ExprSP; SwapStack( 1 ); } AddOp( left, ExprSP ); switch( left->info.kind ) { case TK_BOOL: case TK_ENUM: case TK_CHAR: case TK_INTEGER: U64Add( &left->v.uint, &ExprSP->v.uint, &left->v.uint ); break; case TK_POINTER: case TK_ADDRESS: switch( ExprSP->info.kind ) { case TK_BOOL: case TK_ENUM: case TK_CHAR: case TK_INTEGER: break; default: Error( ERR_NONE, LIT_ENG( ERR_ILL_TYPE ) ); } if( (left->info.modifier & TM_MOD_MASK) == TM_NEAR ) { //NYI: 64 bit offsets left->v.addr.mach.offset += U32FetchTrunc( ExprSP->v.uint ); } else { //NYI: 64 bit offsets left->v.addr = AddrAdd( left->v.addr, U32FetchTrunc( ExprSP->v.uint ) ); } break; case TK_REAL: LDAdd( &left->v.real, &ExprSP->v.real, &left->v.real ); break; case TK_COMPLEX: LDAdd( &left->v.cmplx.re, &ExprSP->v.cmplx.re, &left->v.cmplx.re ); LDAdd( &left->v.cmplx.im, &ExprSP->v.cmplx.im, &left->v.cmplx.im ); break; default: Error( ERR_NONE, LIT_ENG( ERR_ILL_TYPE ) ); break; } CombineEntries( left, left, ExprSP ); }
void ExprValue( stack_entry *entry ) { ExprResolve( entry ); AddressExpression( entry ); switch( entry->info.kind ) { case TK_STRUCT: case TK_ARRAY: break; default: RValue( entry ); } }
void DoMinus( void ) { stack_entry *left; left = StkEntry( 1 ); LRValue( left ); RValue( ExprSP ); AddOp( left, ExprSP ); switch( left->info.kind ) { case TK_BOOL: case TK_ENUM: case TK_CHAR: case TK_INTEGER: U64Sub( &left->v.uint, &ExprSP->v.uint, &left->v.uint ); left->info.modifier = TM_SIGNED; break; case TK_POINTER: case TK_ADDRESS: switch( ExprSP->info.kind ) { case TK_BOOL: case TK_CHAR: case TK_ENUM: case TK_INTEGER: //NYI: 64 bit offsets left->v.addr = AddrAdd( left->v.addr, -U32FetchTrunc( ExprSP->v.uint ) ); break; case TK_POINTER: case TK_ADDRESS: I32ToI64( AddrDiff( left->v.addr, ExprSP->v.addr ), &left->v.sint ); left->info.kind = TK_INTEGER; left->info.modifier = TM_SIGNED; left->info.size = sizeof( signed_64 ); left->th = NULL; break; default: Error( ERR_NONE, LIT_ENG( ERR_ILL_TYPE ) ); } break; case TK_REAL: LDSub( &left->v.real, &ExprSP->v.real, &left->v.real ); break; case TK_COMPLEX: LDSub( &left->v.cmplx.re, &ExprSP->v.cmplx.re, &left->v.cmplx.re ); LDSub( &left->v.cmplx.im, &ExprSP->v.cmplx.im, &left->v.cmplx.im ); break; default: Error( ERR_NONE, LIT_ENG( ERR_ILL_TYPE ) ); break; } CombineEntries( left, left, ExprSP ); }
static void SwitchStmt( void ) { SWITCHPTR sw; TREEPTR tree; TYPEPTR typ; int switch_type; StartNewBlock(); NextToken(); sw = (SWITCHPTR)CMemAlloc( sizeof( SWITCHDEFN ) ); sw->prev_switch = SwitchStack; sw->low_value = ~0l; sw->high_value = 0; sw->case_format = "%ld"; /* assume signed cases */ SwitchStack = sw; switch_type = TYPE_INT; /* assume int */ tree = RValue( BracketExpr() ); typ = TypeOf( tree ); if( typ->decl_type == TYPE_ENUM ) typ = typ->object; if( typ->decl_type == TYPE_UFIELD ) { if( typ->u.f.field_width == (TARGET_INT * 8) ) { sw->case_format = "%lu"; switch_type = TYPE_UINT; } } switch( typ->decl_type ) { case TYPE_USHORT: case TYPE_UINT: sw->case_format = "%lu"; switch_type = TYPE_UINT; case TYPE_CHAR: case TYPE_UCHAR: case TYPE_SHORT: case TYPE_INT: case TYPE_FIELD: case TYPE_UFIELD: break; case TYPE_ULONG: sw->case_format = "%lu"; switch_type = TYPE_ULONG; break; case TYPE_LONG: switch_type = TYPE_LONG; break; default: CErr1( ERR_INVALID_TYPE_FOR_SWITCH ); } tree = ExprNode( 0, OPR_SWITCH, tree ); tree->op.switch_info = sw; AddStmt( tree ); }
RValue Inst::BinaryOp(int type, RValue lhs, RValue rhs, CodeContext& context) { if (!lhs || !rhs) return RValue(); if (CastMatch(context, lhs, rhs, true)) return RValue(); switch ((lhs.stype()->isPointer() << 1) | rhs.stype()->isPointer()) { default: case 0: // no pointer { auto llvmOp = getOperator(type, lhs.stype(), context); return RValue(BinaryOperator::Create(llvmOp, lhs, rhs, "", context), lhs.stype()); } case 1: // lhs != ptr, rhs == ptr swap(lhs, rhs); case 2: // lhs == ptr, rhs != ptr return PointerMath(type, lhs, rhs, context); case 3: // both ptr context.addError("can't perform operation with two pointers"); return lhs; } }
/* PopAndEvaluate - pop operators and apply them until a '(' or TKN_FCALL token is found */ static int PopAndEvaluate(EvalState *c) { int tkn; for (;;) { if (oStackIsEmpty(c)) Error(c, "mismatched parens"); if ((tkn = oStackTop(c)) == '(' || tkn == TKN_FCALL_ARGS) break; oStackDrop(c); Apply(c, tkn); } RValue(c, c->rStackPtr); if (tkn == TKN_FCALL_ARGS) ++c->argc; return tkn; }
/* ApplyUnary - apply a unary operator to an operand */ static void ApplyUnary(EvalState *c, int op, PVAL *pval) { RValue(c, pval); switch (op) { case TKN_UNARY_MINUS: pval->v.value = -pval->v.value; break; case '~': pval->v.value = (VALUE)~((int)pval->v.value); break; case TKN_FCALL: case TKN_FCALL_ARGS: break; default: Error(c, "internal error in UnaryApply -- '%c' (%d)", op, op); break; } }
static void DoMinusScaled( void ) { stack_entry *left; left = StkEntry( 1 ); LRValue( left ); RValue( ExprSP ); switch( left->info.kind ) { case TK_POINTER: switch( ExprSP->info.kind ) { case TK_POINTER: /* Have to check if base type sizes are the same */ PushBaseSize(); DupStack(); SwapStack( 3 ); PushBaseSize(); MoveSP( 1 ); SwapStack( 3 ); MoveSP( -1 ); if( !TstEQ( 1 ) ) { Error( ERR_NONE, LIT( ERR_ILL_TYPE ) ); } PopEntry(); MoveSP( 1 ); DoMinus(); MoveSP( -1 ); DoDiv(); return; default: ScaleInt(); break; } break; default: switch( ExprSP->info.kind ) { case TK_POINTER: Error( ERR_NONE, LIT( ERR_ILL_TYPE ) ); break; } } DoMinus(); }
static void ReturnStmt( SYM_HANDLE func_result, struct return_info *info ) { TREEPTR tree; BLOCKPTR block; enum return_with with; NextToken(); if( CurToken != T_SEMI_COLON ) { TYPEPTR func_type; func_type = CurFunc->sym_type->object; SKIP_TYPEDEFS( func_type ); tree = RValue( Expr() ); ChkRetType( tree ); tree = BoolConv( func_type, tree ); tree = FixupAss( tree, func_type ); tree = ExprNode( 0, OPR_RETURN, tree ); tree->expr_type = func_type; tree->op.sym_handle = func_result; AddStmt( tree ); with = RETURN_WITH_EXPR; info->with_expr = TRUE; } else { with = RETURN_WITH_NO_EXPR; } if( info->with == RETURN_WITH_NONE ) { info->with = with; } if( info->with != with ) { CErr1( ERR_INCONSISTENT_USE_OF_RETURN ); } block = BlockStack; /* 16-apr-94 */ while( block != NULL ) { if( (block->block_type == T__TRY) || (block->block_type == T___TRY) ) break; block = block->prev_block; } if( block != NULL ) { UnWindTry( -1 ); } }
static void DoPlusScaled( void ) { stack_entry *left; left = StkEntry( 1 ); LRValue( left ); RValue( ExprSP ); switch( left->info.kind ) { case TK_POINTER: ScaleInt(); break; default: switch( ExprSP->info.kind ) { case TK_POINTER: SwapStack( 1 ); ScaleInt(); break; } } DoPlus(); }
RState* RSNrValue::Shift(addr_t v, int32 token, RElem** head) { if (token == tIdent) { int32 id = v; if (ResolveIdentifier(v)) RAddElement(head, RValue(v), fSize, this); else error("Unknown identifier: %s", ST_Ident(id)); } else if (token == tInt) RAddElement(head, (REval *)v, fSize, this); else if (fHasDefault) { RAddElement(head, (REval *)fValue, fSize, this); return fNext->Shift(v, token, head); } else error("internal error 3"); return RSValue::Shift(v, token, head); } /* RSNrValue::Shift */
static unsigned MechStack( unsigned select, unsigned parm ) { unsigned result = 0; stack_entry *entry; sym_info info; switch( select ) { case 0: SwapStack( parm ); break; case 1: MoveSP( parm ); break; case 2: entry = StkEntry( parm ); LValue( entry ); result = TypeInfoToClass( &entry->info ) & (BASE_TYPE | STK_UNSIGNED); break; case 3: ExprValue( StkEntry( parm ) ); break; case 4: LValue( StkEntry( parm ) ); break; case 5: RValue( StkEntry( parm ) ); break; case 6: LRValue( StkEntry( parm ) ); break; case 7: entry = StkEntry( parm ); LValue( entry ); result = TI_CREATE( entry->info.kind, TM_NONE, 0 ); break; case 8: entry = StkEntry( parm ); NameResolve( entry, FALSE ); if( entry->flags & SF_SYM ) { SymInfo( entry->v.sh, entry->lc, &info ); result = info.kind; } else { result = SK_NONE; } break; case 9: entry = StkEntry( parm ); result = NameResolve( entry, FALSE ); break; case 10: entry = StkEntry( parm ); if( entry->flags & SF_NAME ) { result = 0; } else if( entry->flags & SF_SYM ) { result = 1; } else if( entry->flags & SF_LOCATION ) { result = 2; } else { result = 3; } break; } return( result ); }
static unsigned MechMisc( unsigned select, unsigned parm ) { long value; unsigned result = 0; mad_type_info mti; switch( select ) { case 0: ExprAddrDepth += parm; result = ExprAddrDepth; break; case 1: if( _IsOn( SW_EXPR_IS_CALL ) && ExprAddrDepth == 0 ) { result = TRUE; } else { result = FALSE; } break; case 2: SkipCount += parm; break; case 3: result = SkipCount; break; case 4: //never called break; case 5: if( ScanSavePtr >= MAX_SCANSAVE_PTRS ) Error( ERR_INTERNAL, LIT( ERR_TOO_MANY_SCANSAVE ) ); CurrScan[ScanSavePtr++] = ScanPos(); break; case 6: if( ScanSavePtr <= 0 ) Error( ERR_INTERNAL, LIT( ERR_TOO_MANY_SCANRESTORE ) ); ReScan( CurrScan[--ScanSavePtr] ); break; case 7: if( ScanSavePtr <= 0 ) Error( ERR_INTERNAL, LIT( ERR_TOO_MANY_SCANRESTORE ) ); --ScanSavePtr; break; case 8: if( parm ) { /* start scan string */ scan_string = TRUE; ReScan( ScanPos() ); } else { /* end scan string */ scan_string = FALSE; ReScan( ScanPos() ); } break; case 9: ReScan( ScanPos() + (int)parm ); break; case 10: AddChar(); break; case 11: AddCEscapeChar(); break; case 12: AddActualChar( '\0' ); break; case 13: ScanCCharNum = parm; break; case 14: if( NestedCallLevel == MAX_NESTED_CALL - 1 ) { Error( ERR_NONE, LIT( ERR_TOO_MANY_CALLS ) ); } else { PgmStackUsage[ ++NestedCallLevel ] = 0; } break; case 15: RValue( ExprSP ); ConvertTo( ExprSP, TK_INTEGER, TM_SIGNED, 4 ); value = U32FetchTrunc( ExprSP->v.uint ) - 1; PopEntry(); if( ExprSP->info.kind == TK_STRING ) { if( value < 0 || value >= ExprSP->info.size ) { Error( ERR_NONE, LIT( ERR_BAD_SUBSTRING_INDEX ) ); } LocationAdd( &ExprSP->v.string.loc, value*8 ); ExprSP->info.size -= value; ExprSP->v.string.ss_offset = value; } else { Error( ERR_NONE, LIT( ERR_ILL_TYPE ) ); } break; case 16: RValue( ExprSP ); ConvertTo( ExprSP, TK_INTEGER, TM_SIGNED, 4 ); value = U32FetchTrunc( ExprSP->v.sint ) - 1; PopEntry(); if( ExprSP->info.kind == TK_STRING ) { value -= ExprSP->v.string.ss_offset; if( value < 0 || value >= ExprSP->info.size ) { Error( ERR_NONE, LIT( ERR_BAD_SUBSTRING_INDEX ) ); } ExprSP->info.size = value; } else { Error( ERR_NONE, LIT( ERR_ILL_TYPE ) ); } break; case 17: EvalSubstring = parm; if( parm ) ExprSP->v.string.ss_offset = 0; break; case 18: result = EvalSubstring; break; case 19: FreePgmStack( TRUE ); break; case 20: switch( parm ) { // nyi - begin temp case SSL_CASE_SENSITIVE: _SwitchOn( SW_CASE_SENSITIVE ); break; case SSL_SIDE_EFFECT: _SwitchOn( SW_SIDE_EFFECT ); break; //case SSL_32_BIT: // _SwitchOn( SW_32_BIT ); // break; } break; case 21: switch( parm ) { case SSL_CASE_SENSITIVE: _SwitchOff( SW_CASE_SENSITIVE ); break; case SSL_SIDE_EFFECT: _SwitchOff( SW_SIDE_EFFECT ); break; //case SSL_32_BIT: // _SwitchOff( SW_32_BIT ); // break; } break; case 22: switch( parm ) { case SSL_CASE_SENSITIVE: result = _IsOn( SW_CASE_SENSITIVE ); break; case SSL_SIDE_EFFECT: result = _IsOn( SW_SIDE_EFFECT ); break; case SSL_32_BIT: GetMADTypeDefault( MTK_INTEGER, &mti ); result = (mti.b.bits >= 32); break; } break; case 23: // nyi - end temp MarkArrayOrder( parm ); break; case 24: StartSubscript(); break; case 25: AddSubscript(); break; case 26: EndSubscript(); break; } return( result ); }
/* EvalExpr - Eval and evaluate an expression using the shunting yard algorithm */ int EvalExpr(EvalState *c, const char *str, VALUE *pValue) { int unaryPossible = TRUE; int tkn, count, prec, op; PVAL pval; /* setup an error target */ if (setjmp(c->errorTarget)) return FALSE; /* initialize the parser */ c->linePtr = (char *)str; c->savedToken = TKN_NONE; /* initialize the operator and operand stacks */ c->oStackPtr = c->oStack - 1; c->rStackPtr = c->rStack - 1; /* handle each input token */ while ((tkn = GetToken(c, &pval)) != TKN_EOF) { switch (tkn) { case TKN_IDENTIFIER: case TKN_NUMBER: if (!unaryPossible) Error(c, "syntax error"); rStackPush(c, pval); unaryPossible = FALSE; break; case TKN_FCALL: oStackPush(c, c->argc); oStackPushData(c, c->fcn); oStackPush(c, tkn); c->fcn = pval.v.fcn; c->argc = 0; unaryPossible = FALSE; break; case '(': if (oStackTop(c) == TKN_FCALL) c->oStackPtr->op = TKN_FCALL_ARGS; else oStackPush(c, tkn); unaryPossible = TRUE; break; case ',': if (PopAndEvaluate(c) != TKN_FCALL_ARGS) Error(c, "argument list outside of a function call"); unaryPossible = FALSE; break; case ')': tkn = PopAndEvaluate(c); oStackDrop(c); if (tkn == TKN_FCALL || tkn == TKN_FCALL_ARGS) CallFunction(c); unaryPossible = FALSE; break; default: if (unaryPossible && tkn == '-') tkn = TKN_UNARY_MINUS; if (unaryPossible && !Unary(tkn)) Error(c, "syntax error"); prec = Prec(c, tkn); while (!oStackIsEmpty(c)) { int stackPrec = Prec(c, oStackTop(c)); if ((Assoc(tkn) == ASSOC_LEFT && prec > stackPrec) || prec >= stackPrec) break; op = oStackTop(c); oStackDrop(c); if (op == TKN_FCALL) CallFunction(c); else Apply(c, op); } oStackPush(c, tkn); unaryPossible = TRUE; break; } } /* apply all of the remaining operands on the operator stack */ while (!oStackIsEmpty(c)) { int op = oStackTop(c); oStackDrop(c); if (op == '(') Error(c, "mismatched parens"); if (op == TKN_FCALL) CallFunction(c); else Apply(c, op); } /* if the operand stack is empty then there was no expression to parse */ if ((count = rStackCount(c)) == 0) return FALSE; /* otherwise, make sure there is only one entry left on the operand stack */ else if (count != 1) Error(c, "syntax error"); /* return the expression value */ RValue(c, &c->rStackPtr[0]); *pValue = c->rStackPtr[0].v.value; /* return successfully */ return TRUE; }
void BinOp( stack_entry *left, stack_entry *right ) { RValue( left ); RValue( right ); DoBinOp( left, right ); }
static void AddParms( void ) { PARMPTR parm; PARMPTR prev_parm; SYM_HANDLE sym_handle; SYM_HANDLE prev_sym_handle; SYM_HANDLE new_sym_handle; TYPEPTR typ = NULL; int parm_count; id_hash_idx h; parm_list *parmlist; SYM_ENTRY new_sym; CurFunc->u.func.locals = SYM_NULL; CurFunc->u.func.parms = SYM_NULL; parmlist = NULL; prev_sym_handle = SYM_NULL; parm_count = 0; prev_parm = NULL; for( parm = ParmList; parm != NULL; parm = parm->next_parm ) { new_sym_handle = SYM_NULL; parm->sym.flags |= SYM_DEFINED | SYM_ASSIGNED; parm->sym.attribs.is_parm = true; h = parm->sym.info.hash; if( parm->sym.name[0] == '\0' ) { /* no name ==> ... */ parm->sym.sym_type = GetType( TYPE_DOT_DOT_DOT ); parm->sym.attribs.stg_class = SC_AUTO; } else if( parm->sym.sym_type == NULL ) { parm->sym.sym_type = TypeDefault(); parm->sym.attribs.stg_class = SC_AUTO; } else { /* go through ParmList again, looking for FLOAT parms change the name to ".P" and duplicate the symbol with type float and generate an assignment statement. */ typ = parm->sym.sym_type; SKIP_TYPEDEFS( typ ); switch( typ->decl_type ) { case TYPE_CHAR: case TYPE_UCHAR: case TYPE_SHORT: if( CompFlags.strict_ANSI ) { parm->sym.sym_type = GetType( TYPE_INT ); } break; case TYPE_USHORT: if( CompFlags.strict_ANSI ) { #if TARGET_SHORT == TARGET_INT parm->sym.sym_type = GetType( TYPE_UINT ); #else parm->sym.sym_type = GetType( TYPE_INT ); #endif } break; case TYPE_FLOAT: memcpy( &new_sym, &parm->sym, sizeof( SYM_ENTRY ) ); new_sym.handle = CurFunc->u.func.locals; new_sym_handle = SymAdd( h, &new_sym ); CurFunc->u.func.locals = new_sym_handle; SymReplace( &new_sym, new_sym_handle ); parm->sym.name = ".P"; parm->sym.flags |= SYM_REFERENCED; parm->sym.sym_type = GetType( TYPE_DOUBLE ); break; default: break; } } sym_handle = SymAdd( h, &parm->sym ); if( new_sym_handle != SYM_NULL ) { TREEPTR tree; tree = ExprNode( VarLeaf( &new_sym, new_sym_handle ), OPR_EQUALS, RValue( VarLeaf( &parm->sym, sym_handle ) ) ); tree->op.u2.result_type = typ; tree->u.expr_type = typ; AddStmt( tree ); } if( prev_parm == NULL ) { CurFunc->u.func.parms = sym_handle; } else { prev_parm->sym.handle = sym_handle; SymReplace( &prev_parm->sym, prev_sym_handle ); CMemFree( prev_parm ); } prev_parm = parm; prev_sym_handle = sym_handle; ++parm_count; parmlist = NewParm( parm->sym.sym_type, parmlist ); } if( prev_parm != NULL ) { prev_parm->sym.handle = SYM_NULL; SymReplace( &prev_parm->sym, prev_sym_handle ); CMemFree( prev_parm ); } typ = CurFunc->sym_type; // TODO not following my scheme CurFunc->sym_type = FuncNode( typ->object, FLAG_NONE, MakeParmList( parmlist, ParmsToBeReversed( CurFunc->mods, NULL ) ) ); if( PrevProtoType != NULL ) { ChkProtoType(); } }
RValue Inst::Load(CodeContext& context, RValue value) { return RValue(new LoadInst(value, "", context), value.stype()); }
bool Inst::CastTo(CodeContext& context, RValue& value, SType* type, bool upcast) { auto valueType = value.stype(); if (type == valueType) { // non-assignment and non-comparison operations with enum types // must result in an int type to keep enum variables within range. if (upcast && valueType->isEnum()) value.castToSubtype(); return false; } else if (type->isComplex() || valueType->isComplex()) { context.addError("can not cast complex types"); return true; } else if (type->isPointer()) { if (value.isNullPtr()) { // NOTE: discard current null value and create // a new one using the right type value = RValue::getNullPtr(context, type); return false; } else if (type->subType()->isVoid()) { value = RValue(new BitCastInst(value, *type, "", context), type); return false; } context.addError("can't cast value to pointer type"); return true; } else if (type->isVec()) { // unwrap enum type if (valueType->isEnum()) valueType = value.castToSubtype(); if (valueType->isNumeric()) { CastTo(context, value, type->subType(), upcast); auto i32 = SType::getInt(context, 32); auto mask = RValue::getZero(context, SType::getVec(context, i32, type->size())); auto udef = UndefValue::get(*SType::getVec(context, type->subType(), 1)); auto instEle = InsertElementInst::Create(udef, value, RValue::getZero(context, i32), "", context); auto retVal = new ShuffleVectorInst(instEle, udef, mask, "", context); value = RValue(retVal, type); return false; } else if (valueType->isPointer()) { context.addError("can not cast pointer to vec type"); return true; } else if (type->size() != valueType->size()) { context.addError("can not cast vec types of different sizes"); return true; } else if (type->subType()->isBool()) { // cast to bool is value != 0 auto pred = getPredicate(ParserBase::TT_NEQ, valueType, context); auto op = valueType->subType()->isFloating()? Instruction::FCmp : Instruction::ICmp; auto val = CmpInst::Create(op, pred, value, RValue::getZero(context, valueType), "", context); value = RValue(val, type); return false; } else { auto op = getCastOp(valueType->subType(), type->subType()); auto val = CastInst::Create(op, value, *type, "", context); value = RValue(val, type); return false; } } else if (type->isEnum()) { // casting to enum would violate value constraints context.addError("can't cast to enum type"); return true; } else if (type->isBool()) { if (valueType->isVec()) { context.addError("can not cast vec type to bool"); return true; } else if (valueType->isEnum()) { valueType = value.castToSubtype(); } // cast to bool is value != 0 auto pred = getPredicate(ParserBase::TT_NEQ, valueType, context); auto op = valueType->isFloating()? Instruction::FCmp : Instruction::ICmp; auto val = CmpInst::Create(op, pred, value, RValue::getZero(context, valueType), "", context); value = RValue(val, type); return false; } if (valueType->isPointer()) { context.addError("can't cast pointer to numeric type"); return true; } // unwrap enum type if (valueType->isEnum()) valueType = value.castToSubtype(); auto op = getCastOp(valueType, type); auto val = op != Instruction::AddrSpaceCast? CastInst::Create(op, value, *type, "", context) : value; value = RValue(val, type); return false; }