I see mainframes: a real life PDS container!

September 22, 2017 Mainframe No comments , , , , , ,

I found a PDS container walking about my neighbourhood this morning:

 

Just like the mainframe version, you can put all sorts of stuff in this one.

A mainframe PDS (partitioned data set) is technically a different sort of container, as you can only put DATASETs (mainframe’ze for a file) in them. An example would be if you have two programs (loadmodules in mainframe’ze) both named PEETERJO, then you can create a two PDS datasets, each having a PEETERJO member, say:

PEETER.JOOT.IS.THE.BEST(PEETERJO)
PEETER.JOOT.IS.STILL.AWESOME(PEETERJO)

From these you could then choose which one you want your JCL script to execute with a STEPLIB statement like:

//A EXEC PGM=PEETERJO
//STEPLIB  DD DSN=PEETER.JOOT.IS.THE.BEST,DISP=SHR
//SYSOUT   DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSTERM  DD SYSOUT=*
//SYSABEND DD SYSOUT=*

This works around the global name space issue that you’d have with storing two different datasets, both with the name PEETERJO.

You can also put any file into a PDS, provided you are willing to have the PDS member name for that file be a 1-8 character string. The PDS is sort of the mainframe equivalent of a directory (the long strings of A.B.C.D.E DATASET names can also be viewed as a directory of sorts).

I’m not sure if you can put a PDS in a PDS. If that is possible, I also don’t know if a PDS member can be accessed as a PDS without first copying it out.

NATFA renegotiation

September 19, 2017 Incoherent ramblings No comments , , ,

leadnow.ca is running a campaign to object to the NATFA secret tribunals, stating:

In just a few days, negotiators from the U.S., Mexico and Canada will converge on Ottawa for a critical round of NAFTA negotiations where sources are saying things are really going to heat up. [1]

Corporate lobbyists are fighting tooth and nail to preserve dangerous and extreme rules in NAFTA called “Investor State Dispute Settlement” (ISDS). ISDS gives corporations the power to sue our government for laws that protect our environment and our health.[2]

Time is running out to influence this deal, and unless we speak up in a big way, lobbyists could bully the Liberals into putting corporate profits ahead of the public interest.[3-4]

The government has opened an inbox to get the public’s input on what it should prioritize in negotiations — and almost 10 000 Leadnow members have already sent messages calling on decision-makers to strip ISDS from the deal. We want to hit at least 15 000 messages before meetings start on the weekend to let negotiators know that Canadians want toxic ISDS rules out of NAFTA. 

Peeter, will you help us up the ante against these toxic rules that let billionaire corporations sue Canada?

 

Their form letter explicitly names the secret corporate tribunals (ISDSs), something I knew existed, but didn’t know the name of:

“Dear Canada’s NAFTA negotiating team,

Modernizing NAFTA means standing up for democracy and fighting to remove its extreme, secretive, and anti-democratic Investor State Dispute Settlement (ISDS) rules. No more corporate lawsuits that kneecap our democracies at the expense of the public good.

We know the corporate lobby and business elite are lobbying to keep ISDS intact. Please don’t cave into the corporate pressure. Put our democracy first. I’m calling on you to fight to remove toxic ISDS rules during NAFTA re-negotiations.”

While informative, their letter was a bit boring, so I wrote my own:

I understand that the NATFA negotiating team is probably populated with corporate shills, fighting to keep or augment the status quo.

This note is a quick exercise in futility, pretending that I have a place in the sham that we call democracy. A “free trade” agreement that is hundreds (probably thousands) of pages long, and was negotiated and now renegotiated in secret, that grants corporation effective control over the countries in the agreement is a travesty.  Unlike so many that fell for or still fall for the deliberately misleading label of “free trade”, I’d like to see NAFTA dissolved entirely.  I know that this is very improbable, and this note and any others that express a similar opinion are just headed for the trash, but I can still fantasize.

second experiment in screen recording

July 17, 2017 math and physics play No comments , , , , ,

Here’s a second attempt at recording a blackboard style screen recording:

 

To handle the screen transitions, equivalent to clearing my small blackboard, I switched to using a black background and just moved the text as I filled things up.  This worked much better.  I still drew with mischief, and recorded with OBS, but then did a small post production edit in iMovie to remove a little bit of dead air and to edit out one particularly bad flub.

This talk covers the product of two vectors, defines the dot and wedge products, and shows how the 3D wedge product is related to the cross product.  I recorded some additional discussion of duality that I left out of this video, which was long enough without it.

experiment in screen recording: An introduction to Geometric Algebra.

July 14, 2017 math and physics play No comments , , ,

I’ve been curious for a while what it would take to create lesson style screen recordings, and finally got around to trying one myself:

 

This is an introduction to Geometric (Clifford) algebra.  I briefly outline a geometrical interpretation of various products of unit vectors, rules for reducing products of unit vectors, and the axioms that justify those rules.

I made this recording using the OBS screen recorder, using a Mac, drawing with a Wacom tablet and using Mischief as my drawing application.  I have to find a way to do the screen clearing transitions more smoothly, as there are sizable dead time delays while I do the ‘File -> Import -> Recent -> …  ; Don’t save’ sequence in mischief to reload.  I also um and ah more than I like, something I think I could avoid if presenting this to a real live person.

quantum spin dreams

July 13, 2017 Incoherent ramblings No comments , , , , ,

I woke up this morning with the perception that I had been dreaming about designing trinary computers and topics related to quantum spin for a large chunk of the night.   Why I would have been dreaming about this is not at all obvious.  I didn’t go to bed thinking about any scientific or computer engineering topics.

In my dream it seemed natural to use spin-1 quantum states to build a trinary clock signal for the microprocessor.  That basically means that the clock signal would be optical, since photons can have spin 1, 0 or -1.  However, what would it even mean to have a spin synchronized clock signal.  This would be a state that could be measured at any point on the microprocessor that has a time varying spin, but measurement of that spin would not alter the spin states of all the other photons in the clock signal?  If measurement of the signal at one point on the chip cannot perturb the overall clock signal, then there must be a large number of particles involved.  Also how could you prepare a stream of photons that you could measure the spin and know before hand what the observed spin state should be at any given point in time?  Is the spin state of any given photon not random when measured?

So, perhaps the clock signal is a complex entangled many-photon state?  Is there a mechanism to produce an entangled state for which the measured state at any point in time would be cyclic?  I haven’t even studied any aspects of quantum information theory, other than knowing that entangled states exist.  Perhaps questions like these are already well understood?

I also dreamed of a large clear glass-like window pane, in which all the spin-1 particles had their spins synchronized.  I guess this is a similar, but simpler version of the microchip spin synchronized clock signal, just not varying with time.  In my dream I wondered what the optical properties of “glass” would be if there was a large degree of spin synchronization.  Now, does glass even have any spin-1 particles?  Perhaps the window pane in my dream was built of some other material, like plastic or Star Trek like transparent aluminium.  Even supposing that it was possible to synchronize the spins in a large number of particles, the optical effects of doing so are not clear to me.  We do calculations of reflection and transparency in electromagnetism, but there the underlying nature of the transparency is treated as a black box, having to do with the electric and magnetic permittivity.  I understand transparency to be a bulk solid state quantum statistical mechanics phenomena, but  don’t really know enough to be able to, say, compute the optical properties of a given crystal lattice of some arbitrary material.  Understanding that has been a goal since I was a kid (perhaps since I saw “The voyage home” with my grandparents as a kid), but I haven’t gotten that far in my studies yet, or if I have, I haven’t put all the pieces together mentally.

In a metal, like aluminum, there would be many free electrons.  Perhaps the spin of those half-integer spin particles could be synchronized.  What would be the optical properties if that was done in a large sheet of material?  In stat-mech we did the calculations that related spin to magnetic moment, so there would surely be magnetic properties to such a spin synchronized surface.  It is kind of interesting that we have two so very different mechanisms for magnetism, one due to quantum half integer spin, and the other due to relativistic effects of observing electrons in motion.  There are surely some subtle ways these are related in quantum field theory, but I don’t know much of that topic either.

This purpose of this dream sequence really seems to be pointing out to me how little I know, in the big picture sense, about how electrodynamics and quantum mechanics fit together.

patriotism, and worship of war, state and country

July 12, 2017 Incoherent ramblings No comments , , ,

I was reading the Gulag Archipelago, by Solzhenitsyn last night before bed, and now find myself up in the middle of the night, not able to sleep.  At first it seemed rather mysterious why I’d be wide awake with anti-patriotism and anti-war thoughts rolling around in my head so strongly, but I finally connected those thoughts with my bedtime reading.

This book reads like a real life version of 1984, starting off with stories of arrests, interrogations and searches.  Perhaps it hits so closely to home since it is so easy to see so many other aspects of 1984 playing out for real in our society around us.  It is probably not a good bedtime reading choice if I want to be able to sleep through the night.

As I lay tossing and turning at ~3am, definitively not sleeping, I had four specific memories rolling around in my head.  All were anti-state and anti-patriotism memories.

You might get the impression that Canadians are anti-war.  Part of this is because “our” participation in war is covert, and not advertised.  If “we” happen to be playing the bombing for dollars in game Kosovo or Syria, it isn’t because there is an explicit declared war, but instead because we are part of NATO “peace-keeping” (hello Orwell!) forces.  Canadian participation in the wars of our belligerent neighbour is expected.  Like the US, we aren’t creating terrorism, we are fighting it!

Canadians aren’t indoctrinated in the believe in the goodness of war as heavily as our US counterparts, but there are some lines that can’t be crossed without getting severe emotional reactions.  I challenge anybody to disrespect the religious Oh Canada or Remembrance day ceremonies, or the sanctity of the belief that Canadians were saving lives by participating in the world wars.

In my own head I had come to the internal conclusion that Oh Canada is nothing but a patriotism indoctrination tool.  The “we stand on guard for thee” words in the song scream exactly this.  I remember being a kid, standing proudly in various public school indoctrination centres, feeling proud to be Canadian, proudly listening to the “with glowing hearts” line.  However, like so many other national anthems, the Canadian anthem appears to have been rolled out in force as a war propaganda action, in our case for WWII, the “good war”.  People are still of age to have plenty of relatives that fought in WWII and aren’t mentally prepared for second guessing absolute confidence that Canadian participation in that war was beneficial.  It is a lot easier to relish the memory of loved grandfathers than to admit that their grandfathers were unfortunate pawns in the games of the power brokers that profit from war.  Canadian participation in WWII is viewed as a shallow “we saved the world from Hitler” point of view.  There are many aspects of this war that you are not allowed to think about.  You are supposed to think of the battles that Canadians helped save the day fighting.  You are not supposed to think of all the civilians that were killed and displaced.  You are not supposed to think about all the German civilians that were killed in bombing raids, and that the British were playing that city bombing game with as much relish as the Germans.  You are allowed to think about Hitler’s concentration camps, but not allowed to think about Allied cooperation with Stalin, who killed many times more of his own people than Hitler managed to kill in camps or active war.  How can a war be good when it aids and facilitates one of the worst murderers in history?

Thoughts of these sorts are hard to enunciate on the spot if you should decide to not participate in the indoctrination game of standing to attention during Oh Canada, or not standing still during a Remembrance day ceremony.  Memories of two specific instances of running the social experiment of not participating in these observances were rolling through my head.  One was at a public school when the national anthem interrupted a talk with the principle that was much more important seeming to me than the anthem (the insanity of how multiplication was being taught to Karl, our current household public school victim).  The other was returning a book at the public library when my conditioning to stand silent during the remembrance day ceremony way playing.  Should you try this social experiment, I can tell you what will happen.  You will get looks of shock and horror, and what easily appears to be pure hatred.  This is from peace loving Canadians.  I was not brave enough to play this game when the US national anthem played at my brother’s recent graduation ceremony.  I can imagine coming out of that auditorium with injuries had I decided to disrespect that particular religious ceremony.  It was both amusing and horrifying to observe the feelings of adoration as all those Americans stood enraptured with their hands on their hearts as their national anthem played.  I am thankful that it was standing room only at Devin’s graduation.  Would I have been tempted to sit during the US national anthem had I not already been standing?  I didn’t have a convenient and well articulated response for sitting at hand for such a social experiment.  I suppose that I could have claimed to be a practising Jehovah’s witness.  It is ironic that one of the only responses that may have been acceptable, like the anthem itself, would have also been religious.

I think there is perhaps value to actively not playing the Oh Canada game or the remembrance day game.  Doing that may be enough to get some people to realize exactly how conditioned their behaviour is.  At the same time, it makes people angry, which is counter productive, because people cannot reason when they are angry.   Instead perhaps consider for your self just how angry you would get if some insolent snot like me didn’t stand for attention during the anthem or walked around during a remembrance day ceremony, when we all know that you are supposed to stand still quietly.  Can you honestly say that you wouldn’t get angry to observe that?  If you did get angry, consider your reasons for that anger.  Does the fact that fact that you were forced to comply with this religious ceremony again and again and again in school have anything to do with your conditioned response?

