ack/lang/cem/cemcom/eval.c

1032 lines
22 KiB
C
Raw Normal View History

1986-03-10 13:07:55 +00:00
/* $Header$ */
/* EXPRESSION-CODE GENERATOR */
/* main functions :
EVAL() -- expression tree evaluator
tmp_pointer_var() -- deliver temporary pointer variable
free_tmp_var() -- return the pointer var
store_val() -- store primary expression
load_val() -- load primary expression
auxiliary functions:
assop()
compare()
*/
#include <em.h>
1986-03-10 13:07:55 +00:00
#include "debug.h"
#include "nobitfield.h"
#include "dataflow.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"
#define CRASH() crash("EVAL: CRASH at line %u", __LINE__)
#define roundup(n) ((n) < word_size ? word_size : (n))
char *symbol2str();
1986-03-26 16:58:43 +00:00
char *long2str();
1986-03-10 13:07:55 +00:00
arith tmp_pointer_var();
/* EVAL() serves as the main expression tree evaluator, which turns
any legal expression tree into legal EM code.
The parameters describe how EVAL should treat the expression tree:
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
1986-03-17 17:47:04 +00:00
EVAL while this should not result in any EM
code
1986-03-10 13:07:55 +00:00
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
1986-03-17 17:47:04 +00:00
generates jumps to the specified program
labels, in case they are specified
(i.e. are non-zero)
1986-03-10 13:07:55 +00:00
*/
EVAL(expr, val, code, true_label, false_label)
struct expr *expr; /* the expression tree itself */
int val; /* either RVAL or LVAL */
int code; /* generate explicit code or not */
label true_label;
label false_label; /* labels to jump to in logical expr's */
{
register gencode = (code == TRUE);
switch (expr->ex_class) {
case Value: /* just a simple value */
if (gencode)
load_val(expr, val);
break;
case String: /* a string constant */
if (gencode) {
label datlab = data_label();
C_df_dlb(datlab);
C_con_scon(expr->SG_VALUE, (arith)expr->SG_LEN);
C_lae_dlb(datlab, (arith)0);
1986-03-10 13:07:55 +00:00
}
break;
case Float: /* a floating constant */
if (gencode) {
label datlab = data_label();
C_df_dlb(datlab);
C_rom_fcon(expr->FL_VALUE, expr->ex_type->tp_size);
C_lae_dlb(datlab, (arith)0);
1986-03-10 13:07:55 +00:00
C_loi(expr->ex_type->tp_size);
}
break;
case Oper: /* compound expression */
{
register int oper = expr->OP_OPER;
register struct expr *leftop = expr->OP_LEFT;
register struct expr *rightop = expr->OP_RIGHT;
register struct type *tp = expr->OP_TYPE;
if (tp->tp_fund == ERRONEOUS) /* stop immediately */
break;
switch (oper) {
case '+':
/* We have the following possibilities :
int + int, pointer + int, pointer + long,
long + long, double + double
*/
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL);
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL);
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:
C_ads(rightop->ex_type->tp_size);
break;
case DOUBLE:
C_adf(tp->tp_size);
break;
default:
crash("bad type +");
}
}
break;
case '-':
if (leftop == 0) { /* unary */
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL);
if (gencode) {
switch (tp->tp_fund) {
case DOUBLE:
C_ngf(tp->tp_size);
break;
case INT:
case LONG:
case POINTER:
C_ngi(tp->tp_size);
break;
default:
CRASH();
}
}
break;
}
/* Binary: we have the following flavours:
int - int, pointer - int, pointer - long,
pointer - pointer, long - long, double - double
*/
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL);
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL);
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 (rightop->ex_type->tp_fund == POINTER)
1986-03-10 13:07:55 +00:00
C_sbs(pointer_size);
else {
C_ngi(rightop->ex_type->tp_size);
C_ads(rightop->ex_type->tp_size);
}
break;
case DOUBLE:
C_sbf(tp->tp_size);
break;
default:
crash("bad type -");
}
break;
case '*':
if (leftop == 0) /* unary */
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL);
else { /* binary */
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL);
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL);
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 DOUBLE:
C_mlf(double_size);
break;
default:
crash("bad type *");
}
}
break;
case '/':
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL);
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL);
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 DOUBLE:
C_dvf(double_size);
break;
default:
crash("bad type /");
}
break;
case '%':
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL);
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL);
if (gencode)
1986-03-17 17:47:04 +00:00
if ( tp->tp_fund == INT
|| tp->tp_fund == LONG
) {
1986-03-10 13:07:55 +00:00
if (tp->tp_unsigned)
C_rmu(tp->tp_size);
else
C_rmi(tp->tp_size);
}
else
crash("bad type %%");
break;
case LEFT:
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL);
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL);
if (gencode)
if (tp->tp_unsigned)
C_slu(tp->tp_size);
else
C_sli(tp->tp_size);
break;
case RIGHT:
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL);
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL);
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:
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL);
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL);
if (gencode) {
/* The operands have the same type */
1986-03-17 17:47:04 +00:00
arith size = leftop->ex_type->tp_size;
1986-03-10 13:07:55 +00:00
switch (tp->tp_fund) {
case INT:
case LONG:
if (leftop->ex_type->tp_unsigned)
1986-03-17 17:47:04 +00:00
C_cmu(size);
1986-03-10 13:07:55 +00:00
else
1986-03-17 17:47:04 +00:00
C_cmi(size);
1986-03-10 13:07:55 +00:00
break;
case FLOAT:
case DOUBLE:
1986-03-17 17:47:04 +00:00
C_cmf(size);
1986-03-10 13:07:55 +00:00
break;
case POINTER:
C_cmp();
break;
case ENUM:
1986-03-17 17:47:04 +00:00
C_cmi(size);
1986-03-10 13:07:55 +00:00
break;
default:
CRASH();
}
if (true_label != 0) {
compare(oper, true_label);
C_bra(false_label);
}
else {
label l_true = text_label();
label l_end = text_label();
compare(oper, l_true);
C_loc((arith)0);
C_bra(l_end);
C_df_ilb(l_true);
1986-03-10 13:07:55 +00:00
C_loc((arith)1);
C_df_ilb(l_end);
1986-03-10 13:07:55 +00:00
}
}
break;
case '&':
case '|':
case '^':
/* both operands should have type int */
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL);
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL);
if (gencode) {
arith size = tp->tp_size;
if (size < 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 (leftop->ex_type->tp_fund == FIELD) {
/* assignment to bitfield variable
*/
eval_field(expr, code);
break;
}
#endif NOBITFIELD
EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
if (gencode)
C_dup(ATW(tp->tp_size));
if (leftop->ex_class != Value) {
EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL);
store_block(tp->tp_size, tp->tp_align);
}
else
store_val(leftop->VL_IDF, leftop->ex_type,
leftop->VL_VALUE);
break;
case PLUSAB:
case MINAB:
case TIMESAB:
case DIVAB:
case MODAB:
case LEFTAB:
case RIGHTAB:
case ANDAB:
case XORAB:
case ORAB:
#ifndef NOBITFIELD
if (leftop->ex_type->tp_fund == FIELD) {
eval_field(expr, code);
break;
}
#endif NOBITFIELD
if (leftop->ex_class != Value) {
arith old_offset;
arith tmpvar = tmp_pointer_var(&old_offset);
EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL);
C_lal(tmpvar);
C_sti(pointer_size);
C_lal(tmpvar);
C_loi(pointer_size);
C_loi(tp->tp_size);
EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
assop(tp, oper);
if (gencode)
C_dup(roundup(tp->tp_size));
C_lal(tmpvar);
C_loi(pointer_size);
C_sti(tp->tp_size);
free_tmp_var(old_offset);
}
else {
load_val(leftop, RVAL);
EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
assop(tp, oper);
if (gencode)
C_dup(roundup(tp->tp_size));
store_val(leftop->VL_IDF, leftop->ex_type,
leftop->VL_VALUE);
}
break;
case '(':
{
register struct expr *expr;
arith ParSize = (arith)0;
if (expr = rightop) {
/* function call with parameters*/
while ( expr->ex_class == Oper &&
expr->OP_OPER == PARCOMMA
) {
EVAL(expr->OP_RIGHT, RVAL, TRUE,
NO_LABEL, NO_LABEL);
ParSize +=
ATW(expr->ex_type->tp_size);
expr = expr->OP_LEFT;
}
EVAL(expr, RVAL, TRUE, NO_LABEL, NO_LABEL);
ParSize += ATW(expr->ex_type->tp_size);
}
if (leftop->ex_class == Value && leftop->VL_IDF != 0) {
/* just an example:
main() { (*((int (*)())0))(); }
*/
C_cal(leftop->VL_IDF->id_text);
#ifdef DATAFLOW
{ extern char options[];
if (options['d'])
DfaCallFunction(
leftop->VL_IDF->id_text
);
}
#endif DATAFLOW
}
else {
EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL);
C_cai();
}
/* remove parameters from stack */
if (ParSize > (arith)0)
C_asp(ParSize);
if (!gencode)
break;
if (is_struct_or_union(tp->tp_fund)) {
C_lfr(pointer_size);
load_block(tp->tp_size, tp->tp_align);
}
else
C_lfr(ATW(tp->tp_size));
break;
}
case '.':
EVAL(leftop, LVAL, code, NO_LABEL, NO_LABEL);
if (gencode)
C_adp(rightop->VL_VALUE);
break;
case ARROW:
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL);
if (gencode)
C_adp(rightop->VL_VALUE);
break;
case ',':
EVAL(leftop, RVAL, FALSE, NO_LABEL, NO_LABEL);
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL);
break;
case '~':
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL);
if (gencode)
C_com(tp->tp_size);
break;
case POSTINCR:
case POSTDECR:
case PLUSPLUS:
case MINMIN:
{
arith old_offset, tmp;
arith esize = tp->tp_size;
#ifndef NOBITFIELD
if (leftop->ex_type->tp_fund == FIELD) {
eval_field(expr, code);
break;
}
#endif NOBITFIELD
if (leftop->ex_class != Value) {
tmp = tmp_pointer_var(&old_offset);
EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL);
C_dup(pointer_size);
C_lal(tmp);
C_sti(pointer_size);
C_loi(tp->tp_size);
}
else
load_val(leftop, RVAL);
/* We made the choice to put this stuff here
and not to put the conversion in the expression
tree because this conversion is EM dependent
and not described in C
*/
if (esize < word_size) {
conversion(tp, word_type);
esize = word_size;
}
if (gencode && (oper == POSTINCR || oper == POSTDECR))
C_dup(esize);
EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
assop(tp, oper);
if (gencode && (oper == PLUSPLUS || oper == MINMIN))
C_dup(esize);
if (tp->tp_size < word_size)
conversion(word_type, tp);
if (leftop->ex_class != Value) {
C_lal(tmp); /* always init'd */
C_loi(pointer_size);
C_sti(tp->tp_size);
free_tmp_var(old_offset);
}
else
store_val(leftop->VL_IDF, leftop->ex_type,
leftop->VL_VALUE);
break;
}
case '?': /* must be followed by ':' */
{
label l_true = text_label();
label l_false = text_label();
label l_end = text_label();
EVAL(leftop, RVAL, TRUE, l_true, l_false);
C_df_ilb(l_true);
1986-03-17 17:47:04 +00:00
EVAL(rightop->OP_LEFT, RVAL, code,
NO_LABEL, NO_LABEL);
1986-03-10 13:07:55 +00:00
C_bra(l_end);
C_df_ilb(l_false);
1986-03-17 17:47:04 +00:00
EVAL(rightop->OP_RIGHT, RVAL, code,
NO_LABEL, NO_LABEL);
C_df_ilb(l_end);
1986-03-10 13:07:55 +00:00
break;
}
case AND:
if (true_label == 0) {
label l_true = text_label();
label l_false = text_label();
label l_maybe = text_label();
label l_end = text_label();
EVAL(leftop, RVAL, TRUE, l_maybe, l_false);
C_df_ilb(l_maybe);
1986-03-10 13:07:55 +00:00
if (gencode) {
EVAL(rightop, RVAL, TRUE,
l_true, l_false);
C_df_ilb(l_true);
1986-03-10 13:07:55 +00:00
C_loc((arith)1);
C_bra(l_end);
C_df_ilb(l_false);
1986-03-10 13:07:55 +00:00
C_loc((arith)0);
C_df_ilb(l_end);
1986-03-10 13:07:55 +00:00
}
else {
EVAL(rightop, RVAL, FALSE, l_false,
l_false);
C_df_ilb(l_false);
1986-03-10 13:07:55 +00:00
}
}
else {
label l_maybe = text_label();
EVAL(leftop, RVAL, TRUE, l_maybe, false_label);
C_df_ilb(l_maybe);
1986-03-10 13:07:55 +00:00
EVAL(rightop, RVAL, code, true_label,
false_label);
}
break;
case OR:
if (true_label == 0) {
label l_true = text_label();
label l_false = text_label();
label l_maybe = text_label();
label l_end = text_label();
EVAL(leftop, RVAL, TRUE, l_true, l_maybe);
C_df_ilb(l_maybe);
1986-03-10 13:07:55 +00:00
if (gencode) {
EVAL(rightop, RVAL, TRUE,
l_true, l_false);
C_df_ilb(l_false);
1986-03-10 13:07:55 +00:00
C_loc((arith)0);
C_bra(l_end);
C_df_ilb(l_true);
1986-03-10 13:07:55 +00:00
C_loc((arith)1);
C_df_ilb(l_end);
1986-03-10 13:07:55 +00:00
}
else {
EVAL(rightop, RVAL, FALSE, l_true,
l_true);
C_df_ilb(l_true);
1986-03-10 13:07:55 +00:00
}
}
else {
label l_maybe = text_label();
EVAL(leftop, RVAL, TRUE, true_label, l_maybe);
C_df_ilb(l_maybe);
1986-03-10 13:07:55 +00:00
EVAL(rightop, RVAL, code, true_label,
false_label);
}
break;
case '!':
if (true_label == 0) {
if (gencode) {
label l_true = text_label();
label l_false = text_label();
label l_end = text_label();
EVAL(rightop, RVAL, TRUE,
l_false, l_true);
C_df_ilb(l_false);
1986-03-10 13:07:55 +00:00
C_loc((arith)0);
C_bra(l_end);
C_df_ilb(l_true);
1986-03-10 13:07:55 +00:00
C_loc((arith)1);
C_df_ilb(l_end);
1986-03-10 13:07:55 +00:00
}
else
EVAL(rightop, RVAL, FALSE,
NO_LABEL, NO_LABEL);
}
else
EVAL(rightop, RVAL, code, false_label,
true_label);
break;
case INT2INT:
case INT2FLOAT:
case FLOAT2INT:
case FLOAT2FLOAT:
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL);
if (gencode)
conversion(rightop->ex_type, leftop->ex_type);
break;
default:
crash("(EVAL) bad operator %s\n", symbol2str(oper));
1986-03-10 13:07:55 +00:00
}
/* 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)
load_block(expr->ex_type->tp_size,
expr->ex_type->tp_align);
break;
}
case Type:
default:
crash("(EVAL) bad expression class");
}
}
/* compare() serves as an auxiliary function of EVAL */
compare(relop, lbl)
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();
}
}
/* assop() generates the opcode of an assignment operators op= */
assop(type, oper)
struct type *type;
int oper;
{
register arith size = type->tp_size;
register uns = type->tp_unsigned;
if (size < 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:
switch (oper) {
case PLUSAB:
case PLUSPLUS:
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);
C_ads(size);
break;
case ERRONEOUS:
break;
default:
crash("(assop) bad type %s\n", symbol2str(type->tp_fund));
}
}
/* tmp_pointer_var() returns the EM address of a new temporary
pointer variable needed at increment, decrement and assignment
operations to store the address of some variable or lvalue-expression.
*/
arith
tmp_pointer_var(oldoffset)
arith *oldoffset; /* previous allocated address */
{
struct stack_level *stl = local_level;
*oldoffset = stl->sl_local_offset;
stl->sl_local_offset =
- align(-stl->sl_local_offset + pointer_size, pointer_align);
if (stl->sl_local_offset < stl->sl_max_block)
stl->sl_max_block = stl->sl_local_offset;
return stl->sl_local_offset;
}
/* free_tmp_var() returns the address allocated by tmp_pointer_var()
and resets the last allocated address.
*/
free_tmp_var(oldoffset)
arith oldoffset;
{
local_level->sl_local_offset = oldoffset;
}
/* 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
When the destination is described by an (lvalue) expression, the call
is "store_val(ex->VL_IDF, ex->ex_type, ex->VL_VALUE)"
*/
store_val(id, tp, offs)
register struct idf *id;
struct type *tp;
arith offs;
{
arith size = tp->tp_size;
int tpalign = tp->tp_align;
if (id) {
register struct def *df = id->id_def;
int al_on_word = (tpalign % word_align == 0);
register inword = (size == word_size && al_on_word);
register indword = (size == dword_size && al_on_word);
if (df->df_level == L_GLOBAL) {
if (inword)
C_ste_dnam(id->id_text, offs);
else
if (indword)
C_sde_dnam(id->id_text, offs);
else {
C_lae_dnam(id->id_text, offs);
store_block(size, tpalign);
}
}
else
if (df->df_sc == STATIC) {
if (inword)
C_ste_dlb((label)df->df_address, offs);
1986-03-10 13:07:55 +00:00
else
if (indword)
C_sde_dlb((label)df->df_address, offs);
1986-03-10 13:07:55 +00:00
else {
C_lae_dlb((label)df->df_address, offs);
1986-03-10 13:07:55 +00:00
store_block(size, tpalign);
}
}
else {
if (inword)
C_stl(df->df_address + offs);
else
if (indword)
C_sdl(df->df_address + offs);
else {
C_lal(df->df_address + offs);
store_block(size, tpalign);
df->df_register = REG_NONE;
}
}
}
else { /* absolute addressing */
load_cst(offs, pointer_size);
store_block(size, tpalign);
}
}
/* 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
*/
load_val(expr, val)
struct expr *expr; /* expression containing the value */
int val; /* generate either LVAL or RVAL */
{
register struct idf *id;
register struct type *tp = expr->ex_type;
register struct def *df;
register rvalue = (val == RVAL && expr->ex_lvalue != 0);
register arith exval = expr->VL_VALUE;
register arith size = tp->tp_size;
register tpalign = tp->tp_align;
register al_on_word = (tpalign % word_align == 0);
if ((id = expr->VL_IDF) == 0) {
/* Note: enum constants are also dealt with here */
if (rvalue) {
/* absolute addressing
*/
load_cst(exval, pointer_size);
load_block(size, tpalign);
}
else /* integer, unsigned, long, enum etc */
load_cst(exval, size);
}
else
if ((df = id->id_def)->df_type->tp_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) {
if (rvalue) {
if (size == word_size && al_on_word)
C_loe_dnam(id->id_text, exval);
else
if (size == dword_size && al_on_word)
C_lde_dnam(id->id_text, exval);
else {
C_lae_dnam(id->id_text, exval);
load_block(size, tpalign);
}
}
else {
C_lae_dnam(id->id_text, (arith)0);
C_adp(exval);
}
}
else
if (df->df_sc == STATIC) {
if (rvalue) {
if (size == word_size && al_on_word)
C_loe_dlb((label)df->df_address, exval);
1986-03-10 13:07:55 +00:00
else
if (size == dword_size && al_on_word)
C_lde_dlb((label)df->df_address, exval);
1986-03-10 13:07:55 +00:00
else {
C_lae_dlb((label)df->df_address, exval);
1986-03-10 13:07:55 +00:00
load_block(size, tpalign);
}
}
else {
C_lae_dlb((label)df->df_address, (arith)0);
1986-03-10 13:07:55 +00:00
C_adp(exval);
}
}
else {
if (rvalue) {
if (size == word_size && al_on_word)
C_lol(df->df_address + exval);
else
if (size == dword_size && al_on_word)
C_ldl(df->df_address + exval);
else {
C_lal(df->df_address + exval);
load_block(size, tpalign);
df->df_register = REG_NONE;
}
}
else {
/* following code may be used when
comparing addresses as in the following
example:
f() {
int a[10], *i;
for (i = &a[0]; i < &a[10]; i++) ...;
}
We don't accept the contents of a[10] to
be legitimate, so the RVAL of it may
contain a big mess.
*/
C_lal(df->df_address);
C_adp(exval);
df->df_register = REG_NONE;
}
}
}
load_cst(val, siz)
arith val, siz;
{
if (siz <= word_size)
C_loc(val);
else
if (siz == dword_size)
C_ldc(val);
else {
label datlab;
C_df_dlb(datlab = data_label());
1986-03-26 16:58:43 +00:00
C_rom_icon(long2str((long)val, 10), siz);
C_lae_dlb(datlab, (arith)0);
1986-03-10 13:07:55 +00:00
C_loi(siz);
}
}