1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
|
#include "stdafx.h"
#include "Clone.h"
#include "CodeGen.h"
#include "Type.h"
#include "Package.h"
#include "Engine.h"
#include "Exception.h"
namespace storm {
using namespace code;
CloneTemplate::CloneTemplate() : Template(new (engine()) Str(L"clone")) {}
// Dummy for TObjects.
static TObject *CODECALL returnPtr(TObject *o) {
return o;
}
static TObject *CODECALL returnPtrEnv(TObject *o, CloneEnv *e) {
return o;
}
static Function *generateSingle(Value type) {
Engine &e = type.type->engine;
Value cloneEnvT = Value(CloneEnv::stormType(e));
Array<Value> *params = new (e) Array<Value>(1, type);
if (type.isActor())
return nativeFunction(e, type, S("clone"), params, address(&returnPtr));
else if (type.isClass())
return nativeFunction(e, type, S("clone"), params, address(&runtime::cloneObject));
// Value or built-in type. We need to generate some code...
CodeGen *g = new (e) CodeGen(RunOn(), false, type);
Var in = g->createParam(type);
*g->l << prolog();
if (Function *copyFn = type.type->deepCopyFn()) {
Var cloneEnv = allocObject(g, cloneEnvT.type);
*g->l << lea(ptrA, in);
*g->l << fnParam(e.ptrDesc(), ptrA);
*g->l << fnParam(e.ptrDesc(), cloneEnv);
*g->l << fnCall(copyFn->ref(), true);
}
g->returnValue(in);
return dynamicFunction(e, type, S("clone"), params, g->l);
}
static Function *generateDual(Value type) {
Engine &e = type.type->engine;
Value cloneEnvT = Value(CloneEnv::stormType(e));
Array<Value> *params = new (e) Array<Value>(2, type);
params->at(1) = cloneEnvT;
if (type.isActor())
return nativeFunction(e, type, S("clone"), params, address(&returnPtrEnv));
else if (type.isObject())
return nativeFunction(e, type, S("clone"), params, address(&runtime::cloneObjectEnv));
// Value or built-in type. We need to generate some code...
CodeGen *g = new (e) CodeGen(RunOn(), false, type);
Var in = g->createParam(type);
Var cloneEnv = g->createParam(cloneEnvT);
*g->l << prolog();
if (Function *copyFn = type.type->deepCopyFn()) {
*g->l << lea(ptrA, in);
*g->l << fnParam(e.ptrDesc(), ptrA);
*g->l << fnParam(e.ptrDesc(), cloneEnv);
*g->l << fnCall(copyFn->ref(), true);
}
g->returnValue(in);
return dynamicFunction(e, type, S("clone"), params, g->l);
}
MAYBE(Named *) CloneTemplate::generate(SimplePart *part) {
Array<Value> *params = part->params;
if (params->count() < 1 || params->count() > 2)
return null;
Value type = params->at(0).asRef(false);
if (type.type == null)
return null;
Named *result = null;
if (params->count() == 2) {
Value cloneEnv = params->at(1).asRef(false);
if (cloneEnv.type != CloneEnv::stormType(engine()))
return null;
result = generateDual(type);
} else {
result = generateSingle(type);
}
if (result)
result->flags |= namedMatchNoInheritance;
return result;
}
Function *cloneFn(Type *t) {
Engine &e = t->engine;
Package *p = e.package(S("core"));
Function *r = as<Function>(p->find(S("clone"), Value(t), e.scope()));
if (!r)
throw new (t) InternalError(TO_S(t->engine, S("Can not finde core.clone for ") << t->identifier()));
return r;
}
Function *cloneFnEnv(Type *t) {
Engine &e = t->engine;
Package *p = e.package(S("core"));
Array<Value> *params = new (e) Array<Value>(2, Value(t));
params->at(1) = Value(CloneEnv::stormType(e));
Function *r = as<Function>(p->find(S("clone"), params, e.scope()));
if (!r)
throw new (t) InternalError(TO_S(t->engine, S("Can not finde core.clone for ") << t->identifier()));
return r;
}
}
|