Good patriots stand for attention during the national anthem.  Good patriots do not question the goodness of war.  Good patriots fight without considering they are being manipulated to fight the battles of others and line the pocketbooks of the power brokers that love war.  What could be wrong with encouraging patriotism?

My dad was thoroughly anti-state, and a lot of that rubbed off on me.  I think that I learned my disrespect for Remembrance day from him.  I didn’t understand it when I was a kid.  He’d been a refugee himself.  He’d lost his original home and country, his biological father, and much of his family and roots.  He’d ended up with an abusive and drunkard of a step father.   My dad was Estonian, a country that was a desirable territory in its day, having been repeatedly occupied by both German and Russian forces as they passed through it in their insane fight.  I heard many stories from my insane step grandfather about Estonian guerrilla tactics against both the invading Germans and the invading Russians.  They seemed to support the good-war indoctrination that I was receiving at school, but they didn’t work on my dad.  It was very confusing when I was kid that he didn’t respect the sanctity of remembrance day having had such personal involvement in WWII, but I think I understand some of the factors now.  Part of it is probably fairly simple.  Had there not been a world war to “fight Hitler”, the Estonians would have just had to fight the Germans in their home territory as they passed through to Russia.  Imagine that the only actions taken against the Germans were defensive, and that the Germans had to fight guerrilla tactics on all fronts in all directions from their invading epicenter.  That might have been a good war.  The real story is nothing of the sort, since fundamentally, the war was desired by the British and others, and there were hard fights on many fronts to get others involved in the game.

The other thoughts that were floating around in my head had to do with the religion of Trump in the USA.  In my youth, before I found Quantum Mechanics and Maxwells’ equations, my own religious indoctrination was that of Scientology.  Until recently, I thought of Scientologists, like my dad, as predominately anti-state, but have been disabused of that notion thoroughly by my recent visit to the US, where I discovered that there are a number of true believers in my family (both active Scientologists and also fellow childhood indoctrinees).  I guess it is true that Scientology is a multi-denominational religion.

I’ve dumped enough thoughts that I think I’ll try to go back to sleep now.  I will leave thinking through vague thoughts on Trumpism and Scientology to another day.

Building a new BBQ drip tray.

July 3, 2017 Incoherent ramblings No comments ,

My old BBQ drip tray was in really rough shape:

In exchange for coffees, the installer of our new energy efficient (and functional!) air conditioner gave me a nice new piece of sheet metal, so I’m traced out a new drip tray:

Here it is before any folds:

I don’t have a brake, nor access to a metal shop, but Sofia bought Lance a little vice a few Christmases ago, and I borrowed that:

I also found that a heavy ruler (one of the edges of my square), worked well to help with the bends

The very skinny bends were harder to do nicely, and I had to resort to some pliers to help coerce them into place, but the final result is pretty decent and a lot less porous:

It looks a bit out of place with all the rust in the remainder of the BBQ, but should help give the unit a few more years:

 

Unpacking a PL/I VSAM keyed write loop.

June 7, 2017 Mainframe No comments , , , , ,

I found myself faced with the task of understanding the effects of a PL/I WRITE loop that does the initial sequential load of a VSAM DATASET.  The block of code I was looking at had the following declarations:

     dcl IXUPD FILE UNBUFFERED KEYED env(vsam);
     dcl
        01 recArea,
            03 recPrefix,
                05 recID        PIC'(4)9' init (0),
                05 recKeyC      CHAR (4)  init (' '),
            03 recordData       CHAR (70) init (' ');

     dcl recIndx FIXED BIN(31) INITIAL(0);

     dcl keyListSize fixed bin(31) initial(10);
     dcl keyList(10) char(8);

