12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052 |
- /*
- * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
- * See the copyright notice in the ACK home directory, in the file "Copyright".
- */
- /* $Id$ */
- /* EXPRESSION-CODE GENERATOR */
- #include "lint.h"
- #ifndef LINT
- #include <em.h>
- #include <em_reg.h>
- #include <alloc.h>
- #include "debug.h"
- #include "nobitfield.h"
- #include "dataflow.h"
- #include <flt_arith.h>
- #include <system.h>
- #include "print.h"
- #include "arith.h"
- #include "type.h"
- #include "idf.h"
- #include "label.h"
- #include "code.h"
- #include "assert.h"
- #include "def.h"
- #include "expr.h"
- #include "sizes.h"
- #include "Lpars.h"
- #include "level.h"
- #include "stack.h"
- #include "align.h"
- #include "mes.h"
- #include "atw.h"
- #include "blocks.h"
- #include "conversion.h"
- #include "specials.h"
- #include "ch3.h"
- #include "eval.h"
- #include "error.h"
- #include "field_loc.h"
- #include "struct_loc.h"
- #include "util_loc.h"
- #include <symbol2str.h>
- #define CRASH() crash("EVAL: CRASH at line %u", __LINE__)
- #define LocalPtrVar() NewLocal(pointer_size, pointer_align, reg_pointer, REGISTER)
- extern int err_occurred; /* error.c */
- /* EVAL() is the main expression-tree evaluator, which turns
- any legal expression tree into EM code. Parameters:
- struct expr *expr
- pointer to root of the expression tree to be evaluated
- int val
- indicates whether the resulting expression is to be
- dereferenced (if val == RVAL and expr->ex_lvalue == 1)
- or not (val == LVAL). The latter case indicates that
- the resulting expression is an lvalue expression which
- should not be dereferenced by EVAL
-
- int code
- indicates whether the expression tree must be turned
- into EM code or not. E.g. the expression statement "12;"
- delivers the expression "12" to EVAL while this should
- not result in any EM code
-
- label false_label, label true_label
- if the expression is a logical or relational expression
- and if the loop of the program depends on the resulting
- value then EVAL generates jumps to the specified program
- labels, in case they are specified (i.e. are non-zero)
- */
- void EVAL(struct expr *expr, int val, int code, label true_label, label false_label)
- {
- int vol = (code != TRUE && recurqual(expr->ex_type, TQ_VOLATILE));
- int gencode = code == TRUE;
- if (err_occurred) return;
- switch (expr->ex_class) {
- case Value: /* just a simple value */
- if (gencode) {
- if (true_label) {
- /* can only result from ','-expressions with
- constant right-hand sides ???
- */
- ASSERT(is_cp_cst(expr));
- C_bra(expr->VL_VALUE == 0 ? false_label : true_label);
- }
- else load_val(expr, val);
- }
- else if (vol) {
- load_val(expr, val);
- C_asp(ATW(expr->ex_type->tp_size));
- }
- break;
- case String: /* a string constant */
- if (gencode) {
- string2pointer(expr);
- C_lae_dlb(expr->VL_LBL, expr->VL_VALUE);
- }
- break;
- case Float: /* a floating constant */
- if (gencode) {
- label datlab = data_label();
- char buf[FLT_STRLEN];
-
- fp_used = 1;
- flt_flt2str(&(expr->FL_ARITH), buf, FLT_STRLEN);
- C_df_dlb(datlab);
- C_rom_fcon(buf, expr->ex_type->tp_size);
- C_lae_dlb(datlab, (arith)0);
- C_loi(expr->ex_type->tp_size);
- }
- break;
- case Oper: /* compound expression */
- {
- int oper = expr->OP_OPER;
- struct expr *left = expr->OP_LEFT;
- struct expr *right = expr->OP_RIGHT;
- struct type *tp = expr->OP_TYPE;
- switch (oper) {
- case '+':
- /* We have the following possibilities :
- int + int, pointer + int, pointer + long,
- long + long, double + double
- */
- operands(expr, gencode);
- if (gencode) {
- switch (tp->tp_fund) {
- case INT:
- case LONG:
- if (tp->tp_unsigned)
- C_adu(tp->tp_size);
- else
- C_adi(tp->tp_size);
- break;
- case POINTER:
- ptr_add(right->ex_type->tp_size);
- break;
- case FLOAT:
- case DOUBLE:
- case LNGDBL:
- C_adf(tp->tp_size);
- break;
- default:
- crash("bad type +");
- }
- }
- break;
- case '-':
- if (left == 0) { /* unary */
- EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
- if (gencode) {
- switch (tp->tp_fund) {
- case INT:
- case LONG:
- case POINTER:
- C_ngi(tp->tp_size);
- break;
- case FLOAT:
- case DOUBLE:
- case LNGDBL:
- C_ngf(tp->tp_size);
- break;
- default:
- CRASH();
- }
- }
- break;
- }
- /* else binary; we have the following flavours:
- int - int, pointer - int, pointer - long,
- pointer - pointer, long - long, double - double
- */
- operands(expr, gencode);
- if (!gencode)
- break;
- switch (tp->tp_fund) {
- case INT:
- case LONG:
- if (tp->tp_unsigned)
- C_sbu(tp->tp_size);
- else
- C_sbi(tp->tp_size);
- break;
- case POINTER:
- if (right->ex_type->tp_fund == POINTER)
- C_sbs(pointer_size);
- else {
- C_ngi(right->ex_type->tp_size);
- ptr_add(right->ex_type->tp_size);
- }
- break;
- case FLOAT:
- case DOUBLE:
- case LNGDBL:
- C_sbf(tp->tp_size);
- break;
- default:
- crash("bad type -");
- }
- break;
- case '*':
- if (left == 0) { /* unary */
- EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
- if (gencode && right->ex_class == String) {
- C_loi((arith)1);
- }
- break;
- }
- operands(expr, gencode);
- if (gencode) {
- switch (tp->tp_fund) {
- case INT:
- case LONG:
- case POINTER:
- if (tp->tp_unsigned)
- C_mlu(tp->tp_size);
- else
- C_mli(tp->tp_size);
- break;
- case FLOAT:
- case DOUBLE:
- case LNGDBL:
- C_mlf(tp->tp_size);
- break;
- default:
- crash("bad type *");
- }
- }
- break;
- case '/':
- operands(expr, gencode);
- if (gencode)
- switch (tp->tp_fund) {
- case INT:
- case LONG:
- case POINTER:
- if (tp->tp_unsigned)
- C_dvu(tp->tp_size);
- else
- C_dvi(tp->tp_size);
- break;
- case FLOAT:
- case DOUBLE:
- case LNGDBL:
- /*C_dvf(double_size);*/
- C_dvf(tp->tp_size);
- break;
- default:
- crash("bad type /");
- }
- break;
- case '%':
- operands(expr, gencode);
- ASSERT(tp->tp_fund==INT || tp->tp_fund==LONG);
- if (gencode)
- {
- if (tp->tp_unsigned)
- {
- C_rmu(tp->tp_size);
- }
- else
- {
- C_rmi(tp->tp_size);
- }
- }
- break;
- case LEFT:
- operands(expr, gencode);
- if (gencode)
- {
- if (tp->tp_unsigned)
- {
- C_slu(tp->tp_size);
- }
- else
- {
- C_sli(tp->tp_size);
- }
- }
- break;
- case RIGHT:
- operands(expr, gencode);
- if (gencode)
- {
- if (tp->tp_unsigned)
- {
- C_sru(tp->tp_size);
- }
- else
- {
- C_sri(tp->tp_size);
- }
- }
- break;
- case '<':
- case LESSEQ:
- case '>':
- case GREATEREQ:
- case EQUAL:
- case NOTEQUAL:
- operands(expr, gencode);
- if (gencode) {
- /* The operands have the same type */
- arith size = left->ex_type->tp_size;
-
- switch (tp->tp_fund) {
- case INT:
- case LONG:
- if (left->ex_type->tp_unsigned)
- C_cmu(size);
- else
- C_cmi(size);
- break;
- case FLOAT:
- case DOUBLE:
- case LNGDBL:
- C_cmf(size);
- break;
- case POINTER:
- C_cmp();
- break;
- case ENUM:
- C_cmi(size);
- break;
- default:
- CRASH();
- }
- if (true_label != 0) {
- compare(oper, true_label);
- C_bra(false_label);
- }
- else {
- truthvalue(oper);
- }
- }
- break;
- case '&':
- case '|':
- case '^':
- /* both operands should have type int */
- operands(expr, gencode);
- if (gencode) {
- arith size = tp->tp_size;
- if ((int)size < (int)word_size)
- size = word_size;
- switch (oper) {
- case '&':
- C_and(size);
- break;
- case '|':
- C_ior(size);
- break;
- case '^':
- C_xor(size);
- break;
- }
- }
- break;
- case '=':
- #ifndef NOBITFIELD
- if (left->ex_type->tp_fund == FIELD) {
- eval_field(expr, gencode);
- break;
- }
- #endif /* NOBITFIELD */
- if (is_struct_or_union(tp->tp_fund) && ! gencode) {
- EVAL(right, LVAL, TRUE, NO_LABEL, NO_LABEL);
- EVAL(left, LVAL, TRUE, NO_LABEL, NO_LABEL);
- copy_block(tp->tp_size, tp->tp_align);
- break;
- }
- EVAL(right, RVAL, TRUE, NO_LABEL, NO_LABEL);
- if (gencode && val == RVAL)
- C_dup(ATW(tp->tp_size));
- if (left->ex_class != Value) {
- EVAL(left, LVAL, TRUE, NO_LABEL, NO_LABEL);
- if (gencode && val == LVAL) {
- arith tmp = LocalPtrVar();
- C_dup(pointer_size);
- StoreLocal(tmp, pointer_size);
- store_block(tp->tp_size, tp->tp_align);
- LoadLocal(tmp, pointer_size);
- FreeLocal(tmp);
- }
- else store_block(tp->tp_size, tp->tp_align);
- }
- else {
- store_val(&(left->EX_VALUE), left->ex_type);
- if (gencode && val == LVAL) {
- EVAL(left, LVAL, TRUE, NO_LABEL, NO_LABEL);
- }
- }
- break;
- case PLUSAB:
- case MINAB:
- case TIMESAB:
- case DIVAB:
- case MODAB:
- case LEFTAB:
- case RIGHTAB:
- case ANDAB:
- case XORAB:
- case ORAB:
- case POSTINCR:
- case POSTDECR:
- case PLUSPLUS:
- case MINMIN:
- {
- arith tmp = 0;
- int compl; /* Complexity of left operand */
- int right_done = 0;
- int dupval;
- #ifndef NOBITFIELD
- if (left->ex_type->tp_fund == FIELD) {
- eval_field(expr, gencode);
- break;
- }
- #endif /* NOBITFIELD */
- if (left->ex_class == Value) {
- compl = 0; /* Value */
- }
- else if (left->ex_depth == 1 &&
- !(left->ex_flags & EX_SIDEEFFECTS)) {
- compl = 1;
- }
- else compl = 2;
- /* evaluate right-hand side first when possible,
- but not for POSTINCR or PLUSPLUS, because then
- we might miss a chance for increment instructions.
- */
- if (compl != 2 &&
- tp->tp_fund != POINTER &&
- (oper == PLUSAB || oper == TIMESAB ||
- oper == ANDAB || oper == XORAB || oper == ORAB)) {
- right_done = 1;
- EVAL(right, RVAL, TRUE, NO_LABEL, NO_LABEL);
- }
- if (compl == 0) {
- load_val(left, RVAL);
- }
- else
- if (compl == 1) {
- EVAL(left, RVAL, TRUE, NO_LABEL, NO_LABEL);
- }
- else {
- EVAL(left, LVAL, TRUE, NO_LABEL, NO_LABEL);
- tmp = LocalPtrVar();
- C_dup(pointer_size);
- StoreLocal(tmp, pointer_size);
- C_loi(left->ex_type->tp_size);
- }
- if (gencode && (oper == POSTINCR ||
- oper == POSTDECR))
- C_dup(ATW(left->ex_type->tp_size));
- conversion(left->ex_type, tp);
- if (! right_done) {
- EVAL(right, RVAL, TRUE, NO_LABEL, NO_LABEL);
- }
- dupval = gencode && oper != POSTINCR &&
- oper != POSTDECR;
- assop(tp, oper);
- conversion(tp, left->ex_type);
- if (compl == 0) {
- store_val(&(left->EX_VALUE),
- left->ex_type);
- if (dupval) load_val(left, RVAL);
- }
- else if (compl == 1) {
- EVAL(left, LVAL, TRUE, NO_LABEL, NO_LABEL);
- C_sti(left->ex_type->tp_size);
- if (dupval) {
- EVAL(left, LVAL, TRUE, NO_LABEL, NO_LABEL);
- C_loi(left->ex_type->tp_size);
- }
- }
- else {
- LoadLocal(tmp, pointer_size);
- C_sti(left->ex_type->tp_size);
- if (dupval) {
- LoadLocal(tmp, pointer_size);
- C_loi(left->ex_type->tp_size);
- }
- FreeLocal(tmp);
- }
- break;
- }
- case '(':
- {
- struct expr *ex;
- arith ParSize = (arith)0;
- label setjmp_label = 0;
- arith retspace = 0;
- if (ISNAME(left)) {
- if (left->VL_IDF->id_special == SP_SETJMP) {
- label addr_label = data_label();
- setjmp_label = text_label();
- C_df_dlb(addr_label);
- C_rom_ilb(setjmp_label);
- C_lae_dlb(addr_label, (arith) 0);
- C_loi(pointer_size);
- ParSize += pointer_size;
- }
- }
- if ((ex = right) != NILEXPR) {
- /* function call with parameters*/
- while ( ex->ex_class == Oper &&
- ex->OP_OPER == PARCOMMA
- ) {
- EVAL(ex->OP_RIGHT, RVAL, TRUE,
- NO_LABEL, NO_LABEL);
- ParSize += ATW(ex->OP_RIGHT->ex_type->tp_size);
- ex = ex->OP_LEFT;
- }
- EVAL(ex, RVAL, TRUE, NO_LABEL, NO_LABEL);
- ParSize += ATW(ex->ex_type->tp_size);
- }
- if (is_struct_or_union(tp->tp_fund)) {
- retspace = NewLocal(tp->tp_size, tp->tp_align,
- -1, 0);
- C_lal(retspace);
- ParSize += pointer_size;
- }
- if (ISNAME(left)) {
- /* e.g., main() { (*((int (*)())0))(); } */
- C_cal(left->VL_IDF->id_text);
- if (setjmp_label) {
- C_df_ilb(setjmp_label);
- }
- #ifdef DATAFLOW
- { extern char options[];
- if (options['d'])
- DfaCallFunction(
- left->VL_IDF->id_text);
- }
- #endif /* DATAFLOW */
- }
- else {
- EVAL(left, LVAL, TRUE, NO_LABEL, NO_LABEL);
- C_cai();
- }
- /* remove parameters from stack */
- if (ParSize > (arith)0)
- C_asp(ParSize);
- if (gencode) {
- if (is_struct_or_union(tp->tp_fund)) {
- C_lfr(pointer_size);
- if (val == RVAL) {
- load_block(tp->tp_size, (int) word_size);
- FreeLocal(retspace);
- }
- }
- else
- C_lfr(ATW(tp->tp_size));
- }
- if (tp->tp_fund == FLOAT || tp->tp_fund == DOUBLE
- || tp->tp_fund == LNGDBL)
- fp_used = 1;
- /* ??? set filename and line number ??? */
- break;
- }
- case '.':
- case ARROW:
- if (tp->tp_fund == FLOAT || tp->tp_fund == DOUBLE
- || tp->tp_fund == LNGDBL)
- fp_used = 1;
- EVAL(left, oper == '.' ? LVAL : RVAL, gencode,
- NO_LABEL, NO_LABEL);
- ASSERT(is_cp_cst(right));
- if (gencode) {
- C_adp(right->VL_VALUE);
- }
- break;
- case ',':
- EVAL(left, RVAL, FALSE, NO_LABEL, NO_LABEL);
- EVAL(right, val, gencode, true_label, false_label);
- break;
- case '~':
- EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
- if (gencode)
- C_com(tp->tp_size);
- break;
- case '?': /* must be followed by ':' */
- {
- label l_true = text_label();
- label l_false = text_label();
- label l_end = text_label();
- EVAL(left, RVAL, TRUE, l_true, l_false);
- C_df_ilb(l_true);
- EVAL(right->OP_LEFT, val, gencode, NO_LABEL, NO_LABEL);
- C_bra(l_end);
- C_df_ilb(l_false);
- EVAL(right->OP_RIGHT, val, gencode, NO_LABEL, NO_LABEL);
- C_df_ilb(l_end);
- break;
- }
- case OR:
- case AND: {
- label l_false, l_true, l_maybe;
- l_maybe = text_label();
- if (true_label) {
- l_false = false_label;
- l_true = true_label;
- }
- else {
- l_false = text_label();
- l_true = gencode ? text_label(): l_false;
- }
- EVAL(left, RVAL, TRUE, oper == AND ? l_maybe : l_true,
- oper == AND ? l_false : l_maybe);
- C_df_ilb(l_maybe);
- EVAL(right, RVAL, gencode, l_true, l_false);
- if (gencode && !true_label) {
- label l_end = text_label();
- C_df_ilb(l_true);
- C_loc((arith)1);
- C_bra(l_end);
- C_df_ilb(l_false);
- C_loc((arith)0);
- C_df_ilb(l_end);
- }
- else {
- if (! true_label) C_df_ilb(l_false);
- }
- }
- break;
- case '!':
- if (true_label == 0) {
- EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
- if (gencode) {
- C_teq();
- }
- }
- else
- EVAL(right, RVAL, gencode, false_label,
- true_label);
- break;
- case INT2INT:
- case INT2FLOAT:
- case FLOAT2INT:
- case FLOAT2FLOAT:
- EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
- if (gencode)
- conversion(right->ex_type, left->ex_type);
- break;
- default:
- crash("(EVAL) bad operator %s\n", symbol2str(oper));
- }
- /* If the rvalue of the expression is required but
- only its lvalue is evaluated, its rvalue is
- loaded by the following statements:
- */
- if (gencode && val == RVAL && expr->ex_lvalue == 1) {
- if (expr->ex_type->tp_fund == FLOAT
- || expr->ex_type->tp_fund == DOUBLE
- || expr->ex_type->tp_fund == LNGDBL)
- fp_used = 1;
- load_block(expr->ex_type->tp_size,
- expr->ex_type->tp_align);
- }
- break;
- }
- default:
- crash("(EVAL) bad expression class");
- }
- if (val == RVAL && ((expr->ex_flags & EX_VOLATILE) || vol)) C_nop();
- }
- /* compare() serves as an auxiliary function of EVAL */
- void compare(int relop, label lbl)
- {
- switch (relop) {
- case '<':
- C_zlt(lbl);
- break;
- case LESSEQ:
- C_zle(lbl);
- break;
- case '>':
- C_zgt(lbl);
- break;
- case GREATEREQ:
- C_zge(lbl);
- break;
- case EQUAL:
- C_zeq(lbl);
- break;
- case NOTEQUAL:
- C_zne(lbl);
- break;
- default:
- CRASH();
- }
- }
- /* truthvalue() serves as an auxiliary function of EVAL */
- void truthvalue(int relop)
- {
- switch (relop) {
- case '<':
- C_tlt();
- break;
- case LESSEQ:
- C_tle();
- break;
- case '>':
- C_tgt();
- break;
- case GREATEREQ:
- C_tge();
- break;
- case EQUAL:
- C_teq();
- break;
- case NOTEQUAL:
- C_tne();
- break;
- default:
- CRASH();
- }
- }
- /* assop() generates the opcode of an assignment operators op= */
- void assop(struct type *type, int oper)
- {
- arith size;
- int uns = type->tp_unsigned;
- if ((int)(size = type->tp_size) < (int)word_size)
- size = word_size;
- switch (type->tp_fund) {
- case CHAR:
- case SHORT:
- case INT:
- case LONG:
- case ENUM:
- switch (oper) {
- case PLUSAB:
- case PLUSPLUS:
- case POSTINCR:
- if (uns)
- C_adu(size);
- else
- C_adi(size);
- break;
- case MINAB:
- case MINMIN:
- case POSTDECR:
- if (uns)
- C_sbu(size);
- else
- C_sbi(size);
- break;
- case TIMESAB:
- if (uns)
- C_mlu(size);
- else
- C_mli(size);
- break;
- case DIVAB:
- if (uns)
- C_dvu(size);
- else
- C_dvi(size);
- break;
- case MODAB:
- if (uns)
- C_rmu(size);
- else
- C_rmi(size);
- break;
- case LEFTAB:
- if (uns)
- C_slu(size);
- else
- C_sli(size);
- break;
- case RIGHTAB:
- if (uns)
- C_sru(size);
- else
- C_sri(size);
- break;
- case ANDAB:
- C_and(size);
- break;
- case XORAB:
- C_xor(size);
- break;
- case ORAB:
- C_ior(size);
- break;
- }
- break;
- case FLOAT:
- case DOUBLE:
- case LNGDBL:
- switch (oper) {
- case PLUSAB:
- case PLUSPLUS: /* ??? etc... */
- case POSTINCR:
- C_adf(size);
- break;
- case MINAB:
- case MINMIN:
- case POSTDECR:
- C_sbf(size);
- break;
- case TIMESAB:
- C_mlf(size);
- break;
- case DIVAB:
- C_dvf(size);
- break;
- }
- break;
- case POINTER:
- if (oper == MINAB || oper == MINMIN || oper == POSTDECR)
- C_ngi(size);
- ptr_add(size);
- break;
- default:
- crash("(assop) bad type %s\n", symbol2str(type->tp_fund));
- }
- }
- void ptr_add(arith size)
- {
- if (size != pointer_size) {
- C_loc(size);
- C_loc(pointer_size);
- C_cuu();
- }
- C_ads(pointer_size);
- }
- /* store_val() generates code for a store operation.
- There are four ways of storing data:
- - into a global variable
- - into an automatic local variable
- - into a local static variable
- - absolute addressing
- */
- void store_val(struct value *vl, struct type *tp)
- {
- int inword = 0;
- int indword = 0;
- arith val = vl->vl_value;
- if (vl->vl_class == Const) { /* absolute addressing */
- load_cst(val, pointer_size);
- store_block(tp->tp_size, tp->tp_align);
- return;
- }
- if (tp->tp_align % word_align == 0) {
- if (tp->tp_size == word_size) inword = 1;
- else if (tp->tp_size == dword_size) indword = 1;
- }
- if (vl->vl_class == Name) {
- struct idf *id = vl->vl_data.vl_idf;
- struct def *df = id->id_def;
- /* if (df->df_level == L_GLOBAL) { // } ??? re-examine */
- if (df->df_sc == GLOBAL
- || df->df_sc == EXTERN
- || df->df_sc == STATIC) {
- if (inword)
- C_ste_dnam(id->id_text, val);
- else
- if (indword)
- C_sde_dnam(id->id_text, val);
- else {
- C_lae_dnam(id->id_text, val);
- store_block(tp->tp_size, tp->tp_align);
- }
- }
- else {
- ASSERT(df->df_sc != STATIC);
- if (inword || indword)
- StoreLocal(df->df_address + val, tp->tp_size);
- else {
- AddrLocal(df->df_address + val);
- store_block(tp->tp_size, tp->tp_align);
- }
- }
- }
- else {
- label dlb = vl->vl_data.vl_lbl;
- ASSERT(vl->vl_class == Label);
- if (inword)
- C_ste_dlb(dlb, val);
- else
- if (indword)
- C_sde_dlb(dlb, val);
- else {
- C_lae_dlb(dlb, val);
- store_block(tp->tp_size, tp->tp_align);
- }
- }
- }
- /* load_val() generates code for stacking a certain value (from ex),
- which can be obtained in one of the following ways:
- - value from absolute addressed memory
- - constant value
- - function result
- - global variable
- - static variable
- - local variable
- */
- /* expr -> expression containing the value
- rlval -> generate either LVAL or RVAL
- */
- void load_val(struct expr *expr, int rlval)
- {
- struct type *tp = expr->ex_type;
- int rvalue = (rlval == RVAL && expr->ex_lvalue != 0);
- int inword = 0, indword = 0;
- arith val = expr->VL_VALUE;
- if (expr->ex_type->tp_fund == FLOAT
- || expr->ex_type->tp_fund == DOUBLE
- || expr->ex_type->tp_fund == LNGDBL)
- fp_used = 1;
- if (expr->VL_CLASS == Const) {
- if (rvalue) { /* absolute addressing */
- load_cst(val, pointer_size);
- load_block(tp->tp_size, tp->tp_align);
- }
- else /* integer, unsigned, long, enum etc */
- load_cst(val, tp->tp_size);
- return;
- }
- if (rvalue) {
- if (tp->tp_align % word_align == 0) {
- if (tp->tp_size == word_size) inword = 1;
- else if (tp->tp_size == dword_size) indword = 1;
- }
- }
- if (expr->VL_CLASS == Label) {
- if (rvalue) {
- if (inword)
- C_loe_dlb(expr->VL_LBL, val);
- else
- if (indword)
- C_lde_dlb(expr->VL_LBL, val);
- else {
- C_lae_dlb(expr->VL_LBL, val);
- load_block(tp->tp_size, tp->tp_align);
- }
- }
- else {
- C_lae_dlb(expr->VL_LBL, (arith)0);
- C_adp(val);
- }
- }
- else {
- struct idf *id = expr->VL_IDF;
- struct def *df = id->id_def;
- int fund = df->df_type->tp_fund;
- ASSERT(ISNAME(expr));
- if (fund == FUNCTION) {
- /* the previous statement tried to catch a function
- identifier, which may be cast to a pointer to a
- function.
- ASSERT(!(rvalue)); ???
- */
- C_lpi(id->id_text);
- }
- else
- /* if (df->df_level == L_GLOBAL) { // } ??? re-examine */
- if ( df->df_sc == GLOBAL
- || df->df_sc == STATIC
- || df->df_sc == EXTERN) {
- if (rvalue) {
- if (inword)
- C_loe_dnam(id->id_text, val);
- else
- if (indword)
- C_lde_dnam(id->id_text, val);
- else {
- C_lae_dnam(id->id_text, val);
- load_block(tp->tp_size, tp->tp_align);
- }
- }
- else {
- C_lae_dnam(id->id_text, (arith)0);
- C_adp(val);
- }
- }
- else {
- /* ASSERT(df->df_sc != STATIC); */
- if (rvalue) {
- if (inword || indword)
- LoadLocal(df->df_address + val, tp->tp_size);
- else {
- AddrLocal(df->df_address + val);
- load_block(tp->tp_size, tp->tp_align);
- }
- }
- else {
- AddrLocal(df->df_address);
- C_adp(val);
- }
- }
- }
- }
- void load_cst(arith val, arith siz)
- {
- if ((int)siz <= (int)word_size)
- C_loc(val);
- else
- if ((int)siz == (int)dword_size)
- C_ldc(val);
- else {
- label datlab;
- C_df_dlb(datlab = data_label());
- C_rom_icon(long2str((long)val, 10), siz);
- C_lae_dlb(datlab, (arith)0);
- C_loi(siz);
- }
- }
- void operands(struct expr *expr, int gencode)
- {
- EVAL(expr->OP_LEFT, RVAL, gencode, NO_LABEL, NO_LABEL);
- EVAL(expr->OP_RIGHT, RVAL, gencode, NO_LABEL, NO_LABEL);
- }
- #endif /* LINT */
|