⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mal_compiler.mx

📁 一个内存数据库的源代码这是服务器端还有客户端
💻 MX
字号:
@' The contents of this file are subject to the MonetDB Public License@' Version 1.1 (the "License"); you may not use this file except in@' compliance with the License. You may obtain a copy of the License at@' http://monetdb.cwi.nl/Legal/MonetDBLicense-1.1.html@'@' Software distributed under the License is distributed on an "AS IS"@' basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the@' License for the specific language governing rights and limitations@' under the License.@'@' The Original Code is the MonetDB Database System.@'@' The Initial Developer of the Original Code is CWI.@' Portions created by CWI are Copyright (C) 1997-2007 CWI.@' All Rights Reserved.@f mal_compiler@a M. L. Kersten@+ MAL compilationOne of the last resorts to gain performance is tocompile the MAL into C, followed by compilationand dynamic linkage.The facility is offered as one of the optimizationsteps.The current translation scheme is chosen forsimplicity and is particularly aimed atremoving the MAL interpreter overhead.To best result is most likely obtained afterthe other MAL optimizers have performed their job.This may involve code in-lining steps specificallygeared at producing C later on.To illustrate the process consider the MAL function below (actual a fragment of tst903 from the test suite).It contains most of the language features.@examplefunction tst903();    b:= new(:void,:lng);    barrier (go,i):= newRange(0:lng);        k:= rand();        l:= lng(k);        insert(b,nil,l);        redo (go,i):= nextElement(1:lng,1000000:lng);    exit (go,i);end tst903;@end exampleThe C code is derived in a few steps. First the variablesare collected from the symbol table and turned into aninitialized C variable. Thereafter, we simple producefunction calls for each MAL instruction and plug inthe required flow of control statements.Notice that each instruction may produce an exception,which should be catched. Of course the resulting code is not optimal, e.g.the following portion for the example is produced:@examplestr MCC_Admin_tst903(void *tst903){        BAT *b= 0; /* bat[:void,:lng] */        void T2 = 0;        lng T3 = 0;        bit go = 0;        lng i = 0;        lng T6 = 0;        int k = 0;        lng l = 0;        void T10 = nil;        lng T11 = 1;        lng T12 = 1000000;        if( Xmsg = CMDBATnew(&b,&T2,&T3) ) return Xmsg;        if( Xmsg = RNGnewRange_lng(&go,&i,&T6) ) return Xmsg;        if( !( go == 0 ||go== bit_nil) ) goto EXIT_7;BARRIER_3:        if( Xmsg = CALCrandint(&k) ) return Xmsg;        if( Xmsg = CALCint2lng(&l,&k) ) return Xmsg;        if( Xmsg = BKCinsert_bun(&T9,&b,&T10,&l) ) return Xmsg;        if( Xmsg = RNGnextElement_lng(&go,&i,&T11,&T12) ) return Xmsg;        if(  go == 0 ||go== bit_nil ) goto BARRIER_3;EXIT_7: ;}@end exampleThis models a for-loop over an integer range andcontains an expensive coercion.One way to improve code generation is to associatea code string to each MAL signature, and makeexception handling explicit.@- LimitationsThe current implementation only handles translationof command calls and multiplex statements over commands.Patterns should be handled differently, e.g.  CMDBATnewin the example above would make this program notexecutable.@malmodule compiler;pattern MALtoC(mod:str, fcn:str):voidaddress MCdynamicCompilercomment "MAL to C compiler for functions";@{@h#ifndef _MAL_COMPILER_H_#define _MAL_COMPILER_H_#include "mal.h"#include "mal_client.h"#define DEBUG_MAL_COMPILER#ifdef WIN32#ifndef LIBMAL_COMPILER#define mal_compiler_export extern __declspec(dllimport)#else#define mal_compiler_export extern __declspec(dllexport)#endif#else#define mal_compiler_export extern#endifmal_compiler_export str MCdynamicCompiler(MalBlkPtr mb, MalStkPtr stk, InstrPtr p);#endif /* _MAL_COMPILER_H_ */@-@c#include "mal_config.h"#include "mal_compiler.h"#include "mal_interpreter.h"#include "mal_function.h"static char *mccPrelude[] = {	"/* MAL to C compiler\n",	"   Copyright (c) 2001-2007, CWI.\n",	"   All rights reserved.\n",	" \n",	"   The current version does not yet\n",	"   support THREAD blocks\n",	"*/\n",	"#include \"mal.h\"\n",	"#include \"mal_function.h\"\n",	"#define BAT int\n",	/* the interface works on BAT ids */	0};voidmccVar(stream *f, MalBlkPtr mb, int i){	if (isTmpVar(mb, i))		stream_printf(f, "T%d", mb->var[i]->tmpindex);	else		stream_printf(f, "%s", mb->var[i]->name);}voidmccArg(stream *f, MalBlkPtr mb, int i){	stream_printf(f, "&");	mccVar(f, mb, i);}voidmccValue(stream *f, MalBlkPtr mb, int i){	int (*tostr) (str *, int *, ptr);	str buf = 0, c;	int sz = 0;	ValPtr val;	val = &getVarConstant(mb, i);	if (val->vtype == TYPE_str) {		stream_printf(f, "\"%s\"", val->val.sval);	} else {		tostr = BATatoms[val->vtype].atomToStr;		(*tostr) (&buf, &sz, VALptr(val));		c = strchr(buf, '@');		if (c && *(c + 1) == '0')			*c = 0;		stream_printf(f, "%s", buf);		GDKfree(buf);	}}voidmccType(stream *f, MalBlkPtr mb, int i){	str tpe;	tpe = getTypeName(getVarType(mb, i));	if (strcmp(tpe, "void") == 0) {		stream_printf(f, "void *");	} else if (isaBatType(getVarType(mb, i))) {		stream_printf(f, "BAT *");	} else {		stream_printf(f, "%s *", tpe);	}	GDKfree(tpe);}voidmccInit(stream *f, MalBlkPtr mb){	int i, j;	InstrPtr p;	for (i = 0; mccPrelude[i]; i++)		stream_printf(f, "%s", mccPrelude[i]);	p = getInstrPtr(mb, 0);	stream_printf(f, "str MCC%s_%s(", getModuleId(p), getFunctionId(p));	if (p->argc > 0) {		mccType(f, mb, i);		mccVar(f, mb, getArg(p, 0));		for (j = 1; j < p->argc; j++) {			stream_printf(f, ",");			mccType(f, mb, i);			mccVar(f, mb, getArg(p, j));		}	}	stream_printf(f, ")\n{\n");}voidmccVariables(stream *f, MalBlkPtr mb){	int i;	str tpe, v;	for (i = 1; i < mb->vtop; i++) {		tpe = getTypeName(getVarType(mb, i));		v = getVarName(mb, i);		if (isTmpVar(mb, i))			*v = 'V';		if (getVarType(mb, i) == TYPE_void) {			stream_printf(f, "\tvoid *");			mccVar(f, mb, i);			stream_printf(f, "= 0; /* %s */\n", tpe);		} else if (isaBatType(getVarType(mb, i))) {			stream_printf(f, "\tBAT *");			mccVar(f, mb, i);			stream_printf(f, "= 0; /* %s */\n", tpe);		} else {			stream_printf(f, "\t%s ", tpe);			mccVar(f, mb, i);			stream_printf(f, " = ");			mccValue(f, mb, i);			stream_printf(f, ";\n");		}		GDKfree(tpe);	}	/* if( isTmpVar(mb,i) ) GDKfree(v); */	stream_printf(f, "\tstr Xmsg = MAL_SUCCEED;\n");}voidmccEntry(stream *f, MalBlkPtr mb, int i){	switch (getVarType(mb, i)) {	case TYPE_void:		stream_printf(f, "1");		break;	case TYPE_bit:		mccVar(f, mb, i);		stream_printf(f, " == 0 ||");		mccVar(f, mb, i);		stream_printf(f, "== bit_nil");		break;	case TYPE_chr:		mccVar(f, mb, i);		stream_printf(f, "== chr_nil");		break;	case TYPE_sht:		mccVar(f, mb, i);		stream_printf(f, " < 0 ||");		mccVar(f, mb, i);		stream_printf(f, "== sht_nil");		break;	case TYPE_int:		mccVar(f, mb, i);		stream_printf(f, " < 0 ||");		mccVar(f, mb, i);		stream_printf(f, "== int_nil");		break;	case TYPE_lng:		mccVar(f, mb, i);		stream_printf(f, " < 0 ||");		mccVar(f, mb, i);		stream_printf(f, "== lng_nil");		break;	case TYPE_flt:	case TYPE_dbl:		mccVar(f, mb, i);		stream_printf(f, " < 0 ||");		mccVar(f, mb, i);		stream_printf(f, "== dbl_nil");		break;	case TYPE_oid:		mccVar(f, mb, i);		stream_printf(f, "== oid_nil");		break;	case TYPE_str:		stream_printf(f, " strlen(");		mccVar(f, mb, i);		stream_printf(f, ") == 0 ||");		mccVar(f, mb, i);		stream_printf(f, "== str_nil");		break;	default:		stream_printf(f, "/* Unknown barrier :%d */", getVarType(mb, i));	}}@-Before we generate code, we should check existence ofCATCH blocks. If they do not exist, then any exceptionterminates the function. Otherwise, we jump to the first one.@cintmccInstruction(stream *f, MalBlkPtr mb, InstrPtr p, int i, int *catch, int *ctop){	int errors = 0;	int j;	if (p->barrier == EXITsymbol)		stream_printf(f, "EXIT_%d: ;\n", i);	if (p->barrier == CATCHsymbol) {		stream_printf(f, "CATCH_%d:\n", i);		stream_printf(f, "if( ");		mccVar(f, mb, getArg(p, 0));		stream_printf(f, " == MAL_SUCCEED) goto EXIT_%d;\n", p->jump);		return errors;	}	if (p->blk && p->blk->binding) {		stream_printf(f, "\tif( Xmsg = ");		stream_printf(f, "%s(", p->blk->binding);		mccArg(f, mb, getArg(p, 0));		for (j = 1; j < p->argc; j++) {			stream_printf(f, ",");			mccArg(f, mb, getArg(p, j));		}		stream_printf(f, ") )");		if (*ctop > 0)			stream_printf(f, " goto CATCH_%d;\n", catch[--*ctop]);		else			stream_printf(f, " return Xmsg;\n");	}	if (p->barrier)		switch (p->barrier) {		case BARRIERsymbol:			stream_printf(f, "\tif(  ");			mccEntry(f, mb, getArg(p, 0));			stream_printf(f, " ) goto EXIT_%d;\n", p->jump);			stream_printf(f, "BARRIER_%d:\n", i + 1);			break;		case RETURNsymbol:			for (j = 0; j < p->retc; j++) {				stream_printf(f, "\tVALcopy(&");				mccVar(f, mb, getArg(getInstrPtr(mb, 0), j));				stream_printf(f, ", &");				mccVar(f, mb, getArg(p, j));				stream_printf(f, ");\n");			}			stream_printf(f, "\treturn Xmsg;\n");		case CATCHsymbol:		case EXITsymbol:			break;		case LEAVEsymbol:		case REDOsymbol:			stream_printf(f, "\tif( !( ");			mccEntry(f, mb, getArg(p, 0));			stream_printf(f, ") ) goto BARRIER_%d;\n", p->jump);			break;		default:			stream_printf(f, "/* case not yet covered: %d */\n", p->barrier);		}	return errors;}@-Multiplex script calls are expanded to their code base.@cvoidmccMultiplex(stream *f, MalBlkPtr mb, InstrPtr p){	int pc = getPC(mb, p);	InstrPtr pn;	pn = copyInstruction(p);	if (getFunctionId(pn))		GDKfree(pn->fcnname);	if (getModuleId(pn))		setModuleId(p,NULL);	setModuleId(pn, NULL);	setFunctionId(pn, GDKstrdup(getVarConstant(mb, pn->argv[pn->retc]).val.sval));	delArgument(pn, pn->retc);	typeChecker(MCgetClient()->nspace, mb, pn, TRUE);	stream_printf(f, "{\tlng mloop;\n\tptr h,t;\n");	stream_printf(f, "init todo\n");	stream_printf(f, "\tif(mloop>0)\n\tdo{\n");	stream_printf(f, "TODO\n");	mccInstruction(f, mb, pn, pc, 0, 0);	stream_printf(f, "\t} while(mloop > 0 );\n");	stream_printf(f, "}\n");	freeInstruction(pn);}voidmccBody(stream *f, MalBlkPtr mb){	int i;	InstrPtr p;	int *catch, ctop = 0, errors = 0;	catch = (int *) alloca(mb->stop);	for (i = 1; i < mb->stop; i++) {		p = getInstrPtr(mb, i);		if (p->barrier == CATCHsymbol)			catch[ctop++] = i;	}	for (i = 1; i < mb->stop; i++) {		p = getInstrPtr(mb, i);@-Unfortunately, we can only compile commands now.Patterns require simulation of the context. The bestapproach would be to provide alternative implementationsdirectly.A simple extension would be to also compile the dependentfunctions.@c		if (p->token != CMDcall && getFunctionId(p)) {			if (getModuleId(p) && getFunctionId(p) && 				idcmp(getModuleId(p), "multiplex") == 0 && 				idcmp(getFunctionId(p), "script") == 0) {				mccMultiplex(f, mb, p);				continue;			}			GDKwarning("call to %s.%s can not be handled correctly\n", 				getModuleId(p), getFunctionId(p));			errors++;		}		errors += mccInstruction(f, mb, p, i, catch, &ctop);	}	if (errors)		showErrors();}voidmccExit(stream *f){	stream_printf(f, "}\n");	(void) stream_close(f);}@-The compiler is called with arguments to designatethe routine be expanded and the designated file.@cstrmccGenerate(MalBlkPtr mb){	char buf[1024];	stream *f;	snprintf(buf, 1024, "%s/MCC%s_%s.c", monet_cwd, 			getModuleId(getInstrPtr(mb, 0)), getFunctionId(getInstrPtr(mb, 0)));	f = open_wastream(buf);	if (f == NULL)		throw(IO, "optimizer.MCcompiler", "Could not access file");	mccInit(f, mb);	mccVariables(f, mb);	mccBody(f, mb);	mccExit(f);	return MAL_SUCCEED;}@-The static compiler assumes constant values for the moduleand function name,The dynamic version takes variables from the runtime stack.@cstrMCdynamicCompiler(MalBlkPtr mb, MalStkPtr stk, InstrPtr p){	Module s;	Symbol t;	int j;	str nme, fcn, msg = MAL_SUCCEED;	(void) mb;	printf("Calling the dynamic compiler\n");	nme = *(str *) getArgReference(stk, p, 1);	fcn = *(str *) getArgReference(stk, p, 2);#ifdef DEBUG_MAL_COMPILER	printf("MCdynamicCompiler: %s.%s\n", nme, fcn);#endif	s = findModule(mal_scope, nme);	if (s == 0)		s = mal_scope;	for (; s; s = s->outer)		if (strcmp(s->name, nme) == 0 && s->subscope) {			j = getSubScope(fcn);			for (t = s->subscope[j]; t != NULL; t = t->peer)				if (t->def->errors == 0) {					if (getSignature(t)->token == FUNCTIONsymbol && 						idcmp(fcn, getFunctionId(getSignature(t))) == 0)						/* call macro expansion */						mccGenerate(t->def);					if (msg)						return msg;				}		}	return msg;}@}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -