Permalink
Browse files

Add recordVariadicField prim-op.

Add variadic record field test.
Update record primitives to support var fields.
Update debug info for var record fields.
  • Loading branch information...
1 parent 268e845 commit 94756a6d98d940508d2783a1bc36d95478d7ab2a agemogolk committed Nov 19, 2012
View
13 compiler/analyzer.cpp
@@ -3298,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
18 compiler/codegen.cpp
@@ -6257,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;
View
20 compiler/evaluator.cpp
@@ -4472,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
1 compiler/loader.cpp
@@ -1070,6 +1070,7 @@ static ModulePtr makePrimitivesModule() {
PRIMITIVE(recordFieldRef);
PRIMITIVE(recordFieldRefByName);
PRIMITIVE(recordFields);
+ PRIMITIVE(recordVariadicField);
PRIMITIVE(VariantP);
PRIMITIVE(VariantMemberIndex);
View
1 compiler/loader.hpp
@@ -141,6 +141,7 @@ enum PrimOpCode {
PRIM_recordFieldRef,
PRIM_recordFieldRefByName,
PRIM_recordFields,
+ PRIM_recordVariadicField,
PRIM_VariantP,
PRIM_VariantMemberIndex,
View
56 compiler/types.cpp
@@ -1545,8 +1545,60 @@ static void defineLLVMType(TypePtr t) {
vector<llvm::Value*> members;
size_t debugOffset = 0;
for (size_t i = 0; i < fieldNames.size(); ++i) {
- if (x->hasVarField && i == x->varFieldPosition) {
-
+ if (x->hasVarField && i >= x->varFieldPosition) {
+ if (i == x->varFieldPosition) {
+ for (size_t j = 0; j < x->varFieldSize(); ++j) {
+ llvm::SmallString<128> buf;
+ llvm::raw_svector_ostream sout(buf);
+ sout << fieldNames[i] << ".." << j;
+ llvm::Type *memberLLT = llvmType(fieldTypes[i+j]);
+ size_t debugAlign = debugTypeAlignment(memberLLT);
+ size_t debugSize = debugTypeSize(memberLLT);
+ debugOffset = alignedUpTo(debugOffset, debugAlign);
+
+ Location fieldLocation = fieldNames[i]->location;
+ if (!fieldLocation.ok())
+ fieldLocation = x->record->location;
+ int fieldLine, fieldColumn;
+ llvm::DIFile fieldFile = getDebugLineCol(fieldLocation, fieldLine, fieldColumn);
+ members.push_back(llvmDIBuilder->createMemberType(
+ placeholder,
+ sout.str(),
+ fieldFile, // file
+ fieldLine, // lineNo
+ debugSize, // size
+ debugAlign, // align
+ debugOffset, // offset
+ 0, // flags
+ llvmTypeDebugInfo(fieldTypes[i+j]) // type
+ ));
+ debugOffset += debugSize;
+ }
+ } else {
+ size_t k = i+x->varFieldSize()-1;
+ llvm::Type *memberLLT = llvmType(fieldTypes[k]);
+ size_t debugAlign = debugTypeAlignment(memberLLT);
+ size_t debugSize = debugTypeSize(memberLLT);
+ debugOffset = alignedUpTo(debugOffset, debugAlign);
+
+ Location fieldLocation = fieldNames[i]->location;
+ if (!fieldLocation.ok())
+ fieldLocation = x->record->location;
+ int fieldLine, fieldColumn;
+ llvm::DIFile fieldFile = getDebugLineCol(fieldLocation, fieldLine, fieldColumn);
+ members.push_back(llvmDIBuilder->createMemberType(
+ placeholder,
+ fieldNames[i]->str,
+ fieldFile, // file
+ fieldLine, // lineNo
+ debugSize, // size
+ debugAlign, // align
+ debugOffset, // offset
+ 0, // flags
+ llvmTypeDebugInfo(fieldTypes[k]) // type
+ ));
+ debugOffset += debugSize;
+ }
} else {
llvm::Type *memberLLT = llvmType(fieldTypes[i]);
size_t debugAlign = debugTypeAlignment(memberLLT);
View
14 test/lang/records/variadics/main.clay
@@ -0,0 +1,14 @@
+import printer.*;
+
+record Cow[..T] (a:Int32, ..data:T, b:Float64);
+
+[..T]
+overload Cow(a:Int32, ..data:T, b:Float64) = Cow[..T](a, ..data, b);
+
+main() {
+ var ..data = 2,6,"pigs",[3.0f,Float32],7.0;
+ var mycow = Cow(..data);
+ println(..weaveValues(",", ..recordFields(mycow)));
+ println(..weaveValues(",", ..recordVariadicField(mycow)));
+ println(..weaveValues(",", ..mycow.data));
+}
View
3 test/lang/records/variadics/out.txt
@@ -0,0 +1,3 @@
+2,6,pigs,[3, Float32],7
+6,pigs,[3, Float32]
+6,pigs,[3, Float32]

0 comments on commit 94756a6

Please sign in to comment.