Permalink
Browse files

Merge pull request #446 from agemogolk/record_variadic

Support variadic fields in Records
  • Loading branch information...
2 parents 98d74b1 + 273e8d3 commit fb63da9aace725aba12bd14dc7070c390c7fa1ac agemogolk committed Nov 19, 2012
View
@@ -3242,10 +3242,20 @@ MultiPValuePtr analyzePrimOp(PrimOpPtr x, MultiPValuePtr args)
if (!obj || !staticToSizeTOrInt(obj, i))
argumentError(1, "expecting static SizeT or Int value");
llvm::ArrayRef<TypePtr> fieldTypes = recordFieldTypes(t);
- if (i >= fieldTypes.size())
+ if (i >= t->fieldCount())
argumentIndexRangeError(1, "record field index",
- i, fieldTypes.size());
- return new MultiPValue(PVData(fieldTypes[i], false));
+ i, t->fieldCount());
+
+ MultiPValuePtr mpv = new MultiPValue();
+ if (t->hasVarField && i >= t->varFieldPosition)
+ if (i == t->varFieldPosition)
+ for (size_t j=0;j < t->varFieldSize(); ++j)
+ mpv->add(PVData(fieldTypes[i+j], false));
+ else
+ mpv->add(PVData(fieldTypes[i+t->varFieldSize()-1], false));
+ else
+ mpv->add(PVData(fieldTypes[i], false));
+ return mpv;
}
case PRIM_recordFieldRefByName : {
@@ -3265,7 +3275,17 @@ MultiPValuePtr analyzePrimOp(PrimOpPtr x, MultiPValuePtr args)
argumentError(1, sout.str());
}
llvm::ArrayRef<TypePtr> fieldTypes = recordFieldTypes(t);
- return new MultiPValue(PVData(fieldTypes[fi->second], false));
+ MultiPValuePtr mpv = new MultiPValue();
+ size_t i = fi->second;
+ if (t->hasVarField && i >= t->varFieldPosition)
+ if (i == t->varFieldPosition)
+ for (size_t j=0;j < t->varFieldSize(); ++j)
+ mpv->add(PVData(fieldTypes[i+j], false));
+ else
+ mpv->add(PVData(fieldTypes[i+t->varFieldSize()-1], false));
+ else
+ mpv->add(PVData(fieldTypes[i], false));
+ return mpv;
}
case PRIM_recordFields : {
@@ -3278,6 +3298,19 @@ MultiPValuePtr analyzePrimOp(PrimOpPtr x, MultiPValuePtr args)
return mpv;
}
+ case PRIM_recordVariadicField : {
+ ensureArity(args, 1);
+ RecordTypePtr t = recordTypeOfValue(args, 0);
+ if (!t->hasVarField)
+ argumentError(0, "expecting a record with a variadic field");
+ llvm::ArrayRef<TypePtr> fieldTypes = recordFieldTypes(t);
+ MultiPValuePtr mpv = new MultiPValue();
+ size_t varEnd = t->varFieldPosition + t->varFieldSize();
+ for (unsigned i = t->varFieldPosition; i < varEnd; ++i)
+ mpv->add(PVData(fieldTypes[i], false));
+ return mpv;
+ }
+
case PRIM_VariantP :
return new MultiPValue(PVData(boolType, true));
View
@@ -1870,17 +1870,24 @@ struct RecordBody : public ANode {
ExprListPtr computed; // valid if isComputed == true
vector<RecordFieldPtr> fields; // valid if isComputed == false
bool isComputed:1;
+ bool hasVarField:1;
RecordBody(ExprListPtr computed)
- : ANode(RECORD_BODY), computed(computed), isComputed(true) {}
+ : ANode(RECORD_BODY), computed(computed), isComputed(true),
+ hasVarField(false) {}
RecordBody(llvm::ArrayRef<RecordFieldPtr> fields)
- : ANode(RECORD_BODY), fields(fields), isComputed(false) {}
+ : ANode(RECORD_BODY), fields(fields), isComputed(false),
+ hasVarField(false) {}
+ RecordBody(llvm::ArrayRef<RecordFieldPtr> fields, bool hasVarField)
+ : ANode(RECORD_BODY), fields(fields), isComputed(false),
+ hasVarField(hasVarField) {}
};
struct RecordField : public ANode {
IdentifierPtr name;
ExprPtr type;
+ bool varField:1;
RecordField(IdentifierPtr name, ExprPtr type)
- : ANode(RECORD_FIELD), name(name), type(type) {}
+ : ANode(RECORD_FIELD), name(name), type(type), varField(false) {}
};
struct VariantDecl : public TopLevelItem {
@@ -2828,18 +2835,28 @@ struct RecordType : public Type {
vector<IdentifierPtr> fieldNames;
vector<TypePtr> fieldTypes;
+
llvm::StringMap<size_t> fieldIndexMap;
const llvm::StructLayout *layout;
+ unsigned varFieldPosition;
+ bool hasVarField:1;
bool fieldsInitialized:1;
RecordType(RecordDeclPtr record)
: Type(RECORD_TYPE), record(record),
- layout(NULL), fieldsInitialized(false) {}
+ layout(NULL), fieldsInitialized(false), hasVarField(false) {}
RecordType(RecordDeclPtr record, llvm::ArrayRef<ObjectPtr> params)
: Type(RECORD_TYPE), record(record), params(params),
- layout(NULL), fieldsInitialized(false) {}
+ layout(NULL), fieldsInitialized(false), hasVarField(false) {}
+
+ unsigned varFieldSize() {
+ return fieldTypes.size() - fieldNames.size() + 1;
+ }
+ unsigned fieldCount() {
+ return fieldNames.size();
+ }
};
struct VariantType : public Type {
View
@@ -6124,8 +6124,7 @@ void codegenPrimOp(PrimOpPtr x,
case PRIM_RecordFieldCount : {
ensureArity(args, 1);
RecordTypePtr rt = valueToRecordType(args, 0);
- llvm::ArrayRef<TypePtr> fieldTypes = recordFieldTypes(rt);
- ValueHolderPtr vh = sizeTToValueHolder(fieldTypes.size());
+ ValueHolderPtr vh = sizeTToValueHolder(rt->fieldCount());
codegenStaticObject(vh.ptr(), ctx, out);
break;
}
@@ -6168,14 +6167,35 @@ void codegenPrimOp(PrimOpPtr x,
llvm::Value *vrec = recordValue(args, 0, rt);
size_t i = valueToStaticSizeTOrInt(args, 1);
llvm::ArrayRef<TypePtr> fieldTypes = recordFieldTypes(rt);
- if (i >= fieldTypes.size())
+ if (i >= rt->fieldCount())
argumentIndexRangeError(1, "record field index",
- i, fieldTypes.size());
- llvm::Value *ptr = ctx->builder->CreateConstGEP2_32(vrec, 0, i);
- assert(out->size() == 1);
- CValuePtr out0 = out->values[0];
- assert(out0->type == pointerType(fieldTypes[i]));
- ctx->builder->CreateStore(ptr, out0->llValue);
+ i, rt->fieldCount());
+
+ if (rt->hasVarField && i >= rt->varFieldPosition) {
+ if (i == rt->varFieldPosition) {
+ assert(out->size() == rt->varFieldSize());
+ for (size_t j = 0; j < rt->varFieldSize(); ++j) {
+ CValuePtr outi = out->values[j];
+ assert(outi->type == pointerType(fieldTypes[i+j]));
+ llvm::Value *ptr = ctx->builder->CreateConstGEP2_32(vrec, 0, i+j);
+ ctx->builder->CreateStore(ptr, outi->llValue);
+ }
+ } else {
+ size_t k = i+rt->varFieldSize()-1;
+ llvm::Value *ptr = ctx->builder->CreateConstGEP2_32(vrec, 0, k);
+ assert(out->size() == 1);
+ CValuePtr out0 = out->values[0];
+ assert(out0->type == pointerType(fieldTypes[k]));
+ ctx->builder->CreateStore(ptr, out0->llValue);
+ }
+ } else {
+ llvm::Value *ptr = ctx->builder->CreateConstGEP2_32(vrec, 0, i);
+ assert(out->size() == 1);
+ CValuePtr out0 = out->values[0];
+ assert(out0->type == pointerType(fieldTypes[i]));
+ ctx->builder->CreateStore(ptr, out0->llValue);
+ }
+
break;
}
@@ -6193,13 +6213,32 @@ void codegenPrimOp(PrimOpPtr x,
sout << "field not found: " << fname->str;
argumentError(1, sout.str());
}
- size_t index = fi->second;
+ size_t i = fi->second;
llvm::ArrayRef<TypePtr> fieldTypes = recordFieldTypes(rt);
- llvm::Value *ptr = ctx->builder->CreateConstGEP2_32(vrec, 0, index);
- assert(out->size() == 1);
- CValuePtr out0 = out->values[0];
- assert(out0->type == pointerType(fieldTypes[index]));
- ctx->builder->CreateStore(ptr, out0->llValue);
+ if (rt->hasVarField && i >= rt->varFieldPosition) {
+ if (i == rt->varFieldPosition) {
+ assert(out->size() == rt->varFieldSize());
+ for (size_t j = 0; j < rt->varFieldSize(); ++j) {
+ CValuePtr outi = out->values[j];
+ assert(outi->type == pointerType(fieldTypes[i+j]));
+ llvm::Value *ptr = ctx->builder->CreateConstGEP2_32(vrec, 0, i+j);
+ ctx->builder->CreateStore(ptr, outi->llValue);
+ }
+ } else {
+ size_t k = i+rt->varFieldSize()-1;
+ llvm::Value *ptr = ctx->builder->CreateConstGEP2_32(vrec, 0, k);
+ assert(out->size() == 1);
+ CValuePtr out0 = out->values[0];
+ assert(out0->type == pointerType(fieldTypes[k]));
+ ctx->builder->CreateStore(ptr, out0->llValue);
+ }
+ } else {
+ llvm::Value *ptr = ctx->builder->CreateConstGEP2_32(vrec, 0, i);
+ assert(out->size() == 1);
+ CValuePtr out0 = out->values[0];
+ assert(out0->type == pointerType(fieldTypes[i]));
+ ctx->builder->CreateStore(ptr, out0->llValue);
+ }
break;
}
@@ -6218,6 +6257,24 @@ void codegenPrimOp(PrimOpPtr x,
break;
}
+ case PRIM_recordVariadicField : {
+ ensureArity(args, 1);
+ RecordTypePtr rt;
+ llvm::Value *vrec = recordValue(args, 0, rt);
+ llvm::ArrayRef<TypePtr> fieldTypes = recordFieldTypes(rt);
+ if (!rt->hasVarField)
+ argumentError(0, "expecting a record with a variadic field");
+ assert(out->size() == rt->varFieldSize());
+ for (unsigned i = 0; i < rt->varFieldSize(); ++i) {
+ size_t k = rt->varFieldPosition + i;
+ CValuePtr outi = out->values[i];
+ assert(outi->type == pointerType(fieldTypes[k]));
+ llvm::Value *ptr = ctx->builder->CreateConstGEP2_32(vrec, 0, k);
+ ctx->builder->CreateStore(ptr, outi->llValue);
+ }
+ break;
+ }
+
case PRIM_VariantP : {
ensureArity(args, 1);
bool isVariantType = false;
@@ -125,6 +125,7 @@ void initBuiltinConstructor(RecordDeclPtr x)
CodePtr code = new Code();
code->location = x->location;
+ code->hasVarArg = y->hasVarField;
for (unsigned i = 0; i < x->params.size(); ++i) {
PatternVar pvar(false, x->params[i]);
code->patternVars.push_back(pvar);
@@ -136,7 +137,7 @@ void initBuiltinConstructor(RecordDeclPtr x)
for (unsigned i = 0; i < y->fields.size(); ++i) {
RecordFieldPtr f = y->fields[i];
- FormalArgPtr arg = new FormalArg(f->name, f->type);
+ FormalArgPtr arg = new FormalArg(f->name, f->type, TEMPNESS_DONTCARE, f->varField);
arg->location = f->location;
code->formalArgs.push_back(arg.ptr());
}
View
@@ -4336,8 +4336,7 @@ void evalPrimOp(PrimOpPtr x, MultiEValuePtr args, MultiEValuePtr out)
case PRIM_RecordFieldCount : {
ensureArity(args, 1);
RecordTypePtr rt = valueToRecordType(args, 0);
- llvm::ArrayRef<TypePtr> fieldTypes = recordFieldTypes(rt);
- ValueHolderPtr vh = sizeTToValueHolder(fieldTypes.size());
+ ValueHolderPtr vh = sizeTToValueHolder(rt->fieldCount());
evalStaticObject(vh.ptr(), out);
break;
}
@@ -4380,15 +4379,35 @@ void evalPrimOp(PrimOpPtr x, MultiEValuePtr args, MultiEValuePtr out)
EValuePtr erec = recordValue(args, 0, rt);
size_t i = valueToStaticSizeTOrInt(args, 1);
llvm::ArrayRef<TypePtr> fieldTypes = recordFieldTypes(rt);
- if (i >= fieldTypes.size())
+ if (i >= rt->fieldCount())
argumentIndexRangeError(1, "record field index",
- i, fieldTypes.size());
+ i, rt->fieldCount());
const llvm::StructLayout *layout = recordTypeLayout(rt.ptr());
- char *ptr = erec->addr + layout->getElementOffset(i);
- assert(out->size() == 1);
- EValuePtr out0 = out->values[0];
- assert(out0->type == pointerType(fieldTypes[i]));
- out0->as<void *>() = (void *)ptr;
+
+ if (rt->hasVarField && i >= rt->varFieldPosition) {
+ if (i == rt->varFieldPosition) {
+ assert(out->size() == rt->varFieldSize());
+ for (unsigned j = 0; j < rt->varFieldSize(); ++j) {
+ char *ptr = erec->addr + layout->getElementOffset(i+j);
+ EValuePtr out0 = out->values[j];
+ assert(out0->type == pointerType(fieldTypes[i+j]));
+ out0->as<void *>() = (void *)ptr;
+ }
+ } else {
+ unsigned k = i+rt->varFieldSize()-1;
+ char *ptr = erec->addr + layout->getElementOffset(k);
+ assert(out->size() == 1);
+ EValuePtr out0 = out->values[0];
+ assert(out0->type == pointerType(fieldTypes[k]));
+ out0->as<void *>() = (void *)ptr;
+ }
+ } else {
+ char *ptr = erec->addr + layout->getElementOffset(i);
+ assert(out->size() == 1);
+ EValuePtr out0 = out->values[0];
+ assert(out0->type == pointerType(fieldTypes[i]));
+ out0->as<void *>() = (void *)ptr;
+ }
break;
}
@@ -4406,14 +4425,34 @@ void evalPrimOp(PrimOpPtr x, MultiEValuePtr args, MultiEValuePtr out)
sout << "field not found: " << fname->str;
argumentError(1, sout.str());
}
- size_t index = fi->second;
+ size_t i = fi->second;
llvm::ArrayRef<TypePtr> fieldTypes = recordFieldTypes(rt);
const llvm::StructLayout *layout = recordTypeLayout(rt.ptr());
- char *ptr = erec->addr + layout->getElementOffset(index);
- assert(out->size() == 1);
- EValuePtr out0 = out->values[0];
- assert(out0->type == pointerType(fieldTypes[index]));
- out0->as<void *>() = (void *)ptr;
+
+ if (rt->hasVarField && i >= rt->varFieldPosition) {
+ if (i == rt->varFieldPosition) {
+ assert(out->size() == rt->varFieldSize());
+ for (unsigned j = 0; j < rt->varFieldSize(); ++j) {
+ char *ptr = erec->addr + layout->getElementOffset(i+j);
+ EValuePtr out0 = out->values[j];
+ assert(out0->type == pointerType(fieldTypes[i+j]));
+ out0->as<void *>() = (void *)ptr;
+ }
+ } else {
+ unsigned k = i+rt->varFieldSize()-1;
+ char *ptr = erec->addr + layout->getElementOffset(k);
+ assert(out->size() == 1);
+ EValuePtr out0 = out->values[0];
+ assert(out0->type == pointerType(fieldTypes[k]));
+ out0->as<void *>() = (void *)ptr;
+ }
+ } else {
+ char *ptr = erec->addr + layout->getElementOffset(i);
+ assert(out->size() == 1);
+ EValuePtr out0 = out->values[0];
+ assert(out0->type == pointerType(fieldTypes[i]));
+ out0->as<void *>() = (void *)ptr;
+ }
break;
}
@@ -4433,6 +4472,26 @@ void evalPrimOp(PrimOpPtr x, MultiEValuePtr args, MultiEValuePtr out)
break;
}
+ case PRIM_recordVariadicField : {
+ ensureArity(args, 1);
+ RecordTypePtr rt;
+ EValuePtr erec = recordValue(args, 0, rt);
+ llvm::ArrayRef<TypePtr> fieldTypes = recordFieldTypes(rt);
+ if (!rt->hasVarField)
+ argumentError(0, "expecting a record with a variadic field");
+ assert(out->size() == fieldTypes.size());
+ const llvm::StructLayout *layout = recordTypeLayout(rt.ptr());
+ assert(out->size() == rt->varFieldSize());
+ for (unsigned i = 0; i < rt->varFieldSize(); ++i) {
+ size_t k = rt->varFieldPosition + i;
+ EValuePtr outi = out->values[i];
+ assert(outi->type == pointerType(fieldTypes[k]));
+ char *ptr = erec->addr + layout->getElementOffset(k);
+ outi->as<void *>() = (void *)ptr;
+ }
+ break;
+ }
+
case PRIM_VariantP : {
ensureArity(args, 1);
bool isVariantType = false;
View
@@ -1070,6 +1070,7 @@ static ModulePtr makePrimitivesModule() {
PRIMITIVE(recordFieldRef);
PRIMITIVE(recordFieldRefByName);
PRIMITIVE(recordFields);
+ PRIMITIVE(recordVariadicField);
PRIMITIVE(VariantP);
PRIMITIVE(VariantMemberIndex);
View
@@ -141,6 +141,7 @@ enum PrimOpCode {
PRIM_recordFieldRef,
PRIM_recordFieldRefByName,
PRIM_recordFields,
+ PRIM_recordVariadicField,
PRIM_VariantP,
PRIM_VariantMemberIndex,
Oops, something went wrong.

0 comments on commit fb63da9

Please sign in to comment.