public String[] generateSubFormat(CodeBuilder builder, Template node) {
            mBuilder = builder;

            // Acquire input parameter for use as context.
            final LocalVariable param = builder.getParameters()[0];
            Variable contextVar = mContextParam.getVariable();
            Variable newLocalContext =
                new Variable(null, contextVar.getName(), contextVar.getType());
            declareVariable(newLocalContext, param);

            // Cast local context parameter to ensure its the right type.
            mBuilder.loadLocal(param);
            mBuilder.checkCast(makeDesc(contextVar));
            mBuilder.storeLocal(param);

            // Store context in field in case a substitution is exported from
            // this template.
            storeToVariable(contextVar, new Runnable() {
                public void run() {
                    mBuilder.loadLocal(param);
                }
            });
            contextVar.setField(false);

            // Create ReturnValue field if template returns a value.
            Type returnType = node.getReturnType();
            if (!(Type.VOID_TYPE.equals(returnType))) {
                Variable returnValue =
                    new Variable(null, "returnValue", returnType);
                returnValue.setField(true);
                declareVariable(returnValue);

                mReturnValue = new VariableRef(null, returnValue.getName());
                mReturnValue.setVariable(returnValue);
            }

            // Create blockId field.
            Type blockIdType = Type.INT_TYPE;
            Variable blockId = new Variable(null, "blockId", blockIdType);
            blockId.setField(true);
            declareVariable(blockId);

            mBlockId = new VariableRef(null, blockId.getName());
            mBlockId.setVariable(blockId);

            // switch (blockId) {...
            mBuilder.loadThis();
            mBuilder.loadField(blockId.getName(), TypeDesc.INT);

            // Create case labels.
            int[] cases = new int[mSubBlockCount + 1];
            Label[] switchLabels = new Label[mSubBlockCount + 1];
            mCaseNodes = new ArrayList<Node>(mSubBlockCount + 1);

            for (int i=0; i <= mSubBlockCount; i++) {
                cases[i] = i;
                switchLabels[i] = mBuilder.createLabel();
            }

            Label defaultLabel = mBuilder.createLabel();

            mBuilder.switchBranch(cases, switchLabels, defaultLabel);

            int size = 0;
            int newSize;
            mCaseNodes.add(node);
            while ( (newSize = mCaseNodes.size()) > size) {
                for (; size < newSize; size++) {
                    if (size > 0) {
                        mBuilder.returnVoid();
                    }
                    switchLabels[size].setLocation();

                    // Inject pre-call profiling bytecode.
                    TypeDesc methodObserverType =
                        TypeDesc.forClass(MergedClass.InvocationEventObserver.class);

                    boolean profilingEnabled = isProfilingEnabled();

                    LocalVariable startTime = mBuilder.createLocalVariable("blockTime",
                        TypeDesc.forClass(long.class));
                    if (profilingEnabled && size > 0) {
                        mBuilder.invokeStatic(mContextParam.getVariable().getType().getObjectClass().getName(),
                            "getInvocationObserver", methodObserverType);
                        mBuilder.invokeInterface(methodObserverType.getFullName(), "currentTime",
                           TypeDesc.forClass(long.class));
                        mBuilder.storeLocal(startTime);
                    }

                    generate(mCaseNodes.get(size));

                    // Inject post-call profiling bytecode.
                    if (profilingEnabled && size > 0) {
                        mBuilder.invokeStatic(mContextParam.getVariable().getType().getObjectClass().getName(),
                            "getInvocationObserver", methodObserverType);
                        mBuilder.loadConstant(mUnit.getName());
                        mBuilder.loadConstant(mCallerToSubNoList.get(size - 1));
                        mBuilder.invokeStatic(mContextParam.getVariable().getType().getObjectClass().getName(),
                            "getInvocationObserver", methodObserverType);
                        mBuilder.invokeInterface(methodObserverType.getFullName(), "currentTime",
                            TypeDesc.forClass(long.class));
                        mBuilder.loadLocal(startTime);
                        mBuilder.math(Opcode.LSUB);
                        mBuilder.invokeInterface(methodObserverType.getFullName(), "invokedEvent", null,
                            new TypeDesc[] { TypeDesc.forClass(String.class), TypeDesc.forClass(String.class),
                                TypeDesc.forClass(long.class) });
                    }

                }
            }

            defaultLabel.setLocation();
            mBuilder.returnVoid();

            generateExceptionHandlers();

            return new String[] {
                mBlockId.getName(),
                (mReturnValue != null) ? mReturnValue.getName() : null
            }