Permalink
Browse files

Allow optional variadic record fields.

Update record primitives for accessing variadic records.
Update record lib to support variadic records (INCOMPLETE)
Update referenceType lib to support variadic records (INCOMPLETE)
  • Loading branch information...
1 parent 98d74b1 commit 268e845f0e4f89fcff3fe805c0d3aa2e202bca47 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 : {
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,6 +2835,9 @@ struct RecordType : public Type {
vector<IdentifierPtr> fieldNames;
vector<TypePtr> fieldTypes;
+ unsigned varFieldPosition;
+ bool hasVarField:1;
+
llvm::StringMap<size_t> fieldIndexMap;
const llvm::StructLayout *layout;
@@ -2836,10 +2846,17 @@ struct RecordType : public Type {
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;
}
@@ -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;
}
View
@@ -1950,20 +1950,35 @@ bool importVisibility(Visibility &x) {
// records
//
-static bool recordField(RecordFieldPtr &x) {
+static bool recordField(RecordFieldPtr &x, bool &hasVarField) {
Location location = currentLocation();
IdentifierPtr y;
- if (!identifier(y)) return false;
ExprPtr z;
- if (!exprTypeSpec(z)) return false;
+ bool varField = false;
+ int p = save();
+ if (ellipsis()) {
+ if (hasVarField)
+ return false;
+ else
+ hasVarField = true;
+ varField = true;
+ } else
+ restore(p);
+ if (!identifier(y)) return false;
+ if (varField) {
+ if (!varArgTypeSpec(z)) return false;
+ } else {
+ if (!exprTypeSpec(z)) return false;
+ }
x = new RecordField(y, z);
x->location = location;
+ x->varField = varField;
return true;
}
-static bool recordFields(vector<RecordFieldPtr> &x) {
+static bool recordFields(vector<RecordFieldPtr> &x, bool &hasVarField) {
RecordFieldPtr y;
- if (!recordField(y)) return false;
+ if (!recordField(y, hasVarField)) return false;
x.clear();
while (true) {
x.push_back(y);
@@ -1973,17 +1988,17 @@ static bool recordFields(vector<RecordFieldPtr> &x) {
break;
}
p = save();
- if (!recordField(y)) {
+ if (!recordField(y, hasVarField)) {
restore(p);
break;
}
}
return true;
}
-static bool optRecordFields(vector<RecordFieldPtr> &x) {
+static bool optRecordFields(vector<RecordFieldPtr> &x, bool &hasVarField) {
int p = save();
- if (!recordFields(x)) {
+ if (!recordFields(x, hasVarField)) {
restore(p);
x.clear();
}
@@ -1994,10 +2009,11 @@ static bool recordBodyFields(RecordBodyPtr &x) {
Location location = currentLocation();
if (!symbol("(")) return false;
vector<RecordFieldPtr> y;
- if (!optRecordFields(y)) return false;
+ bool hasVarField = false;
+ if (!optRecordFields(y, hasVarField)) return false;
if (!symbol(")")) return false;
if (!symbol(";")) return false;
- x = new RecordBody(y);
+ x = new RecordBody(y, hasVarField);
x->location = location;
return true;
}
Oops, something went wrong.

0 comments on commit 268e845

Please sign in to comment.