As a C++ programmer, there are a few of oddities here:

  • Options for the FILE are specified at the file declaration point (or can be), not at the OPEN point.  They can also be specified at the OPEN point.  The designers of PL/I seem to have been guided by the general principle of “why have one way of doing something, when it can be done in an infinite variety of possible ways”.
  • There is a hybrid “structure & variable” declaration above.  recArea is like an object of an unnamed structure, containing nested parts (with lots of ugly COBOL like nesting specifications to show the depth of the various “structure” members).  It’s something like the following struct declaration (with c++11 default initializer specifiers):
    #include <stdio.h>
    
    int main() {
        struct {
            struct {
                char recID[4]{'0', '0', '0', '0'};
                char recKeyC[4]{' ', ' ', ' ', ' '};
            } recPrefix;
            char recordData[70]{ ' ', ' ', /* ... 70 spaces total */ };
        } recArea;
    
        printf( "recID: %.4s\n", recArea.recPrefix.recID );
        printf( "recKeyC: '%.4s'\n", recArea.recPrefix.recKeyC );
    
        return 0;
    }
    

    To PL/I’s credit, only ~45 years after the creation of PL/1 did C++ add a simple way of encoding default structure member initializers.

    We’ll see below that PL/I lets you access the inner members without any qualification if desired (i.e. recID == recArea.recPrefix.recId). The PL/I compiler writer is basically faced with the unenviable task of continually trying to guess what the programmer could have possibly meant.

  • The int32_t types have the annoying “mainframe”ism of being referred to as 31-bit integers (FIXED BIN(31)). Even if the high bit in pointers is ignored by the hardware (allowing the programmer to set 0x80000000 as a flag, for example for end of list in a list of pointers), that doesn’t mean that the registers aren’t fully 32-bit, nor does it mean that a 32-bit integer isn’t representable. I can’t for the life of me understand why a 32-bit integer variable should be declared as FIXED BINARY(31)?
  • The recID variable is declared with a PICTURE specification, as we also saw in COBOL code. PIC ‘9999’ (or PIC'(4)9′, for “short”), means that the character array will have four (EBCDIC) digits in it. I don’t quite understand this specification in this case, since the code (to follow) seems to put ‘RNNN’, where N is a digit in this field.

Here’s how the declarations above are used:

    
     keyList(1) = 'R001';
     keyList(2) = 'R002';
...
     OPEN FILE(IXUPD) OUTPUT;

     put skip list ('====== Write record to file by key.');
     do while (recIndx &lt; keyListSize);
        recIndx = recIndx + 1;
        recID = recIndx;
        recKeyC = 'Abcd';
        recordData = 'Data for ' || keyList(recIndx);
        write FILE(IXUPD) FROM(recArea) KEYFROM(keyList(recIndx));
     end;
     put skip list (recIndx, ' records is written to file by key.');

     CLOSE FILE(IXUPD);

My guess about what this ‘WRITE FROM(recArea)’ would do is to create records of the form:

0001AbcdData for R001
0002AbcdData for R002
0003AbcdData for R003
...

However, the VSAM DATASET (which was created with key offset 0, and key size 8), actually ends up with:

R001    Data for R001
R002    Data for R002
R003    Data for R003
...

Despite the fact that we are writing from recArea, which includes the recID and recKeyC fields (numeric and character respectively), only the non-key portion of the WRITE “data payload” ends up hitting the disk.

If that is the case, where do the spaces in the key-portion of the records come from? Again, the C programmer in me is interfering with my understanding. I look at:

dcl keyList(10) char(8);
keyList(1) = 'R001';

and think that keyList(1) = “R001\x00\x00\x00\x00”, but it must actually be space filled in PL/I! This seems to be confirmed emperically, based on the expected results for the test, but I can also see it in the debugger after manually relocating the 32-bit mainframe address:

(gdb) p keyLen
$1 = 8
(gdb) p /x aKey + 0x7ffbc4000000
$2 = 0x7ffbc5005740
(gdb) set target-charset EBCDIC-US
(gdb) p (char *)$2
$3 = 0x7ffbc5005740 "R001    R002    R003    R004    R005    R006    R007    R008    R009    R010    "

The final form of the records in the VSAM DATASET (mainframe for a file), is now fully understood. Note that the data disagrees with the PICTURE specification for the recID field in the recData variable declaration, but that’s okay, at least for this part of the program, since there is never any store to that field that is non-numeric. Would anything even have to have been written to recID or recKeyC … I suspect not? Once we have R00N in that part of the record what happens if we read it into recData with the numeric only PICTURE specification? Does that raise a PL/1 condition?

ps. Notice how the payload for the keyList array entries is nicely packed into memory. This is done in a very non-C like fashion with no requirement for an array of pointers and the corresponding cache hit loss those pointers create when accessing a big multilevel C array.

Still amused reading my PL/1 book: external storage.

May 28, 2017 Mainframe No comments , , , ,

The z/OS Enterprise PL/I, Language Reference is the primary reference I have been using for the PL/1 that I’ve had to learn, but it is too modern, and not nearly as fun as the 1970’s era “PL/I structured programming book” I’ve got:

 

I’m not sure what a disk pack is, but I presume it is a predecessor to the hard drive.

Edit: Art Kaufmann, who I worked with at IBM, knew what a disk pack was (picture above from wikipedia):

“Back in the day, disk drives used removable media called “disk packs.” These were stacks of disks (usually about 2′ across) on a spindle with a plastic cover. See the IBM 2311 and 2314 for examples of these drives. You’d open the drive, lower the pack into place, twist the handle and remove the cover, then close the drive. The big risk was getting dust in when the cover was off; that would cause a head crash. Then some nitwit operator would either put a different disk pack in that drive (ruining that pack) or move the bad pack to a new drive, crashing that one. Or both.”

 

 

 

 

LLVM IR Null pointer constants and function pointers. A wild goose chase after a bad assumption.

March 30, 2017 clang/llvm No comments , , , , , ,

With ELLCC, you can easily check out the LLVM IR for code like:

typedef void ( *f )( void );
void foo( void );

f bar() {
    return (f)foo;
}

That code is:

define nonnull void ()* @bar() local_unnamed_addr {
  ret void ()* @foo
}

declare void @foo()

I was trying to use @foo in a “struct” object, and was getting an error attempting this:

llvm/lib/IR/Constants.cpp:879:llvm::ConstantAggregate::ConstantAggregate(
 llvm::CompositeType*, llvm::Value::ValueTy, llvm::ArrayRef<llvm::Constant*>):
 Assertion `V[I]->getType() == T->getTypeAtIndex(I) &&
 "Initializer for composite element doesn't match!"' failed.

After adding:

fooFunc->dump();

where it shows the whole function body of foo(), I thought that’s where the error was coming from, and that I needed some other method to obtain just “@foo”, a global variable reference to the function, and not the function body itself.

The actual story is much simpler. Here the LLVM code to generate the IR for a foo() with this interface:

//------------
// void foo(){ }
//
auto vt = m_builder.getVoidTy();
auto voidFuncVoidType = FunctionType::get( vt, false /* varargs */ );

Function *fooFunc = Function::Create(
    voidFuncVoidType, Function::InternalLinkage, "foo",
    m_module );
BasicBlock *fooBB =
    BasicBlock::Create( m_context, "", fooFunc );
m_builder.SetInsertPoint( fooBB );
m_builder.CreateRetVoid();

My clue that the error is something else is that I am able to build a function that returns a foo function pointer:

//------------
// void(*)() bar() { return foo ; }
//
auto fpRetFuncType = FunctionType::get( voidFuncVoidType->getPointerTo(), false /* varargs */ );

Function *barFunc = Function::Create(
    fpRetFuncType, Function::ExternalLinkage, "bar",
    m_module );
BasicBlock *barBB =
    BasicBlock::Create( m_context, "", barFunc );
m_builder.SetInsertPoint( barBB );
m_builder.CreateRet( fooFunc );

The module at this point looks like:

define internal void @foo() {
   ret void
}

define void ()* @bar() {
   ret void ()* @foo
}

So why can I used fooFunc in a return statement, but don’t appear to be able to use it in a structure object? Here’s the code that created that structure type

//------------
//
// struct { int, void (*)(), char * }
auto i8t = m_builder.getInt8Ty();
auto i32t = m_builder.getInt32Ty();
std::vector<Type *> consStructMembers{
    i32t, voidFuncVoidType->getPointerTo(), i8t->getPointerTo()};
auto consStructType =
    StructType::create( m_context, consStructMembers, "" );

and my attempt to populate an object of this type:

//
// %struct { int, void (*)(), char * } = { 65535, foo, null };
//
auto consPriority = ConstantInt::get( i32t, 65535 );
auto consDataZero = ConstantInt::get( i8t->getPointerTo(), 0 );

std::vector<Constant *> v{consPriority, fooFunc, consDataZero};
Constant *g = ConstantStruct::get( consStructType, v );

The actual error was in the third struct member initialization, and had nothing to do with the function pointer value. In retrospect, this makes sense since llvm::Function is derived from llvm::Constant, so there shouldn’t logically be a mismatch there.

What actually fixed the error was simply:

auto consDataZero = ConstantPointerNull::get( i8t->getPointerTo() );

It appears that the numeric zero value isn’t the same thing as an LLVM ‘null’. With that corrected, my variable declaration is:

%"type 0x10ea0c0" { i32 65535, void ()* @foo, i8* null }

… so I should now be able to proceed with the actual task at hand.