home *** CD-ROM | disk | FTP | other *** search
- /*
- * @(#)genexp.c 1.7 2/23/90
- */
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <errno.h>
-
- #include "assert.h"
- #include "addresses.h"
- #include "nodes.h"
- #include "map.h"
- #include "sequence.h"
- #include "system.h"
- #include "semantics.h"
- #include "builtins.h"
- #include "evaluate.h"
- #include "opNames.h"
- #include "primitives.h"
- #include "allocate.h"
- #include "MyParser.h"
- #include "datadesc.h"
- #include "environment.h"
- #include "regdefs.h"
- #include "genutils.h"
- #include "emit.h"
- #include "error.h"
- #include "consts.h"
- #include "flags.h"
- #include "trace.h"
- #include "option.h"
-
- /*
- * Imported routines
- */
- extern void moveDataToRegister(), moveVariableToRegisters(), claimReg();
- extern void resolveGlobal();
- extern void findTemp();
- extern DD generateCreation();
- extern Boolean isARealImport();
- extern NodePtr newExecuteAsAT(), tryToExecuteAsAT();
- extern void generateInvocation();
- extern NodePtr buildOpName();
- /*
- * Global variables
- */
-
- extern int cEM_locates;
-
- /*
- * Exported definitions
- */
-
- /*
- * Local definitions
- */
-
- /*
- * Forward definitions
- */
-
- void generateExpression(), generateExp(), generateUnaryExp();
- void generate(), generateVectorLiteral();
-
- void generateExpression(p, c)
- NodePtr p;
- Context c;
- {
- Variable result, *v;
- register Symbol st;
- NodePtr setqs, q, r;
- Symbol sym;
-
- assert((int)p >= 0x200);
- result.data = nullDD;
- result.abCon = nullDD;
- switch (p->tag) {
- case P_ARG:
- /* ignore p->b.arg.move */
- generateExpression(p->b.arg.exp, c);
- break;
- case P_SYMDEF:
- case P_SYMREF:
- st = ST_Fetch(p->b.symref.symbol);
- vPushSymbol(st, c);
- break;
- case P_BUILTINLIT:
- case P_NILLIT:
- case P_BOOLLIT:
- case P_INTLIT:
- case P_STRINGLIT:
- case P_CHARLIT:
- case P_REALLIT:
- vPushValue(p, c);
- break;
- case P_GLOBALREF:
- resolveGlobal(p, (ValuePtr) NULL);
- generateExpression(p->b.globalref.value, c);
- break;
- case P_ATLIT:
- generate(p);
- vPushValue(p, c);
- break;
- case P_OBLIT:
- generate(p);
- result.abCon = buildAbConFromObject(p);
- if (p == currentObject) {
- result.data.kind = DD_Self;
- } else if (p->b.oblit.f.writeSeparately) {
- /*
- * This is an object that the compiler created, so the value of this
- * expression is just a reference to the object.
- */
- result.data.kind = DD_OIDToODP;
- result.data.value.id = p->b.oblit.id;
- } else if (p->b.oblit.f.isTypeVariable ||
- p->b.oblit.f.dependsOnTypeVariable) {
- ErrorMessage(p,
- "This object depends on a type parameter and cannot be created");
- } else {
- /*
- * This is needs to be translated into a call of the kernel.create
- * primitive to actually build a new object.
- */
- /*
- * Allocate the space on the stack for the result.
- */
- IFOPTION(createonstack, 1 &&
- p->b.oblit.codeOID != OIDOfBuiltin(B_INSTCT, STRINGINDEX)) {
- emitMove(result.abCon, pusher, 'l');
- emitMove(nilDD, pusher, 'l');
- }
- /*
- * Prepare the parameters to the initially of the object.
- */
- setqs = p->b.oblit.setq;
- Sequence_For(q, setqs)
- /*
- * Charge through the setq list and find the non-manifest ones and
- * push their values on the stack.
- */
- assert(q->tag == P_SETQ);
- r = q->b.setq.inner;
- assert(r->tag == P_SYMDEF);
- sym = ST_Fetch(r->b.symdef.symbol);
- if (isARealImport(sym, TRUE)) {
- /*
- * This is a real import. We need to push the current value of
- * outer on the stack.
- */
- r = q->b.setq.outer;
- vPush(pusherContext.v);
- generateExpression(r, pusherContext);
- vGenerateAssign();
- }
- Sequence_Next
- result.data = generateCreation(p, FALSE,
- (Boolean)(OPTION(locals,1) && p->b.oblit.f.doLocalCreate));
- }
- vPush(result);
- break;
- case P_INVOC:
- generateInvocation(p, 1, c);
- break;
- case P_EXP:
- generateExp(p, c);
- break;
- case P_UNARYEXP:
- generateUnaryExp(p, c);
- break;
- case P_VECTORLIT:
- generateVectorLiteral(p);
- break;
- case P_VIEW:
- generateExpression(p->b.view.exp, anyContext);
- if (p->b.view.isRedundant) {
- IFOPTION(comment, 1) Comment("\t\t\t\tRedundant view expression");
- } else {
- v = vPeek(0);
- q = newExecuteAsAT(p->b.view.type);
- assert(q->tag == P_ATLIT);
- moveVariableToRegisters(v, regs_arg1);
- IFOPTION(view, 1) {
- result.data = buildManifestDD((int)q->b.atlit.id);
- ensureGenerate(q->b.atlit.id);
- result.abCon = buildConCon(INTEGERINDEX);
- moveDataToRegister(&result, regs_arg3, DataBrand);
- preemptReg(regs_scratch, 1);
- generateKernelCall("em_tryview");
- } else IFOPTION(view, 2) {
- result.data.kind = DD_OIDToCodePtr;
- result.data.value.id = q->b.atlit.id;
- ensureGenerate(q->b.atlit.id);
- result.abCon = buildConCon(SIGNATUREINDEX);
- moveDataToRegister(&result, regs_arg3, ODPBrand);
- preemptReg(regs_scratch, 1);
- generateKernelCall("em_tryviewptr");
- } else {
- assert(FALSE);
- }
- vDiscard();
- freeReg(regs_arg3, 1);
- claimReg(regs_arg1, 2, VariableBrand);
- result.data = buildRegisterDD(regs_arg1);
- result.abCon = nextAddress(result.data);
- setDDAbstractType(result.abCon, q->b.atlit.id);
- vPush(result);
- }
- break;
- case P_RESTRICT:
- generateExpression(p->b.restrict.exp, anyContext);
- v = vPeek(0);
- q = newExecuteAsAT(p->b.restrict.type);
- assert(q->tag == P_ATLIT);
- moveVariableToRegisters(v, regs_arg1);
- result.data.kind = DD_OIDToCodePtr;
- result.data.value.id = q->b.atlit.id;
- ensureGenerate(q->b.atlit.id);
- result.abCon = buildConCon(SIGNATUREINDEX);
- moveDataToRegister(&result, regs_arg3, ODPBrand);
- preemptReg(regs_scratch, 1);
- generateKernelCall("em_restrictptr");
- vDiscard();
- freeReg(regs_arg3, 1);
- claimReg(regs_arg1, 2, VariableBrand);
- result.data = buildRegisterDD(regs_arg1);
- result.abCon = nextAddress(result.data);
- setDDAbstractType(result.abCon, q->b.atlit.id);
- vPush(result);
- break;
- default:
- ErrorMessage(p, "Garbage in generateExpression");
- assert(FALSE);
- vPush(result);
- break;
- }
- }
-
- Boolean allAreManifest(p)
- register NodePtr p;
- {
- register NodePtr q;
- Sequence_For(q, p->b.vectorlit.exp)
- if (!isATrivialLiteral(q)) return(FALSE);
- if (q->tag == P_STRINGLIT) return(FALSE);
- Sequence_Next
- return(TRUE);
- }
-
- void generateVectorLiteral(p)
- NodePtr p;
- {
- NodePtr vt, q, instct;
- Symbol elementTypeSymbol;
- int elementTypeSize;
- Variable etsv, *ets = &etsv, ctv, *ct = &ctv, result, nev, *ne = &nev;
-
- assert(p->tag == P_VECTORLIT);
- vt = p->b.vectorlit.vectorType;
- assert(vt != NN);
- vt = GETVALUE(vt);
- assert(vt->tag == P_OBLIT);
- assert(vt->b.oblit.f.writeSeparately);
- assert(vt->b.oblit.f.isManifest);
- assert(vt->b.oblit.id != 0);
- ensureGenerate(vt->b.oblit.id);
-
- instct = findInstCode(vt);
- assert(instct != NULL);
- assert(instct->tag == P_OBLIT);
-
- ct->data.kind = DD_OIDToCodePtr;
- ct->data.value.id = getCodeOID(instct);
- ct->abCon = buildAbConFromObject(instct);
-
- elementTypeSymbol = getElementTypeSymbol(instct);
- elementTypeSize = getSymbolSize(elementTypeSymbol);
-
- if (allAreManifest(p)) {
- if (!doGenerateCode)
- TRACE1(generate, 1, "A manifest vectorliteral on line %d",
- p->lineNumber);
- result.data.kind = DD_Label;
- result.data.value.label = nextLabelNumber++;
- result.abCon = ct->abCon;
- squirrelVectorLiteral(result.data.value.label, p, elementTypeSize,
- getCodeOID(instct));
- vPush(result);
- return;
- }
- TS_StartInvocation();
- IFOPTION(createonstack, 1) {
- emitMove(ct->abCon, pusher, 'l');
- emitMove(nilDD, pusher, 'l');
- }
-
- Sequence_For(q, p->b.vectorlit.exp)
- vPush(pusherContext.v);
- generateExpression(q, pusherContext);
- vGenerateAssign();
- TS_Push();
- Sequence_Next
- TS_EndInvocation();
-
- ne->data = buildManifestDD(Sequence_Length(p->b.vectorlit.exp));
- ne->abCon = buildConCon(INTEGERINDEX);
- moveDataToRegister(ne, regs_arg3, DataBrand);
-
- ets->data = buildManifestDD(elementTypeSize);
- ets->abCon = buildConCon(INTEGERINDEX);
- moveDataToRegister(ets, regs_arg2, DataBrand);
-
- result.abCon = ct->abCon;
- moveDataToRegister(ct, regs_arg1, ODPBrand);
-
- preemptReg(regs_scratch, 1);
- #ifdef MUTABLEVECTORLITERALS
- if (OPTION(locals, 1) && p->b.vectorlit.f.doLocalCreate) {
- generateKernelCall("em_localCreateVectorLiteral");
- } else {
- generateKernelCall("em_globalCreateVectorLiteral");
- }
- #else
- generateKernelCall("em_localCreateVectorLiteral");
- #endif
- FREEV(ets);
- FREEV(ct);
- FREEV(ne);
- claimReg(regs_arg1, 1, ODPBrand);
- result.data = buildRegisterDD(regs_arg1);
- IFOPTION(createonstack, 1) {
- emitMove(popper, result.data, 'l');
- emit(POPABCON);
- }
- vPush(result);
- }
-
-
- /*ARGSUSED*/
- void generateExp(p, c)
- NodePtr p;
- Context c;
- {
- Variable resultV, *result = &resultV, *left, *right, answer, rightV, leftV;
- Variable temp;
- NodePtr q, r, eleft;
- int truelabel, falselabel, endlabel;
- result->data = nullDD;
- result->abCon = nullDD;
-
- assert(p->tag == P_EXP);
- switch (p->b.exp.op) {
- case KOR:
- findTemp(result, 4, DataBrand);
- result->abCon = buildConCon(BOOLEANINDEX);
- vPush(*result);
- result = vPeek(0);
- truelabel = nextLabelNumber++;
- falselabel = nextLabelNumber++;
- endlabel = nextLabelNumber++;
- generateExpression(p->b.exp.left, pslContext);
- generateBranch(TRUE, truelabel);
- generateExpression(p->b.exp.right, pslContext);
- generateBranch(TRUE, truelabel);
- answer.data = buildManifestDD(0);
- answer.abCon = buildConCon(BOOLEANINDEX);
- ddGenerateAssign(result->data, result->abCon, answer.data, answer.abCon);
- emit("\tj%s\tL_%d\n", JN(ALWAYS), endlabel);
- emit("L_%d:\n", truelabel);
- answer.data = buildManifestDD(1);
- answer.abCon = buildConCon(BOOLEANINDEX);
- ddGenerateAssign(result->data, result->abCon, answer.data, answer.abCon);
- emit("L_%d:\n", endlabel);
- break;
- case KAND:
- findTemp(result, 4, DataBrand);
- vPush(*result);
- result = vPeek(0);
- result->abCon = buildConCon(BOOLEANINDEX);
- truelabel = nextLabelNumber++;
- falselabel = nextLabelNumber++;
- endlabel = nextLabelNumber++;
- generateExpression(p->b.exp.left, pslContext);
- generateBranch(FALSE, falselabel);
- generateExpression(p->b.exp.right, pslContext);
- generateBranch(FALSE, falselabel);
- answer.data = buildManifestDD(1);
- answer.abCon = buildConCon(BOOLEANINDEX);
- ddGenerateAssign(result->data, result->abCon, answer.data, answer.abCon);
- emit("\tj%s\tL_%d\n", JN(ALWAYS), endlabel);
- emit("L_%d:\n", falselabel);
- answer.data = buildManifestDD(0);
- answer.abCon = buildConCon(BOOLEANINDEX);
- ddGenerateAssign(result->data, result->abCon, answer.data, answer.abCon);
- emit("L_%d:\n", endlabel);
- break;
- case OIDENTITY:
- case ONOTIDENTITY:
- result->abCon = buildConCon(BOOLEANINDEX);
- generateExpression(p->b.exp.left, anyContext);
- left = vPeek(0);
- vForceToTemp(left, TS_All);
- generateExpression(p->b.exp.right, anyContext);
- right = vPeek(0);
- vForceToTemp(right, TS_All);
- currentInstruction = nextLabelNumber++;
- result->data =
- generateCompare(left, right, 'l', p->b.exp.op == OIDENTITY ? EQL : NEQ);
- vDiscard();
- vDiscard();
- vPush(*result);
- break;
- case OCONFORMSTO:
- /* Try to execute the left operand as an AT. */
- r = tryToExecuteAsAT(p->b.exp.left);
- if (r == NULL) {
- eleft = p->b.exp.left;
- if (! conforms(evaluateForAT(eleft, TRUE),
- refToBuiltin(B_INSTAT, SIGNATUREINDEX))) {
- eleft = Construct(P_INVOC, 3,
- eleft,
- buildOpName("getsignature", -1),
- NN);
- }
- generateExpression(eleft, anyContext);
- left = vPeek(0);
- moveDataToRegister(left, regs_arg1, DataBrand);
- emitMove(buildAddressDD(regs_arg1, /* Code_ownOID */ 4), buildRegisterDDNC(regs_arg1), 'l');
- } else {
- assert(r->tag == P_ATLIT);
- assert(r->b.atlit.id != 0);
- left = &leftV;
- left->abCon = buildConCon(INTEGERINDEX);
- left->data = buildManifestDD((int)r->b.atlit.id);
- ensureGenerate(r->b.atlit.id);
- moveDataToRegister(left, regs_arg1, DataBrand);
- }
- q = newExecuteAsAT(p->b.exp.right);
- assert(q != NULL);
- assert(q->tag == P_ATLIT);
- assert(q->b.atlit.id != 0);
- right = &rightV;
- right->abCon = buildConCon(INTEGERINDEX);
- right->data = buildManifestDD((int)q->b.atlit.id);
- ensureGenerate(q->b.atlit.id);
- moveDataToRegister(right, regs_arg2, DataBrand);
- preemptReg(regs_scratch, 1);
- preemptReg(regs_arg3, 1);
- generateKernelCall("em_conform");
- FREEV(left);
- FREEV(right);
- claimReg(regs_arg1, 1, DataBrand);
- result->abCon = buildConCon(BOOLEANINDEX);
- result->data = buildRegisterDD(regs_arg1);
- if (r == NULL) {
- vDiscard();
- }
- vPush(*result);
- break;
- default:
- assert(FALSE);
- break;
- }
- }
-
- /*ARGSUSED*/
- void generateUnaryExp(p, c)
- NodePtr p;
- Context c;
- {
- Variable result;
-
- assert(p->tag == P_UNARYEXP);
- switch (p->b.unaryexp.op) {
- case KAWAITING:
- generateExpression(p->b.unaryexp.exp, anyContext);
- moveDataToRegister(vPeek(0), regs_arg1, ODPBrand);
- preemptReg(regs_scratch, 1);
- preemptReg(regs_arg2, 2);
- generateKernelCall("em_condAwaiting");
- vDiscard();
- claimReg(regs_arg1, 1, DataBrand);
- result.data = buildRegisterDD(regs_arg1);
- result.abCon = buildConCon(BOOLEANINDEX);
- break;
- case KISFIXED:
- generateExpression(p->b.unaryexp.exp, anyContext);
- moveVariableToRegisters(vPeek(0), regs_arg1);
- preemptReg(regs_scratch, 1);
- preemptReg(regs_arg3, 1);
- generateKernelCall("em_isFixed");
- vDiscard();
- claimReg(regs_arg1, 1, DataBrand);
- result.data = buildRegisterDD(regs_arg1);
- result.abCon = buildConCon(BOOLEANINDEX);
- break;
- case KLOCATE:
- generateExpression(p->b.unaryexp.exp, anyContext);
- moveVariableToRegisters(vPeek(0), regs_arg1);
- preemptReg(regs_scratch, 1);
- preemptReg(regs_arg3, 1);
- INC(cEM_locates);
- generateKernelCall("em_locate");
- vDiscard();
- claimReg(regs_arg1, 1, ODPBrand);
- result.data = buildRegisterDD(regs_arg1);
- result.abCon = buildConCon(NODEINDEX);
- break;
- default:
- assert(FALSE);
- break;
- }
- vPush(result);
- }
-